Merge "Remove the implementation of libaapt2_jni in build file"
diff --git a/Android.bp b/Android.bp
index 0c1095d..e1cb037 100644
--- a/Android.bp
+++ b/Android.bp
@@ -297,6 +297,7 @@
srcs: [
":framework-non-updatable-sources",
"core/java/**/*.logtags",
+ ":apex-info-list",
],
aidl: {
generate_get_transaction_name: true,
diff --git a/ApiDocs.bp b/ApiDocs.bp
index 1e5ae7b..82759f7 100644
--- a/ApiDocs.bp
+++ b/ApiDocs.bp
@@ -112,7 +112,6 @@
}
// Defaults module for doc-stubs targets that use module source code as input.
-// This is the default/normal.
stubs_defaults {
name: "framework-doc-stubs-sources-default",
defaults: ["framework-doc-stubs-default"],
@@ -148,12 +147,6 @@
}
droidstubs {
- name: "framework-doc-stubs",
- defaults: ["framework-doc-stubs-sources-default"],
- args: metalava_framework_docs_args,
-}
-
-droidstubs {
name: "framework-doc-system-stubs",
defaults: ["framework-doc-stubs-sources-default"],
args: metalava_framework_docs_args +
@@ -161,11 +154,8 @@
api_levels_sdk_type: "system",
}
-// Experimental target building doc stubs with module stub source code as input.
-// This is intended to eventually replace framework-doc-stubs, once all diffs
-// have been eliminated.
droidstubs {
- name: "framework-doc-stubs-module-stubs",
+ name: "framework-doc-stubs",
defaults: ["framework-doc-stubs-default"],
args: metalava_framework_docs_args,
srcs: [
diff --git a/PACKAGE_MANAGER_OWNERS b/PACKAGE_MANAGER_OWNERS
new file mode 100644
index 0000000..e4549b4
--- /dev/null
+++ b/PACKAGE_MANAGER_OWNERS
@@ -0,0 +1,3 @@
+chiuwinson@google.com
+patb@google.com
+schfan@google.com
\ No newline at end of file
diff --git a/apct-tests/perftests/inputmethod/AndroidManifest.xml b/apct-tests/perftests/inputmethod/AndroidManifest.xml
index 1fb0b88..3eea418 100644
--- a/apct-tests/perftests/inputmethod/AndroidManifest.xml
+++ b/apct-tests/perftests/inputmethod/AndroidManifest.xml
@@ -16,6 +16,9 @@
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.android.perftests.inputmethod">
+ <uses-permission android:name="android.permission.MANAGE_EXTERNAL_STORAGE" />
+ <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
+
<application>
<uses-library android:name="android.test.runner" />
<activity android:name="android.perftests.utils.PerfTestActivity"
diff --git a/apct-tests/perftests/textclassifier/AndroidManifest.xml b/apct-tests/perftests/textclassifier/AndroidManifest.xml
index 7cf487f..a79f0f1 100644
--- a/apct-tests/perftests/textclassifier/AndroidManifest.xml
+++ b/apct-tests/perftests/textclassifier/AndroidManifest.xml
@@ -16,6 +16,9 @@
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.android.perftests.textclassifier">
+ <uses-permission android:name="android.permission.MANAGE_EXTERNAL_STORAGE" />
+ <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
+
<application>
<uses-library android:name="android.test.runner" />
</application>
diff --git a/apex/jobscheduler/service/java/com/android/server/tare/Agent.java b/apex/jobscheduler/service/java/com/android/server/tare/Agent.java
index 035c9d2..b2e95a5 100644
--- a/apex/jobscheduler/service/java/com/android/server/tare/Agent.java
+++ b/apex/jobscheduler/service/java/com/android/server/tare/Agent.java
@@ -16,8 +16,6 @@
package com.android.server.tare;
-import static android.text.format.DateUtils.HOUR_IN_MILLIS;
-
import static com.android.server.tare.EconomicPolicy.REGULATION_BASIC_INCOME;
import static com.android.server.tare.EconomicPolicy.REGULATION_BIRTHRIGHT;
import static com.android.server.tare.EconomicPolicy.REGULATION_WEALTH_RECLAMATION;
@@ -69,12 +67,6 @@
private static final boolean DEBUG = InternalResourceService.DEBUG
|| Log.isLoggable(TAG, Log.DEBUG);
- /**
- * The minimum amount of time an app must not have been used by the user before we start
- * regularly reclaiming ARCs from it.
- */
- private static final long MIN_UNUSED_TIME_MS = 3 * 24 * HOUR_IN_MILLIS;
-
private static final String ALARM_TAG_AFFORDABILITY_CHECK = "*tare.affordability_check*";
private final Object mLock;
@@ -550,41 +542,62 @@
/**
* Reclaim a percentage of unused ARCs from every app that hasn't been used recently. The
- * reclamation will not reduce an app's balance below its minimum balance as dictated by the
- * EconomicPolicy.
+ * reclamation will not reduce an app's balance below its minimum balance as dictated by
+ * {@code scaleMinBalance}.
*
- * @param percentage A value between 0 and 1 to indicate how much of the unused balance should
- * be reclaimed.
+ * @param percentage A value between 0 and 1 to indicate how much of the unused balance
+ * should be reclaimed.
+ * @param minUnusedTimeMs The minimum amount of time (in milliseconds) that must have
+ * transpired since the last user usage event before we will consider
+ * reclaiming ARCs from the app.
+ * @param scaleMinBalance Whether or not to used the scaled minimum app balance. If false,
+ * this will use the constant min balance floor given by
+ * {@link EconomicPolicy#getMinSatiatedBalance(int, String)}. If true,
+ * this will use the scaled balance given by
+ * {@link InternalResourceService#getMinBalanceLocked(int, String)}.
*/
@GuardedBy("mLock")
- void reclaimUnusedAssetsLocked(double percentage) {
+ void reclaimUnusedAssetsLocked(double percentage, long minUnusedTimeMs,
+ boolean scaleMinBalance) {
final CompleteEconomicPolicy economicPolicy = mIrs.getCompleteEconomicPolicyLocked();
- final List<PackageInfo> pkgs = mIrs.getInstalledPackages();
+ final SparseArrayMap<String, Ledger> ledgers = mScribe.getLedgersLocked();
final long now = getCurrentTimeMillis();
- for (int i = 0; i < pkgs.size(); ++i) {
- final int userId = UserHandle.getUserId(pkgs.get(i).applicationInfo.uid);
- final String pkgName = pkgs.get(i).packageName;
- final Ledger ledger = mScribe.getLedgerLocked(userId, pkgName);
- // AppStandby only counts elapsed time for things like this
- // TODO: should we use clock time instead?
- final long timeSinceLastUsedMs =
- mAppStandbyInternal.getTimeSinceLastUsedByUser(pkgName, userId);
- if (timeSinceLastUsedMs >= MIN_UNUSED_TIME_MS) {
- // Use a constant floor instead of the scaled floor from the IRS.
- final long minBalance = economicPolicy.getMinSatiatedBalance(userId, pkgName);
+ for (int u = 0; u < ledgers.numMaps(); ++u) {
+ final int userId = ledgers.keyAt(u);
+ for (int p = 0; p < ledgers.numElementsForKey(userId); ++p) {
+ final Ledger ledger = ledgers.valueAt(u, p);
final long curBalance = ledger.getCurrentBalance();
- long toReclaim = (long) (curBalance * percentage);
- if (curBalance - toReclaim < minBalance) {
- toReclaim = curBalance - minBalance;
+ if (curBalance <= 0) {
+ continue;
}
- if (toReclaim > 0) {
- Slog.i(TAG, "Reclaiming unused wealth! Taking " + toReclaim
- + " from " + appToString(userId, pkgName));
+ final String pkgName = ledgers.keyAt(u, p);
+ // AppStandby only counts elapsed time for things like this
+ // TODO: should we use clock time instead?
+ final long timeSinceLastUsedMs =
+ mAppStandbyInternal.getTimeSinceLastUsedByUser(pkgName, userId);
+ if (timeSinceLastUsedMs >= minUnusedTimeMs) {
+ final long minBalance;
+ if (!scaleMinBalance) {
+ // Use a constant floor instead of the scaled floor from the IRS.
+ minBalance = economicPolicy.getMinSatiatedBalance(userId, pkgName);
+ } else {
+ minBalance = mIrs.getMinBalanceLocked(userId, pkgName);
+ }
+ long toReclaim = (long) (curBalance * percentage);
+ if (curBalance - toReclaim < minBalance) {
+ toReclaim = curBalance - minBalance;
+ }
+ if (toReclaim > 0) {
+ if (DEBUG) {
+ Slog.i(TAG, "Reclaiming unused wealth! Taking " + toReclaim
+ + " from " + appToString(userId, pkgName));
+ }
- recordTransactionLocked(userId, pkgName, ledger,
- new Ledger.Transaction(
- now, now, REGULATION_WEALTH_RECLAMATION, null, -toReclaim),
- true);
+ recordTransactionLocked(userId, pkgName, ledger,
+ new Ledger.Transaction(
+ now, now, REGULATION_WEALTH_RECLAMATION, null, -toReclaim),
+ true);
+ }
}
}
}
diff --git a/apex/jobscheduler/service/java/com/android/server/tare/InternalResourceService.java b/apex/jobscheduler/service/java/com/android/server/tare/InternalResourceService.java
index a39fd47..1ad7407 100644
--- a/apex/jobscheduler/service/java/com/android/server/tare/InternalResourceService.java
+++ b/apex/jobscheduler/service/java/com/android/server/tare/InternalResourceService.java
@@ -18,6 +18,7 @@
import static android.provider.Settings.Global.TARE_ALARM_MANAGER_CONSTANTS;
import static android.provider.Settings.Global.TARE_JOB_SCHEDULER_CONSTANTS;
+import static android.text.format.DateUtils.DAY_IN_MILLIS;
import static android.text.format.DateUtils.HOUR_IN_MILLIS;
import static android.text.format.DateUtils.MINUTE_IN_MILLIS;
@@ -85,6 +86,11 @@
static final long UNUSED_RECLAMATION_PERIOD_MS = 24 * HOUR_IN_MILLIS;
/** How much of an app's unused wealth should be reclaimed periodically. */
private static final float DEFAULT_UNUSED_RECLAMATION_PERCENTAGE = .1f;
+ /**
+ * The minimum amount of time an app must not have been used by the user before we start
+ * periodically reclaiming ARCs from it.
+ */
+ private static final long MIN_UNUSED_TIME_MS = 3 * DAY_IN_MILLIS;
/** The amount of time to delay reclamation by after boot. */
private static final long RECLAMATION_STARTUP_DELAY_MS = 30_000L;
private static final int PACKAGE_QUERY_FLAGS =
@@ -107,6 +113,44 @@
@GuardedBy("mLock")
private CompleteEconomicPolicy mCompleteEconomicPolicy;
+ private static final class ReclamationConfig {
+ /**
+ * ARC circulation threshold (% circulating vs scaled maximum) above which this config
+ * should come into play.
+ */
+ public final double circulationPercentageThreshold;
+ /** @see Agent#reclaimUnusedAssetsLocked(double, long, boolean) */
+ public final double reclamationPercentage;
+ /** @see Agent#reclaimUnusedAssetsLocked(double, long, boolean) */
+ public final long minUsedTimeMs;
+ /** @see Agent#reclaimUnusedAssetsLocked(double, long, boolean) */
+ public final boolean scaleMinBalance;
+
+ ReclamationConfig(double circulationPercentageThreshold, double reclamationPercentage,
+ long minUsedTimeMs, boolean scaleMinBalance) {
+ this.circulationPercentageThreshold = circulationPercentageThreshold;
+ this.reclamationPercentage = reclamationPercentage;
+ this.minUsedTimeMs = minUsedTimeMs;
+ this.scaleMinBalance = scaleMinBalance;
+ }
+ }
+
+ /**
+ * Sorted list of reclamation configs used to determine how many credits to force reclaim when
+ * the circulation percentage is too high. The list should *always* be sorted in descending
+ * order of {@link ReclamationConfig#circulationPercentageThreshold}.
+ */
+ @GuardedBy("mLock")
+ private final List<ReclamationConfig> mReclamationConfigs = List.of(
+ new ReclamationConfig(2, .75, 12 * HOUR_IN_MILLIS, true),
+ new ReclamationConfig(1.6, .5, DAY_IN_MILLIS, true),
+ new ReclamationConfig(1.4, .25, DAY_IN_MILLIS, true),
+ new ReclamationConfig(1.2, .25, 2 * DAY_IN_MILLIS, true),
+ new ReclamationConfig(1, .25, MIN_UNUSED_TIME_MS, false),
+ new ReclamationConfig(
+ .9, DEFAULT_UNUSED_RECLAMATION_PERCENTAGE, MIN_UNUSED_TIME_MS, false)
+ );
+
@NonNull
@GuardedBy("mLock")
private final List<PackageInfo> mPkgCache = new ArrayList<>();
@@ -190,7 +234,8 @@
@Override
public void onAlarm() {
synchronized (mLock) {
- mAgent.reclaimUnusedAssetsLocked(DEFAULT_UNUSED_RECLAMATION_PERCENTAGE);
+ mAgent.reclaimUnusedAssetsLocked(
+ DEFAULT_UNUSED_RECLAMATION_PERCENTAGE, MIN_UNUSED_TIME_MS, false);
mScribe.setLastReclamationTimeLocked(getCurrentTimeMillis());
scheduleUnusedWealthReclamationLocked();
}
@@ -200,6 +245,7 @@
private static final int MSG_NOTIFY_AFFORDABILITY_CHANGE_LISTENER = 0;
private static final int MSG_SCHEDULE_UNUSED_WEALTH_RECLAMATION_EVENT = 1;
private static final int MSG_PROCESS_USAGE_EVENT = 2;
+ private static final int MSG_MAYBE_FOCE_RECLAIM = 3;
private static final String ALARM_TAG_WEALTH_RECLAMATION = "*tare.reclamation*";
private static final String KEY_PKG = "pkg";
@@ -317,6 +363,8 @@
final int newBatteryLevel = getCurrentBatteryLevel();
if (newBatteryLevel > mCurrentBatteryLevel) {
mAgent.distributeBasicIncomeLocked(newBatteryLevel);
+ } else if (newBatteryLevel < mCurrentBatteryLevel) {
+ mHandler.obtainMessage(MSG_MAYBE_FOCE_RECLAIM).sendToTarget();
}
mCurrentBatteryLevel = newBatteryLevel;
}
@@ -511,6 +559,48 @@
}
}
+ /**
+ * Reclaim unused ARCs above apps' minimum balances if there are too many credits currently
+ * in circulation.
+ */
+ @GuardedBy("mLock")
+ private void maybeForceReclaimLocked() {
+ final long maxCirculation = getMaxCirculationLocked();
+ if (maxCirculation == 0) {
+ Slog.wtf(TAG, "Max scaled circulation is 0...");
+ mAgent.reclaimUnusedAssetsLocked(1, HOUR_IN_MILLIS, true);
+ mScribe.setLastReclamationTimeLocked(getCurrentTimeMillis());
+ scheduleUnusedWealthReclamationLocked();
+ return;
+ }
+ final long curCirculation = mScribe.getNarcsInCirculationLocked();
+ final double circulationPerc = 1.0 * curCirculation / maxCirculation;
+ if (DEBUG) {
+ Slog.d(TAG, "Circulation %: " + circulationPerc);
+ }
+ final int numConfigs = mReclamationConfigs.size();
+ if (numConfigs == 0) {
+ return;
+ }
+ // The configs are sorted in descending order of circulationPercentageThreshold, so we can
+ // short-circuit if the current circulation is lower than the lowest threshold.
+ if (circulationPerc
+ < mReclamationConfigs.get(numConfigs - 1).circulationPercentageThreshold) {
+ return;
+ }
+ // TODO: maybe exclude apps we think will be launched in the next few hours
+ for (int i = 0; i < numConfigs; ++i) {
+ final ReclamationConfig config = mReclamationConfigs.get(i);
+ if (circulationPerc >= config.circulationPercentageThreshold) {
+ mAgent.reclaimUnusedAssetsLocked(
+ config.reclamationPercentage, config.minUsedTimeMs, config.scaleMinBalance);
+ mScribe.setLastReclamationTimeLocked(getCurrentTimeMillis());
+ scheduleUnusedWealthReclamationLocked();
+ break;
+ }
+ }
+ }
+
private void registerListeners() {
final IntentFilter filter = new IntentFilter();
filter.addAction(Intent.ACTION_BATTERY_LEVEL_CHANGED);
@@ -594,6 +684,14 @@
@Override
public void handleMessage(Message msg) {
switch (msg.what) {
+ case MSG_MAYBE_FOCE_RECLAIM: {
+ removeMessages(MSG_MAYBE_FOCE_RECLAIM);
+ synchronized (mLock) {
+ maybeForceReclaimLocked();
+ }
+ }
+ break;
+
case MSG_NOTIFY_AFFORDABILITY_CHANGE_LISTENER: {
Bundle data = msg.getData();
final int userId = msg.arg1;
diff --git a/apex/jobscheduler/service/java/com/android/server/tare/Scribe.java b/apex/jobscheduler/service/java/com/android/server/tare/Scribe.java
index d4c6c8c..42f3d9a 100644
--- a/apex/jobscheduler/service/java/com/android/server/tare/Scribe.java
+++ b/apex/jobscheduler/service/java/com/android/server/tare/Scribe.java
@@ -147,6 +147,12 @@
return ledger;
}
+ @GuardedBy("mIrs.getLock()")
+ @NonNull
+ SparseArrayMap<String, Ledger> getLedgersLocked() {
+ return mLedgers;
+ }
+
/** Returns the total amount of narcs currently allocated to apps. */
@GuardedBy("mIrs.getLock()")
long getNarcsInCirculationLocked() {
diff --git a/apex/media/framework/java/android/media/BaseMediaParceledListSlice.java b/apex/media/framework/java/android/media/BaseMediaParceledListSlice.java
index fb66609..915f3f6a3 100644
--- a/apex/media/framework/java/android/media/BaseMediaParceledListSlice.java
+++ b/apex/media/framework/java/android/media/BaseMediaParceledListSlice.java
@@ -43,7 +43,7 @@
*/
abstract class BaseMediaParceledListSlice<T> implements Parcelable {
private static String TAG = "BaseMediaParceledListSlice";
- private static boolean DEBUG = false;
+ private static final boolean DEBUG = false;
/*
* TODO get this number from somewhere else. For now set it to a quarter of
diff --git a/cmds/am/src/com/android/commands/am/Am.java b/cmds/am/src/com/android/commands/am/Am.java
index 4e46aa3..9564dde 100644
--- a/cmds/am/src/com/android/commands/am/Am.java
+++ b/cmds/am/src/com/android/commands/am/Am.java
@@ -41,6 +41,10 @@
private IActivityManager mAm;
private IPackageManager mPm;
+ Am() {
+ svcInit();
+ }
+
/**
* Command-line entry point.
*
@@ -50,6 +54,20 @@
(new Am()).run(args);
}
+ private void svcInit() {
+ mAm = ActivityManager.getService();
+ if (mAm == null) {
+ System.err.println(NO_SYSTEM_ERROR_CODE);
+ return;
+ }
+
+ mPm = IPackageManager.Stub.asInterface(ServiceManager.getService("package"));
+ if (mPm == null) {
+ System.err.println(NO_SYSTEM_ERROR_CODE);
+ return;
+ }
+ }
+
@Override
public void onShowUsage(PrintStream out) {
try {
@@ -61,19 +79,6 @@
@Override
public void onRun() throws Exception {
-
- mAm = ActivityManager.getService();
- if (mAm == null) {
- System.err.println(NO_SYSTEM_ERROR_CODE);
- throw new AndroidException("Can't connect to activity manager; is the system running?");
- }
-
- mPm = IPackageManager.Stub.asInterface(ServiceManager.getService("package"));
- if (mPm == null) {
- System.err.println(NO_SYSTEM_ERROR_CODE);
- throw new AndroidException("Can't connect to package manager; is the system running?");
- }
-
String op = nextArgRequired();
if (op.equals("instrument")) {
diff --git a/core/api/current.txt b/core/api/current.txt
index f989d06..d283e0a 100644
--- a/core/api/current.txt
+++ b/core/api/current.txt
@@ -8684,12 +8684,14 @@
method public android.bluetooth.BluetoothDevice getRemoteDevice(byte[]);
method @RequiresPermission(android.Manifest.permission.BLUETOOTH_SCAN) public int getScanMode();
method public int getState();
+ method public int isCisCentralSupported();
method @RequiresPermission(android.Manifest.permission.BLUETOOTH_SCAN) public boolean isDiscovering();
method public boolean isEnabled();
method public boolean isLe2MPhySupported();
method public boolean isLeCodedPhySupported();
method public boolean isLeExtendedAdvertisingSupported();
method public boolean isLePeriodicAdvertisingSupported();
+ method public int isLePeriodicAdvertisingSyncTransferSenderSupported();
method public boolean isMultipleAdvertisementSupported();
method public boolean isOffloadedFilteringSupported();
method public boolean isOffloadedScanBatchingSupported();
@@ -9542,6 +9544,7 @@
field public static final int ERROR_BLUETOOTH_NOT_ALLOWED = 2; // 0x2
field public static final int ERROR_BLUETOOTH_NOT_ENABLED = 1; // 0x1
field public static final int ERROR_DEVICE_NOT_BONDED = 3; // 0x3
+ field public static final int ERROR_FEATURE_NOT_SUPPORTED = 8; // 0x8
field public static final int ERROR_MISSING_BLUETOOTH_CONNECT_PERMISSION = 6; // 0x6
field public static final int ERROR_UNKNOWN = 2147483647; // 0x7fffffff
field public static final int SUCCESS = 0; // 0x0
@@ -10745,6 +10748,7 @@
field public static final String TELEPHONY_SUBSCRIPTION_SERVICE = "telephony_subscription_service";
field public static final String TEXT_CLASSIFICATION_SERVICE = "textclassification";
field public static final String TEXT_SERVICES_MANAGER_SERVICE = "textservices";
+ field public static final String TV_IAPP_SERVICE = "tv_iapp";
field public static final String TV_INPUT_SERVICE = "tv_input";
field public static final String UI_MODE_SERVICE = "uimode";
field public static final String USAGE_STATS_SERVICE = "usagestats";
@@ -18159,8 +18163,9 @@
method @NonNull public java.util.List<android.util.Size> getExtensionSupportedSizes(int, int);
method @NonNull public java.util.List<java.lang.Integer> getSupportedExtensions();
field public static final int EXTENSION_AUTOMATIC = 0; // 0x0
- field public static final int EXTENSION_BEAUTY = 1; // 0x1
+ field @Deprecated public static final int EXTENSION_BEAUTY = 1; // 0x1
field public static final int EXTENSION_BOKEH = 2; // 0x2
+ field public static final int EXTENSION_FACE_RETOUCH = 1; // 0x1
field public static final int EXTENSION_HDR = 3; // 0x3
field public static final int EXTENSION_NIGHT = 4; // 0x4
}
@@ -22672,7 +22677,7 @@
field public static final String KEY_MAX_FPS_TO_ENCODER = "max-fps-to-encoder";
field public static final String KEY_MAX_HEIGHT = "max-height";
field public static final String KEY_MAX_INPUT_SIZE = "max-input-size";
- field public static final String KEY_MAX_OUTPUT_CHANNEL_COUNT = "max-output-channel_count";
+ field public static final String KEY_MAX_OUTPUT_CHANNEL_COUNT = "max-output-channel-count";
field public static final String KEY_MAX_PTS_GAP_TO_ENCODER = "max-pts-gap-to-encoder";
field public static final String KEY_MAX_WIDTH = "max-width";
field public static final String KEY_MIME = "mime";
@@ -26241,6 +26246,13 @@
}
+package android.media.tv.interactive {
+
+ public final class TvIAppManager {
+ }
+
+}
+
package android.mtp {
public final class MtpConstants {
@@ -30975,6 +30987,7 @@
field public static final int Q = 29; // 0x1d
field public static final int R = 30; // 0x1e
field public static final int S = 31; // 0x1f
+ field public static final int S_V2 = 32; // 0x20
field public static final int TIRAMISU = 10000; // 0x2710
}
@@ -31589,7 +31602,9 @@
method @NonNull public static android.os.Parcel obtain();
method @NonNull public static android.os.Parcel obtain(@NonNull android.os.IBinder);
method @Nullable public Object[] readArray(@Nullable ClassLoader);
+ method @Nullable public <T> T[] readArray(@Nullable ClassLoader, @NonNull Class<T>);
method @Nullable public java.util.ArrayList readArrayList(@Nullable ClassLoader);
+ method @Nullable public <T> java.util.ArrayList<T> readArrayList(@Nullable ClassLoader, @NonNull Class<? extends T>);
method public void readBinderArray(@NonNull android.os.IBinder[]);
method public void readBinderList(@NonNull java.util.List<android.os.IBinder>);
method public boolean readBoolean();
@@ -31617,6 +31632,7 @@
method @Nullable public <T extends android.os.Parcelable> T readParcelable(@Nullable ClassLoader);
method @Nullable public <T extends android.os.Parcelable> T readParcelable(@Nullable ClassLoader, @NonNull Class<T>);
method @Nullable public android.os.Parcelable[] readParcelableArray(@Nullable ClassLoader);
+ method @Nullable public <T> T[] readParcelableArray(@Nullable ClassLoader, @NonNull Class<T>);
method @Nullable public android.os.Parcelable.Creator<?> readParcelableCreator(@Nullable ClassLoader);
method @Nullable public <T> android.os.Parcelable.Creator<T> readParcelableCreator(@Nullable ClassLoader, @NonNull Class<T>);
method @NonNull public <T extends android.os.Parcelable> java.util.List<T> readParcelableList(@NonNull java.util.List<T>, @Nullable ClassLoader);
@@ -31626,6 +31642,7 @@
method @NonNull public android.util.Size readSize();
method @NonNull public android.util.SizeF readSizeF();
method @Nullable public <T> android.util.SparseArray<T> readSparseArray(@Nullable ClassLoader);
+ method @Nullable public <T> android.util.SparseArray<T> readSparseArray(@Nullable ClassLoader, @NonNull Class<? extends T>);
method @Nullable public android.util.SparseBooleanArray readSparseBooleanArray();
method @Nullable public String readString();
method public void readStringArray(@NonNull String[]);
@@ -47696,6 +47713,10 @@
field public static final int KEYCODE_CUT = 277; // 0x115
field public static final int KEYCODE_D = 32; // 0x20
field public static final int KEYCODE_DEL = 67; // 0x43
+ field public static final int KEYCODE_DEMO_APP_1 = 301; // 0x12d
+ field public static final int KEYCODE_DEMO_APP_2 = 302; // 0x12e
+ field public static final int KEYCODE_DEMO_APP_3 = 303; // 0x12f
+ field public static final int KEYCODE_DEMO_APP_4 = 304; // 0x130
field public static final int KEYCODE_DPAD_CENTER = 23; // 0x17
field public static final int KEYCODE_DPAD_DOWN = 20; // 0x14
field public static final int KEYCODE_DPAD_DOWN_LEFT = 269; // 0x10d
@@ -47727,6 +47748,10 @@
field public static final int KEYCODE_F7 = 137; // 0x89
field public static final int KEYCODE_F8 = 138; // 0x8a
field public static final int KEYCODE_F9 = 139; // 0x8b
+ field public static final int KEYCODE_FEATURED_APP_1 = 297; // 0x129
+ field public static final int KEYCODE_FEATURED_APP_2 = 298; // 0x12a
+ field public static final int KEYCODE_FEATURED_APP_3 = 299; // 0x12b
+ field public static final int KEYCODE_FEATURED_APP_4 = 300; // 0x12c
field public static final int KEYCODE_FOCUS = 80; // 0x50
field public static final int KEYCODE_FORWARD = 125; // 0x7d
field public static final int KEYCODE_FORWARD_DEL = 112; // 0x70
@@ -47892,6 +47917,14 @@
field public static final int KEYCODE_U = 49; // 0x31
field public static final int KEYCODE_UNKNOWN = 0; // 0x0
field public static final int KEYCODE_V = 50; // 0x32
+ field public static final int KEYCODE_VIDEO_APP_1 = 289; // 0x121
+ field public static final int KEYCODE_VIDEO_APP_2 = 290; // 0x122
+ field public static final int KEYCODE_VIDEO_APP_3 = 291; // 0x123
+ field public static final int KEYCODE_VIDEO_APP_4 = 292; // 0x124
+ field public static final int KEYCODE_VIDEO_APP_5 = 293; // 0x125
+ field public static final int KEYCODE_VIDEO_APP_6 = 294; // 0x126
+ field public static final int KEYCODE_VIDEO_APP_7 = 295; // 0x127
+ field public static final int KEYCODE_VIDEO_APP_8 = 296; // 0x128
field public static final int KEYCODE_VOICE_ASSIST = 231; // 0xe7
field public static final int KEYCODE_VOLUME_DOWN = 25; // 0x19
field public static final int KEYCODE_VOLUME_MUTE = 164; // 0xa4
diff --git a/core/api/system-current.txt b/core/api/system-current.txt
index 599f11d..0fb8bf4 100755
--- a/core/api/system-current.txt
+++ b/core/api/system-current.txt
@@ -20,6 +20,7 @@
field public static final String ACCESS_SURFACE_FLINGER = "android.permission.ACCESS_SURFACE_FLINGER";
field public static final String ACCESS_TUNED_INFO = "android.permission.ACCESS_TUNED_INFO";
field public static final String ACCESS_TV_DESCRAMBLER = "android.permission.ACCESS_TV_DESCRAMBLER";
+ field public static final String ACCESS_TV_SHARED_FILTER = "android.permission.ACCESS_TV_SHARED_FILTER";
field public static final String ACCESS_TV_TUNER = "android.permission.ACCESS_TV_TUNER";
field public static final String ACCESS_VIBRATOR_STATE = "android.permission.ACCESS_VIBRATOR_STATE";
field public static final String ACTIVITY_EMBEDDING = "android.permission.ACTIVITY_EMBEDDING";
@@ -95,6 +96,7 @@
field public static final String CONTROL_OEM_PAID_NETWORK_PREFERENCE = "android.permission.CONTROL_OEM_PAID_NETWORK_PREFERENCE";
field public static final String CONTROL_VPN = "android.permission.CONTROL_VPN";
field public static final String CREATE_USERS = "android.permission.CREATE_USERS";
+ field public static final String CREATE_VIRTUAL_DEVICE = "android.permission.CREATE_VIRTUAL_DEVICE";
field public static final String CRYPT_KEEPER = "android.permission.CRYPT_KEEPER";
field public static final String DEVICE_POWER = "android.permission.DEVICE_POWER";
field public static final String DISABLE_SYSTEM_SOUND_EFFECTS = "android.permission.DISABLE_SYSTEM_SOUND_EFFECTS";
@@ -382,6 +384,7 @@
field public static final int config_systemNotificationIntelligence = 17039413; // 0x1040035
field public static final int config_systemShell = 17039402; // 0x104002a
field public static final int config_systemSpeechRecognizer = 17039406; // 0x104002e
+ field public static final int config_systemSupervision;
field public static final int config_systemTelevisionNotificationHandler = 17039409; // 0x1040031
field public static final int config_systemTextIntelligence = 17039414; // 0x1040036
field public static final int config_systemUi = 17039418; // 0x104003a
@@ -484,6 +487,8 @@
field public static final String OPSTR_AUTO_REVOKE_PERMISSIONS_IF_UNUSED = "android:auto_revoke_permissions_if_unused";
field public static final String OPSTR_BIND_ACCESSIBILITY_SERVICE = "android:bind_accessibility_service";
field public static final String OPSTR_CHANGE_WIFI_STATE = "android:change_wifi_state";
+ field public static final String OPSTR_ESTABLISH_VPN_MANAGER = "android:establish_vpn_manager";
+ field public static final String OPSTR_ESTABLISH_VPN_SERVICE = "android:establish_vpn_service";
field public static final String OPSTR_GET_ACCOUNTS = "android:get_accounts";
field public static final String OPSTR_GPS = "android:gps";
field public static final String OPSTR_INSTANT_APP_START_FOREGROUND = "android:instant_app_start_foreground";
@@ -1948,6 +1953,22 @@
field @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT) public static final String ACTION_CONNECTION_STATE_CHANGED = "android.bluetooth.a2dp-sink.profile.action.CONNECTION_STATE_CHANGED";
}
+ public final class BluetoothActivityEnergyInfo implements android.os.Parcelable {
+ method public int getBluetoothStackState();
+ method public long getControllerEnergyUsed();
+ method public long getControllerIdleTimeMillis();
+ method public long getControllerRxTimeMillis();
+ method public long getControllerTxTimeMillis();
+ method public long getTimestampMillis();
+ method @NonNull public java.util.List<android.bluetooth.UidTraffic> getUidTraffic();
+ method public boolean isValid();
+ field public static final int BT_STACK_STATE_INVALID = 0; // 0x0
+ field public static final int BT_STACK_STATE_STATE_ACTIVE = 1; // 0x1
+ field public static final int BT_STACK_STATE_STATE_IDLE = 3; // 0x3
+ field public static final int BT_STACK_STATE_STATE_SCANNING = 2; // 0x2
+ field @NonNull public static final android.os.Parcelable.Creator<android.bluetooth.BluetoothActivityEnergyInfo> CREATOR;
+ }
+
public final class BluetoothAdapter {
method @RequiresPermission(allOf={android.Manifest.permission.BLUETOOTH_CONNECT, android.Manifest.permission.BLUETOOTH_PRIVILEGED}) public boolean addOnMetadataChangedListener(@NonNull android.bluetooth.BluetoothDevice, @NonNull java.util.concurrent.Executor, @NonNull android.bluetooth.BluetoothAdapter.OnMetadataChangedListener);
method @RequiresPermission(allOf={android.Manifest.permission.BLUETOOTH_CONNECT, android.Manifest.permission.BLUETOOTH_PRIVILEGED}) public boolean disable(boolean);
@@ -2247,6 +2268,13 @@
method @NonNull public android.bluetooth.OobData.LeBuilder setRandomizerHash(@NonNull byte[]);
}
+ public final class UidTraffic implements java.lang.Cloneable android.os.Parcelable {
+ method public long getRxBytes();
+ method public long getTxBytes();
+ method public int getUid();
+ field @NonNull public static final android.os.Parcelable.Creator<android.bluetooth.UidTraffic> CREATOR;
+ }
+
}
package android.bluetooth.le {
@@ -2310,6 +2338,17 @@
}
+package android.companion.virtual {
+
+ public final class VirtualDeviceManager {
+ }
+
+ public static class VirtualDeviceManager.VirtualDevice implements java.lang.AutoCloseable {
+ method public void close();
+ }
+
+}
+
package android.content {
public class ApexEnvironment {
@@ -6082,7 +6121,7 @@
method @Nullable public android.media.tv.tuner.DemuxCapabilities getDemuxCapabilities();
method @Nullable public android.media.tv.tuner.frontend.FrontendInfo getFrontendInfo();
method @Nullable public android.media.tv.tuner.frontend.FrontendStatus getFrontendStatus(@NonNull int[]);
- method public boolean hasUnusedFrontend(int);
+ method @RequiresPermission("android.permission.TUNER_RESOURCE_ACCESS") public boolean hasUnusedFrontend(int);
method public boolean isLowestPriority(int);
method @Nullable @RequiresPermission(android.Manifest.permission.ACCESS_TV_DESCRAMBLER) public android.media.tv.tuner.Descrambler openDescrambler();
method @Nullable public android.media.tv.tuner.dvr.DvrPlayback openDvrPlayback(long, @NonNull java.util.concurrent.Executor, @NonNull android.media.tv.tuner.dvr.OnPlaybackStatusChangedListener);
@@ -6090,6 +6129,7 @@
method @Nullable public android.media.tv.tuner.filter.Filter openFilter(int, int, long, @Nullable java.util.concurrent.Executor, @Nullable android.media.tv.tuner.filter.FilterCallback);
method @Nullable public android.media.tv.tuner.Lnb openLnb(@NonNull java.util.concurrent.Executor, @NonNull android.media.tv.tuner.LnbCallback);
method @Nullable public android.media.tv.tuner.Lnb openLnbByName(@NonNull String, @NonNull java.util.concurrent.Executor, @NonNull android.media.tv.tuner.LnbCallback);
+ method @Nullable @RequiresPermission(android.Manifest.permission.ACCESS_TV_SHARED_FILTER) public static android.media.tv.tuner.filter.SharedFilter openSharedFilter(@NonNull android.content.Context, @NonNull String, @NonNull java.util.concurrent.Executor, @NonNull android.media.tv.tuner.filter.SharedFilterCallback);
method @Nullable public android.media.tv.tuner.filter.TimeFilter openTimeFilter();
method public int scan(@NonNull android.media.tv.tuner.frontend.FrontendSettings, int, @NonNull java.util.concurrent.Executor, @NonNull android.media.tv.tuner.frontend.ScanCallback);
method public int setLnaEnabled(boolean);
@@ -6097,7 +6137,7 @@
method public void setResourceLostListener(@NonNull java.util.concurrent.Executor, @NonNull android.media.tv.tuner.Tuner.OnResourceLostListener);
method public void shareFrontendFromTuner(@NonNull android.media.tv.tuner.Tuner);
method public int tune(@NonNull android.media.tv.tuner.frontend.FrontendSettings);
- method public void updateResourcePriority(int, int);
+ method @RequiresPermission("android.permission.TUNER_RESOURCE_ACCESS") public void updateResourcePriority(int, int);
field public static final int INVALID_AV_SYNC_ID = -1; // 0xffffffff
field public static final int INVALID_FILTER_ID = -1; // 0xffffffff
field public static final long INVALID_FILTER_ID_LONG = -1L; // 0xffffffffffffffffL
@@ -6298,10 +6338,12 @@
public class Filter implements java.lang.AutoCloseable {
method public void close();
method public int configure(@NonNull android.media.tv.tuner.filter.FilterConfiguration);
+ method @Nullable public String createSharedFilter();
method public int flush();
method @Deprecated public int getId();
method public long getIdLong();
method public int read(@NonNull byte[], long, long);
+ method public void releaseSharedFilter(@NonNull String);
method public int setDataSource(@Nullable android.media.tv.tuner.filter.Filter);
method public int setMonitorEventMask(int);
method public int start();
@@ -6551,6 +6593,20 @@
method public int getType();
}
+ public final class SharedFilter implements java.lang.AutoCloseable {
+ method public void close();
+ method public int flush();
+ method public int read(@NonNull byte[], long, long);
+ method public int start();
+ method public int stop();
+ field public static final int STATUS_INACCESSIBLE = 128; // 0x80
+ }
+
+ public interface SharedFilterCallback {
+ method public void onFilterEvent(@NonNull android.media.tv.tuner.filter.SharedFilter, @NonNull android.media.tv.tuner.filter.FilterEvent[]);
+ method public void onFilterStatusChanged(@NonNull android.media.tv.tuner.filter.SharedFilter, int);
+ }
+
public class TemiEvent extends android.media.tv.tuner.filter.FilterEvent {
method @NonNull public byte[] getDescriptorData();
method public byte getDescriptorTag();
diff --git a/core/api/test-current.txt b/core/api/test-current.txt
index e707b03..72e93f8 100644
--- a/core/api/test-current.txt
+++ b/core/api/test-current.txt
@@ -337,6 +337,7 @@
}
public class StatusBarManager {
+ method public void cancelRequestAddTile(@NonNull String);
method public void clickNotification(@Nullable String, int, int, boolean);
method @RequiresPermission(android.Manifest.permission.STATUS_BAR) public void collapsePanels();
method public void expandNotificationsPanel();
@@ -2785,7 +2786,7 @@
method public static String actionToString(int);
method public final void setDisplayId(int);
field public static final int FLAG_IS_ACCESSIBILITY_EVENT = 2048; // 0x800
- field public static final int LAST_KEYCODE = 288; // 0x120
+ field public static final int LAST_KEYCODE = 304; // 0x130
}
public final class KeyboardShortcutGroup implements android.os.Parcelable {
diff --git a/core/java/android/accessibilityservice/AccessibilityService.java b/core/java/android/accessibilityservice/AccessibilityService.java
index f47995c..61d2b4b 100644
--- a/core/java/android/accessibilityservice/AccessibilityService.java
+++ b/core/java/android/accessibilityservice/AccessibilityService.java
@@ -228,7 +228,7 @@
* <ul>
* <li>{@link AccessibilityServiceInfo#FEEDBACK_AUDIBLE}</li>
* <li>{@link AccessibilityServiceInfo#FEEDBACK_HAPTIC}</li>
- * <li>{@link AccessibilityServiceInfo#FEEDBACK_AUDIBLE}</li>
+ * <li>{@link AccessibilityServiceInfo#FEEDBACK_SPOKEN}</li>
* <li>{@link AccessibilityServiceInfo#FEEDBACK_VISUAL}</li>
* <li>{@link AccessibilityServiceInfo#FEEDBACK_GENERIC}</li>
* <li>{@link AccessibilityServiceInfo#FEEDBACK_BRAILLE}</li>
diff --git a/core/java/android/app/ActivityManagerInternal.java b/core/java/android/app/ActivityManagerInternal.java
index e3909f9..0881db0 100644
--- a/core/java/android/app/ActivityManagerInternal.java
+++ b/core/java/android/app/ActivityManagerInternal.java
@@ -518,6 +518,11 @@
Notification notification, int id, String pkg, @UserIdInt int userId);
/**
+ * Un-foreground all foreground services in the given app.
+ */
+ public abstract void makeServicesNonForeground(String pkg, @UserIdInt int userId);
+
+ /**
* If the given app has any FGSs whose notifications are in the given channel,
* stop them.
*/
diff --git a/core/java/android/app/AppOpsManager.java b/core/java/android/app/AppOpsManager.java
index 773694c..7a545f6 100644
--- a/core/java/android/app/AppOpsManager.java
+++ b/core/java/android/app/AppOpsManager.java
@@ -1313,9 +1313,23 @@
public static final int OP_RECORD_INCOMING_PHONE_AUDIO =
AppProtoEnums.APP_OP_RECORD_INCOMING_PHONE_AUDIO;
+ /**
+ * VPN app establishes a connection through the VpnService API.
+ *
+ * @hide
+ */
+ public static final int OP_ESTABLISH_VPN_SERVICE = AppProtoEnums.APP_OP_ESTABLISH_VPN_SERVICE;
+
+ /**
+ * VPN app establishes a connection through the VpnManager API.
+ *
+ * @hide
+ */
+ public static final int OP_ESTABLISH_VPN_MANAGER = AppProtoEnums.APP_OP_ESTABLISH_VPN_MANAGER;
+
/** @hide */
@UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
- public static final int _NUM_OP = 117;
+ public static final int _NUM_OP = 119;
/** Access to coarse location information. */
public static final String OPSTR_COARSE_LOCATION = "android:coarse_location";
@@ -1754,6 +1768,22 @@
public static final String OPSTR_RECORD_INCOMING_PHONE_AUDIO =
"android:record_incoming_phone_audio";
+ /**
+ * VPN app establishes a connection through the VpnService API.
+ *
+ * @hide
+ */
+ @SystemApi
+ public static final String OPSTR_ESTABLISH_VPN_SERVICE = "android:establish_vpn_service";
+
+ /**
+ * VPN app establishes a connection through the VpnManager API.
+ *
+ * @hide
+ */
+ @SystemApi
+ public static final String OPSTR_ESTABLISH_VPN_MANAGER = "android:establish_vpn_manager";
+
/** {@link #sAppOpsToNote} not initialized yet for this op */
private static final byte SHOULD_COLLECT_NOTE_OP_NOT_INITIALIZED = 0;
/** Should not collect noting of this app-op in {@link #sAppOpsToNote} */
@@ -1972,6 +2002,8 @@
OP_BLUETOOTH_ADVERTISE, // OP_BLUETOOTH_ADVERTISE
OP_RECORD_INCOMING_PHONE_AUDIO, // OP_RECORD_INCOMING_PHONE_AUDIO
OP_NEARBY_WIFI_DEVICES, // OP_NEARBY_WIFI_DEVICES
+ OP_ESTABLISH_VPN_SERVICE, // OP_ESTABLISH_VPN_SERVICE
+ OP_ESTABLISH_VPN_MANAGER, // OP_ESTABLISH_VPN_MANAGER
};
/**
@@ -2095,6 +2127,8 @@
OPSTR_BLUETOOTH_ADVERTISE,
OPSTR_RECORD_INCOMING_PHONE_AUDIO,
OPSTR_NEARBY_WIFI_DEVICES,
+ OPSTR_ESTABLISH_VPN_SERVICE,
+ OPSTR_ESTABLISH_VPN_MANAGER,
};
/**
@@ -2218,7 +2252,9 @@
"ACTIVITY_RECOGNITION_SOURCE",
"BLUETOOTH_ADVERTISE",
"RECORD_INCOMING_PHONE_AUDIO",
- "NEARBY_WIFI_DEVICES"
+ "NEARBY_WIFI_DEVICES",
+ "ESTABLISH_VPN_SERVICE",
+ "ESTABLISH_VPN_MANAGER",
};
/**
@@ -2344,6 +2380,8 @@
Manifest.permission.BLUETOOTH_ADVERTISE,
null, // no permission for OP_RECORD_INCOMING_PHONE_AUDIO,
Manifest.permission.NEARBY_WIFI_DEVICES,
+ null, // no permission for OP_ESTABLISH_VPN_SERVICE
+ null, // no permission for OP_ESTABLISH_VPN_MANAGER
};
/**
@@ -2469,6 +2507,8 @@
null, // BLUETOOTH_ADVERTISE
null, // RECORD_INCOMING_PHONE_AUDIO
null, // NEARBY_WIFI_DEVICES
+ null, // ESTABLISH_VPN_SERVICE
+ null, // ESTABLISH_VPN_MANAGER
};
/**
@@ -2593,6 +2633,8 @@
null, // BLUETOOTH_ADVERTISE
null, // RECORD_INCOMING_PHONE_AUDIO
null, // NEARBY_WIFI_DEVICES
+ null, // ESTABLISH_VPN_SERVICE
+ null, // ESTABLISH_VPN_MANAGER
};
/**
@@ -2716,6 +2758,8 @@
AppOpsManager.MODE_ALLOWED, // BLUETOOTH_ADVERTISE
AppOpsManager.MODE_ALLOWED, // RECORD_INCOMING_PHONE_AUDIO
AppOpsManager.MODE_ALLOWED, // NEARBY_WIFI_DEVICES
+ AppOpsManager.MODE_ALLOWED, // ESTABLISH_VPN_SERVICE
+ AppOpsManager.MODE_ALLOWED, // ESTABLISH_VPN_MANAGER
};
/**
@@ -2843,6 +2887,8 @@
false, // BLUETOOTH_ADVERTISE
false, // RECORD_INCOMING_PHONE_AUDIO
false, // NEARBY_WIFI_DEVICES
+ false, // OP_ESTABLISH_VPN_SERVICE
+ false, // OP_ESTABLISH_VPN_MANAGER
};
/**
diff --git a/core/java/android/app/ApplicationExitInfo.java b/core/java/android/app/ApplicationExitInfo.java
index d54452f..9039bbd 100644
--- a/core/java/android/app/ApplicationExitInfo.java
+++ b/core/java/android/app/ApplicationExitInfo.java
@@ -781,7 +781,7 @@
* @hide
*/
public void setProcessName(final String processName) {
- mProcessName = processName;
+ mProcessName = intern(processName);
}
/**
@@ -844,7 +844,7 @@
* @hide
*/
public void setDescription(final String description) {
- mDescription = description;
+ mDescription = intern(description);
}
/**
@@ -871,7 +871,7 @@
* @hide
*/
public void setPackageName(final String packageName) {
- mPackageName = packageName;
+ mPackageName = intern(packageName);
}
/**
@@ -1008,8 +1008,8 @@
mRealUid = in.readInt();
mPackageUid = in.readInt();
mDefiningUid = in.readInt();
- mProcessName = in.readString();
- mPackageName = in.readString();
+ mProcessName = intern(in.readString());
+ mPackageName = intern(in.readString());
mConnectionGroup = in.readInt();
mReason = in.readInt();
mSubReason = in.readInt();
@@ -1018,7 +1018,7 @@
mPss = in.readLong();
mRss = in.readLong();
mTimestamp = in.readLong();
- mDescription = in.readString();
+ mDescription = intern(in.readString());
mState = in.createByteArray();
if (in.readInt() == 1) {
mAppTraceRetriever = IAppTraceRetriever.Stub.asInterface(in.readStrongBinder());
@@ -1029,6 +1029,10 @@
}
}
+ private static String intern(@Nullable String source) {
+ return source != null ? source.intern() : null;
+ }
+
public @NonNull static final Creator<ApplicationExitInfo> CREATOR =
new Creator<ApplicationExitInfo>() {
@Override
@@ -1045,25 +1049,38 @@
/** @hide */
public void dump(@NonNull PrintWriter pw, @Nullable String prefix, @Nullable String seqSuffix,
@NonNull SimpleDateFormat sdf) {
- pw.println(prefix + "ApplicationExitInfo " + seqSuffix + ":");
- pw.println(prefix + " timestamp=" + sdf.format(new Date(mTimestamp)));
- pw.println(prefix + " pid=" + mPid);
- pw.println(prefix + " realUid=" + mRealUid);
- pw.println(prefix + " packageUid=" + mPackageUid);
- pw.println(prefix + " definingUid=" + mDefiningUid);
- pw.println(prefix + " user=" + UserHandle.getUserId(mPackageUid));
- pw.println(prefix + " process=" + mProcessName);
- pw.println(prefix + " reason=" + mReason + " (" + reasonCodeToString(mReason) + ")");
- pw.println(prefix + " subreason=" + mSubReason + " (" + subreasonToString(mSubReason)
- + ")");
- pw.println(prefix + " status=" + mStatus);
- pw.println(prefix + " importance=" + mImportance);
- pw.print(prefix + " pss="); DebugUtils.printSizeValue(pw, mPss << 10); pw.println();
- pw.print(prefix + " rss="); DebugUtils.printSizeValue(pw, mRss << 10); pw.println();
- pw.println(prefix + " description=" + mDescription);
- pw.println(prefix + " state=" + (ArrayUtils.isEmpty(mState)
- ? "empty" : Integer.toString(mState.length) + " bytes"));
- pw.println(prefix + " trace=" + mTraceFile);
+ StringBuilder sb = new StringBuilder();
+ sb.append(prefix)
+ .append("ApplicationExitInfo ").append(seqSuffix).append(':')
+ .append('\n');
+ sb.append(prefix).append(' ')
+ .append(" timestamp=").append(sdf.format(new Date(mTimestamp)))
+ .append(" pid=").append(mPid)
+ .append(" realUid=").append(mRealUid)
+ .append(" packageUid=").append(mPackageUid)
+ .append(" definingUid=").append(mDefiningUid)
+ .append(" user=").append(UserHandle.getUserId(mPackageUid))
+ .append('\n');
+ sb.append(prefix).append(' ')
+ .append(" process=").append(mProcessName)
+ .append(" reason=").append(mReason)
+ .append(" (").append(reasonCodeToString(mReason)).append(")")
+ .append(" subreason=").append(mSubReason)
+ .append(" (").append(subreasonToString(mSubReason)).append(")")
+ .append(" status=").append(mStatus)
+ .append('\n');
+ sb.append(prefix).append(' ')
+ .append(" importance=").append(mImportance)
+ .append(" pss=");
+ DebugUtils.sizeValueToString(mPss << 10, sb);
+ sb.append(" rss=");
+ DebugUtils.sizeValueToString(mRss << 10, sb);
+ sb.append(" description=").append(mDescription)
+ .append(" state=").append((ArrayUtils.isEmpty(mState)
+ ? "empty" : Integer.toString(mState.length) + " bytes"))
+ .append(" trace=").append(mTraceFile)
+ .append('\n');
+ pw.print(sb.toString());
}
@Override
@@ -1228,7 +1245,7 @@
mDefiningUid = proto.readInt(ApplicationExitInfoProto.DEFINING_UID);
break;
case (int) ApplicationExitInfoProto.PROCESS_NAME:
- mProcessName = proto.readString(ApplicationExitInfoProto.PROCESS_NAME);
+ mProcessName = intern(proto.readString(ApplicationExitInfoProto.PROCESS_NAME));
break;
case (int) ApplicationExitInfoProto.CONNECTION_GROUP:
mConnectionGroup = proto.readInt(ApplicationExitInfoProto.CONNECTION_GROUP);
@@ -1255,7 +1272,7 @@
mTimestamp = proto.readLong(ApplicationExitInfoProto.TIMESTAMP);
break;
case (int) ApplicationExitInfoProto.DESCRIPTION:
- mDescription = proto.readString(ApplicationExitInfoProto.DESCRIPTION);
+ mDescription = intern(proto.readString(ApplicationExitInfoProto.DESCRIPTION));
break;
case (int) ApplicationExitInfoProto.STATE:
mState = proto.readBytes(ApplicationExitInfoProto.STATE);
diff --git a/core/java/android/app/ApplicationLoaders.java b/core/java/android/app/ApplicationLoaders.java
index 08cd0b3..53b16d3 100644
--- a/core/java/android/app/ApplicationLoaders.java
+++ b/core/java/android/app/ApplicationLoaders.java
@@ -48,18 +48,19 @@
ClassLoader parent, String classLoaderName) {
return getClassLoaderWithSharedLibraries(zip, targetSdkVersion, isBundled,
librarySearchPath, libraryPermittedPath, parent, classLoaderName,
- null, null);
+ null, null, null);
}
ClassLoader getClassLoaderWithSharedLibraries(
String zip, int targetSdkVersion, boolean isBundled,
String librarySearchPath, String libraryPermittedPath,
ClassLoader parent, String classLoaderName,
- List<ClassLoader> sharedLibraries, List<String> nativeSharedLibraries) {
+ List<ClassLoader> sharedLibraries, List<String> nativeSharedLibraries,
+ List<ClassLoader> sharedLibrariesLoadedAfterApp) {
// For normal usage the cache key used is the same as the zip path.
return getClassLoader(zip, targetSdkVersion, isBundled, librarySearchPath,
libraryPermittedPath, parent, zip, classLoaderName, sharedLibraries,
- nativeSharedLibraries);
+ nativeSharedLibraries, sharedLibrariesLoadedAfterApp);
}
/**
@@ -71,7 +72,8 @@
*/
ClassLoader getSharedLibraryClassLoaderWithSharedLibraries(String zip, int targetSdkVersion,
boolean isBundled, String librarySearchPath, String libraryPermittedPath,
- ClassLoader parent, String classLoaderName, List<ClassLoader> sharedLibraries) {
+ ClassLoader parent, String classLoaderName, List<ClassLoader> sharedLibraries,
+ List<ClassLoader> sharedLibrariesAfter) {
ClassLoader loader = getCachedNonBootclasspathSystemLib(zip, parent, classLoaderName,
sharedLibraries);
if (loader != null) {
@@ -86,14 +88,15 @@
nativeSharedLibraries.add("ALL");
return getClassLoaderWithSharedLibraries(zip, targetSdkVersion, isBundled,
librarySearchPath, libraryPermittedPath, parent, classLoaderName, sharedLibraries,
- nativeSharedLibraries);
+ nativeSharedLibraries, sharedLibrariesAfter);
}
private ClassLoader getClassLoader(String zip, int targetSdkVersion, boolean isBundled,
String librarySearchPath, String libraryPermittedPath,
ClassLoader parent, String cacheKey,
String classLoaderName, List<ClassLoader> sharedLibraries,
- List<String> nativeSharedLibraries) {
+ List<String> nativeSharedLibraries,
+ List<ClassLoader> sharedLibrariesLoadedAfterApp) {
/*
* This is the parent we use if they pass "null" in. In theory
* this should be the "system" class loader; in practice we
@@ -123,7 +126,7 @@
ClassLoader classloader = ClassLoaderFactory.createClassLoader(
zip, librarySearchPath, libraryPermittedPath, parent,
targetSdkVersion, isBundled, classLoaderName, sharedLibraries,
- nativeSharedLibraries);
+ nativeSharedLibraries, sharedLibrariesLoadedAfterApp);
Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
@@ -140,7 +143,8 @@
Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, zip);
ClassLoader loader = ClassLoaderFactory.createClassLoader(
- zip, null, parent, classLoaderName, sharedLibraries);
+ zip, null, parent, classLoaderName, sharedLibraries,
+ null /*sharedLibrariesLoadedAfterApp*/);
Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
return loader;
}
@@ -196,7 +200,7 @@
ClassLoader classLoader = getClassLoader(path, Build.VERSION.SDK_INT, true /*isBundled*/,
null /*librarySearchPath*/, null /*libraryPermittedPath*/, null /*parent*/,
null /*cacheKey*/, null /*classLoaderName*/, sharedLibraries /*sharedLibraries*/,
- null /* nativeSharedLibraries */);
+ null /* nativeSharedLibraries */, null /*sharedLibrariesLoadedAfterApp*/);
if (classLoader == null) {
// bad configuration or break in classloading code
@@ -267,7 +271,8 @@
// stub's APK path, when the actual package path is the donor APK.
return getClassLoader(packagePath, Build.VERSION.SDK_INT, false, libsPath, null, null,
cacheKey, null /* classLoaderName */, null /* sharedLibraries */,
- null /* nativeSharedLibraries */);
+ null /* nativeSharedLibraries */,
+ null /*sharedLibrariesLoadedAfterApp*/);
}
/**
diff --git a/core/java/android/app/ContextImpl.java b/core/java/android/app/ContextImpl.java
index bd43ab5..756833a 100644
--- a/core/java/android/app/ContextImpl.java
+++ b/core/java/android/app/ContextImpl.java
@@ -2763,7 +2763,7 @@
*/
private static Resources createWindowContextResources(@NonNull ContextImpl windowContextBase) {
final LoadedApk packageInfo = windowContextBase.mPackageInfo;
- final ClassLoader classLoader = windowContextBase.mClassLoader;
+ final ClassLoader classLoader = windowContextBase.getClassLoader();
final IBinder token = windowContextBase.getWindowContextToken();
final String resDir = packageInfo.getResDir();
diff --git a/core/java/android/app/IActivityManager.aidl b/core/java/android/app/IActivityManager.aidl
index 47e4810..658c130 100644
--- a/core/java/android/app/IActivityManager.aidl
+++ b/core/java/android/app/IActivityManager.aidl
@@ -278,6 +278,7 @@
List<ActivityManager.ProcessErrorStateInfo> getProcessesInErrorState();
boolean clearApplicationUserData(in String packageName, boolean keepState,
in IPackageDataObserver observer, int userId);
+ void makeServicesNonForeground(in String packageName, int userId);
@UnsupportedAppUsage
void forceStopPackage(in String packageName, int userId);
boolean killPids(in int[] pids, in String reason, boolean secure);
diff --git a/core/java/android/app/IActivityTaskManager.aidl b/core/java/android/app/IActivityTaskManager.aidl
index 2be7803..b052bc5 100644
--- a/core/java/android/app/IActivityTaskManager.aidl
+++ b/core/java/android/app/IActivityTaskManager.aidl
@@ -68,6 +68,7 @@
import android.os.WorkSource;
import android.service.voice.IVoiceInteractionSession;
import android.view.IRecentsAnimationRunner;
+import android.view.IRemoteAnimationRunner;
import android.view.RemoteAnimationDefinition;
import android.view.RemoteAnimationAdapter;
import android.window.IWindowOrganizerController;
@@ -344,4 +345,9 @@
* @param caller is the IApplicationThread representing the calling process.
*/
void setRunningRemoteTransitionDelegate(in IApplicationThread caller);
+
+ /**
+ * Prepare the back preview in the server
+ */
+ void startBackPreview(IRemoteAnimationRunner runner);
}
diff --git a/core/java/android/app/LoadedApk.java b/core/java/android/app/LoadedApk.java
index a2c9795..5750484 100644
--- a/core/java/android/app/LoadedApk.java
+++ b/core/java/android/app/LoadedApk.java
@@ -54,10 +54,12 @@
import android.util.AndroidRuntimeException;
import android.util.ArrayMap;
import android.util.Log;
+import android.util.Pair;
import android.util.Slog;
import android.util.SparseArray;
import android.view.DisplayAdjustments;
+import com.android.internal.R;
import com.android.internal.annotations.GuardedBy;
import com.android.internal.util.ArrayUtils;
@@ -76,6 +78,7 @@
import java.util.Arrays;
import java.util.Collections;
import java.util.Enumeration;
+import java.util.HashSet;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Objects;
@@ -700,7 +703,7 @@
ClassLoader createSharedLibraryLoader(SharedLibraryInfo sharedLibrary,
boolean isBundledApp, String librarySearchPath, String libraryPermittedPath) {
List<String> paths = sharedLibrary.getAllCodePaths();
- List<ClassLoader> sharedLibraries = createSharedLibrariesLoaders(
+ Pair<List<ClassLoader>, List<ClassLoader>> sharedLibraries = createSharedLibrariesLoaders(
sharedLibrary.getDependencies(), isBundledApp, librarySearchPath,
libraryPermittedPath);
final String jars = (paths.size() == 1) ? paths.get(0) :
@@ -711,15 +714,31 @@
return ApplicationLoaders.getDefault().getSharedLibraryClassLoaderWithSharedLibraries(jars,
mApplicationInfo.targetSdkVersion, isBundledApp, librarySearchPath,
libraryPermittedPath, /* parent */ null,
- /* classLoaderName */ null, sharedLibraries);
+ /* classLoaderName */ null, sharedLibraries.first, sharedLibraries.second);
}
- private List<ClassLoader> createSharedLibrariesLoaders(List<SharedLibraryInfo> sharedLibraries,
+ /**
+ *
+ * @return a {@link Pair} of List<ClassLoader> where the first is for standard shared libraries
+ * and the second is list for shared libraries that code should be loaded after the dex
+ */
+ private Pair<List<ClassLoader>, List<ClassLoader>> createSharedLibrariesLoaders(
+ List<SharedLibraryInfo> sharedLibraries,
boolean isBundledApp, String librarySearchPath, String libraryPermittedPath) {
- if (sharedLibraries == null) {
- return null;
+ if (sharedLibraries == null || sharedLibraries.isEmpty()) {
+ return new Pair<>(null, null);
}
+
+ // if configured to do so, shared libs are split into 2 collections: those that are
+ // on the class path before the applications code, which is standard, and those
+ // specified to be loaded after the applications code.
+ HashSet<String> libsToLoadAfter = new HashSet<>();
+ Resources systemR = Resources.getSystem();
+ Collections.addAll(libsToLoadAfter, systemR.getStringArray(
+ R.array.config_sharedLibrariesLoadedAfterApp));
+
List<ClassLoader> loaders = new ArrayList<>();
+ List<ClassLoader> after = new ArrayList<>();
for (SharedLibraryInfo info : sharedLibraries) {
if (info.isNative()) {
// Native shared lib doesn't contribute to the native lib search path. Its name is
@@ -727,10 +746,19 @@
// default linker namespace.
continue;
}
- loaders.add(createSharedLibraryLoader(
- info, isBundledApp, librarySearchPath, libraryPermittedPath));
+ if (libsToLoadAfter.contains(info.getName())) {
+ if (DEBUG) {
+ Slog.v(ActivityThread.TAG,
+ info.getName() + " will be loaded after application code");
+ }
+ after.add(createSharedLibraryLoader(
+ info, isBundledApp, librarySearchPath, libraryPermittedPath));
+ } else {
+ loaders.add(createSharedLibraryLoader(
+ info, isBundledApp, librarySearchPath, libraryPermittedPath));
+ }
}
- return loaders;
+ return new Pair<>(loaders, after);
}
private StrictMode.ThreadPolicy allowThreadDiskReads() {
@@ -955,9 +983,9 @@
// as this is early and necessary.
StrictMode.ThreadPolicy oldPolicy = allowThreadDiskReads();
- List<ClassLoader> sharedLibraries = createSharedLibrariesLoaders(
- mApplicationInfo.sharedLibraryInfos, isBundledApp, librarySearchPath,
- libraryPermittedPath);
+ Pair<List<ClassLoader>, List<ClassLoader>> sharedLibraries =
+ createSharedLibrariesLoaders(mApplicationInfo.sharedLibraryInfos, isBundledApp,
+ librarySearchPath, libraryPermittedPath);
List<String> nativeSharedLibraries = new ArrayList<>();
if (mApplicationInfo.sharedLibraryInfos != null) {
@@ -971,7 +999,8 @@
mDefaultClassLoader = ApplicationLoaders.getDefault().getClassLoaderWithSharedLibraries(
zip, mApplicationInfo.targetSdkVersion, isBundledApp, librarySearchPath,
libraryPermittedPath, mBaseClassLoader,
- mApplicationInfo.classLoaderName, sharedLibraries, nativeSharedLibraries);
+ mApplicationInfo.classLoaderName, sharedLibraries.first, nativeSharedLibraries,
+ sharedLibraries.second);
mAppComponentFactory = createAppFactory(mApplicationInfo, mDefaultClassLoader);
setThreadPolicy(oldPolicy);
@@ -2134,4 +2163,38 @@
final IBinder mService;
}
}
+
+ /**
+ * Check if the Apk paths in the cache are correct, and update them if they are not.
+ * @hide
+ */
+ public static void checkAndUpdateApkPaths(ApplicationInfo expectedAppInfo) {
+ // Get the LoadedApk from the cache
+ ActivityThread activityThread = ActivityThread.currentActivityThread();
+ if (activityThread == null) {
+ Log.e(TAG, "Cannot find activity thread");
+ return;
+ }
+ checkAndUpdateApkPaths(activityThread, expectedAppInfo, /* cacheWithCode */ true);
+ checkAndUpdateApkPaths(activityThread, expectedAppInfo, /* cacheWithCode */ false);
+ }
+
+ private static void checkAndUpdateApkPaths(ActivityThread activityThread,
+ ApplicationInfo expectedAppInfo, boolean cacheWithCode) {
+ String expectedCodePath = expectedAppInfo.getCodePath();
+ LoadedApk loadedApk = activityThread.peekPackageInfo(
+ expectedAppInfo.packageName, /* includeCode= */ cacheWithCode);
+ // If there is load apk cached, or if the cache is valid, don't do anything.
+ if (loadedApk == null || loadedApk.getApplicationInfo() == null
+ || loadedApk.getApplicationInfo().getCodePath().equals(expectedCodePath)) {
+ return;
+ }
+ // Duplicate framework logic
+ List<String> oldPaths = new ArrayList<>();
+ LoadedApk.makePaths(activityThread, expectedAppInfo, oldPaths);
+
+ // Force update the LoadedApk instance, which should update the reference in the cache
+ loadedApk.updateApplicationInfo(expectedAppInfo, oldPaths);
+ }
+
}
diff --git a/core/java/android/app/StatusBarManager.java b/core/java/android/app/StatusBarManager.java
index 64f89bc..48ceef0 100644
--- a/core/java/android/app/StatusBarManager.java
+++ b/core/java/android/app/StatusBarManager.java
@@ -669,6 +669,21 @@
}
}
+ /**
+ * @hide
+ * @param packageName
+ */
+ @TestApi
+ public void cancelRequestAddTile(@NonNull String packageName) {
+ Objects.requireNonNull(packageName);
+ IStatusBarService svc = getService();
+ try {
+ svc.cancelRequestAddTile(packageName);
+ } catch (RemoteException e) {
+ e.rethrowFromSystemServer();
+ }
+ }
+
/** @hide */
public static String windowStateToString(int state) {
if (state == WINDOW_STATE_HIDING) return "WINDOW_STATE_HIDING";
diff --git a/core/java/android/app/SystemServiceRegistry.java b/core/java/android/app/SystemServiceRegistry.java
index 8ea1f83..6ba185f 100644
--- a/core/java/android/app/SystemServiceRegistry.java
+++ b/core/java/android/app/SystemServiceRegistry.java
@@ -54,6 +54,8 @@
import android.bluetooth.BluetoothManager;
import android.companion.CompanionDeviceManager;
import android.companion.ICompanionDeviceManager;
+import android.companion.virtual.IVirtualDeviceManager;
+import android.companion.virtual.VirtualDeviceManager;
import android.content.ClipboardManager;
import android.content.ContentCaptureOptions;
import android.content.Context;
@@ -124,6 +126,8 @@
import android.media.soundtrigger.SoundTriggerManager;
import android.media.tv.ITvInputManager;
import android.media.tv.TvInputManager;
+import android.media.tv.interactive.ITvIAppManager;
+import android.media.tv.interactive.TvIAppManager;
import android.media.tv.tunerresourcemanager.ITunerResourceManager;
import android.media.tv.tunerresourcemanager.TunerResourceManager;
import android.net.ConnectivityFrameworkInitializer;
@@ -875,6 +879,16 @@
return new CompanionDeviceManager(service, ctx.getOuterContext());
}});
+ registerService(Context.VIRTUAL_DEVICE_SERVICE, VirtualDeviceManager.class,
+ new CachedServiceFetcher<VirtualDeviceManager>() {
+ @Override
+ public VirtualDeviceManager createService(ContextImpl ctx)
+ throws ServiceNotFoundException {
+ IVirtualDeviceManager service = IVirtualDeviceManager.Stub.asInterface(
+ ServiceManager.getServiceOrThrow(Context.VIRTUAL_DEVICE_SERVICE));
+ return new VirtualDeviceManager(service, ctx.getOuterContext());
+ }});
+
registerService(Context.CONSUMER_IR_SERVICE, ConsumerIrManager.class,
new CachedServiceFetcher<ConsumerIrManager>() {
@Override
@@ -945,6 +959,15 @@
}
});
+ registerService(Context.TV_IAPP_SERVICE, TvIAppManager.class,
+ new CachedServiceFetcher<TvIAppManager>() {
+ @Override
+ public TvIAppManager createService(ContextImpl ctx) throws ServiceNotFoundException {
+ IBinder iBinder = ServiceManager.getServiceOrThrow(Context.TV_IAPP_SERVICE);
+ ITvIAppManager service = ITvIAppManager.Stub.asInterface(iBinder);
+ return new TvIAppManager(service, ctx.getUserId());
+ }});
+
registerService(Context.TV_INPUT_SERVICE, TvInputManager.class,
new CachedServiceFetcher<TvInputManager>() {
@Override
@@ -1925,39 +1948,6 @@
public abstract T createService() throws ServiceNotFoundException;
}
- /**
- * Like StaticServiceFetcher, creates only one instance of the service per application, but when
- * creating the service for the first time, passes it the application context of the creating
- * application.
- *
- * TODO: Delete this once its only user (ConnectivityManager) is known to work well in the
- * case where multiple application components each have their own ConnectivityManager object.
- */
- static abstract class StaticApplicationContextServiceFetcher<T> implements ServiceFetcher<T> {
- private T mCachedInstance;
-
- @Override
- public final T getService(ContextImpl ctx) {
- synchronized (StaticApplicationContextServiceFetcher.this) {
- if (mCachedInstance == null) {
- Context appContext = ctx.getApplicationContext();
- // If the application context is null, we're either in the system process or
- // it's the application context very early in app initialization. In both these
- // cases, the passed-in ContextImpl will not be freed, so it's safe to pass it
- // to the service. http://b/27532714 .
- try {
- mCachedInstance = createService(appContext != null ? appContext : ctx);
- } catch (ServiceNotFoundException e) {
- onServiceNotFound(e);
- }
- }
- return mCachedInstance;
- }
- }
-
- public abstract T createService(Context applicationContext) throws ServiceNotFoundException;
- }
-
/** @hide */
public static void onServiceNotFound(ServiceNotFoundException e) {
// We're mostly interested in tracking down long-lived core system
diff --git a/core/java/android/app/WallpaperManager.java b/core/java/android/app/WallpaperManager.java
index a53ef1b..b3fad21 100644
--- a/core/java/android/app/WallpaperManager.java
+++ b/core/java/android/app/WallpaperManager.java
@@ -108,7 +108,7 @@
@SystemService(Context.WALLPAPER_SERVICE)
public class WallpaperManager {
private static String TAG = "WallpaperManager";
- private static boolean DEBUG = false;
+ private static final boolean DEBUG = false;
private float mWallpaperXStep = -1;
private float mWallpaperYStep = -1;
private static final @NonNull RectF LOCAL_COLOR_BOUNDS =
diff --git a/core/java/android/app/slice/SliceManager.java b/core/java/android/app/slice/SliceManager.java
index 4da1acb..5497b78 100644
--- a/core/java/android/app/slice/SliceManager.java
+++ b/core/java/android/app/slice/SliceManager.java
@@ -41,6 +41,7 @@
import android.os.ServiceManager;
import android.os.ServiceManager.ServiceNotFoundException;
import android.os.UserHandle;
+import android.text.TextUtils;
import android.util.ArraySet;
import android.util.Log;
@@ -223,10 +224,15 @@
public @NonNull Collection<Uri> getSliceDescendants(@NonNull Uri uri) {
ContentResolver resolver = mContext.getContentResolver();
try (ContentProviderClient provider = resolver.acquireUnstableContentProviderClient(uri)) {
- Bundle extras = new Bundle();
- extras.putParcelable(SliceProvider.EXTRA_BIND_URI, uri);
- final Bundle res = provider.call(SliceProvider.METHOD_GET_DESCENDANTS, null, extras);
- return res.getParcelableArrayList(SliceProvider.EXTRA_SLICE_DESCENDANTS);
+ if (provider == null) {
+ Log.w(TAG, TextUtils.formatSimple("Unknown URI: %s", uri));
+ } else {
+ Bundle extras = new Bundle();
+ extras.putParcelable(SliceProvider.EXTRA_BIND_URI, uri);
+ final Bundle res = provider.call(
+ SliceProvider.METHOD_GET_DESCENDANTS, null, extras);
+ return res.getParcelableArrayList(SliceProvider.EXTRA_SLICE_DESCENDANTS);
+ }
} catch (RemoteException e) {
Log.e(TAG, "Unable to get slice descendants", e);
}
diff --git a/core/java/android/appwidget/AppWidgetHostView.java b/core/java/android/appwidget/AppWidgetHostView.java
index dd147cc..7c2b1b7 100644
--- a/core/java/android/appwidget/AppWidgetHostView.java
+++ b/core/java/android/appwidget/AppWidgetHostView.java
@@ -20,6 +20,7 @@
import android.annotation.Nullable;
import android.app.Activity;
import android.app.ActivityOptions;
+import android.app.LoadedApk;
import android.compat.annotation.UnsupportedAppUsage;
import android.content.ComponentName;
import android.content.Context;
@@ -554,7 +555,7 @@
}
// Prepare a local reference to the remote Context so we're ready to
// inflate any requested LayoutParams.
- mRemoteContext = getRemoteContext();
+ mRemoteContext = getRemoteContextEnsuringCorrectCachedApkPath();
int layoutId = rvToApply.getLayoutId();
if (rvToApply.canRecycleView(mView)) {
@@ -616,7 +617,7 @@
private void inflateAsync(@NonNull RemoteViews remoteViews) {
// Prepare a local reference to the remote Context so we're ready to
// inflate any requested LayoutParams.
- mRemoteContext = getRemoteContext();
+ mRemoteContext = getRemoteContextEnsuringCorrectCachedApkPath();
int layoutId = remoteViews.getLayoutId();
if (mLastExecutionSignal != null) {
@@ -625,7 +626,7 @@
// If our stale view has been prepared to match active, and the new
// layout matches, try recycling it
- if (layoutId == mLayoutId && mView != null) {
+ if (remoteViews.canRecycleView(mView)) {
try {
mLastExecutionSignal = remoteViews.reapplyAsync(mContext,
mView,
@@ -718,8 +719,10 @@
* purposes of reading remote resources.
* @hide
*/
- protected Context getRemoteContext() {
+ protected Context getRemoteContextEnsuringCorrectCachedApkPath() {
try {
+ ApplicationInfo expectedAppInfo = mInfo.providerInfo.applicationInfo;
+ LoadedApk.checkAndUpdateApkPaths(expectedAppInfo);
// Return if cloned successfully, otherwise default
Context newContext = mContext.createApplicationContext(
mInfo.providerInfo.applicationInfo,
@@ -765,7 +768,7 @@
try {
if (mInfo != null) {
- Context theirContext = getRemoteContext();
+ Context theirContext = getRemoteContextEnsuringCorrectCachedApkPath();
mRemoteContext = theirContext;
LayoutInflater inflater = (LayoutInflater)
theirContext.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
diff --git a/core/java/android/bluetooth/BluetoothActivityEnergyInfo.java b/core/java/android/bluetooth/BluetoothActivityEnergyInfo.java
index df065bf..c17a7b4 100644
--- a/core/java/android/bluetooth/BluetoothActivityEnergyInfo.java
+++ b/core/java/android/bluetooth/BluetoothActivityEnergyInfo.java
@@ -16,18 +16,26 @@
package android.bluetooth;
+import android.annotation.ElapsedRealtimeLong;
+import android.annotation.IntDef;
+import android.annotation.NonNull;
+import android.annotation.SystemApi;
import android.os.Parcel;
import android.os.Parcelable;
-import java.util.Arrays;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.util.Collections;
+import java.util.List;
/**
* Record of energy and activity information from controller and
* underlying bt stack state.Timestamp the record with system
- * time
+ * time.
*
* @hide
*/
+@SystemApi(client = SystemApi.Client.PRIVILEGED_APPS)
public final class BluetoothActivityEnergyInfo implements Parcelable {
private final long mTimestamp;
private int mBluetoothStackState;
@@ -35,13 +43,24 @@
private long mControllerRxTimeMs;
private long mControllerIdleTimeMs;
private long mControllerEnergyUsed;
- private UidTraffic[] mUidTraffic;
+ private List<UidTraffic> mUidTraffic;
+
+ /** @hide */
+ @IntDef(prefix = { "BT_STACK_STATE_" }, value = {
+ BT_STACK_STATE_INVALID,
+ BT_STACK_STATE_STATE_ACTIVE,
+ BT_STACK_STATE_STATE_SCANNING,
+ BT_STACK_STATE_STATE_IDLE
+ })
+ @Retention(RetentionPolicy.SOURCE)
+ public @interface BluetoothStackState {}
public static final int BT_STACK_STATE_INVALID = 0;
public static final int BT_STACK_STATE_STATE_ACTIVE = 1;
public static final int BT_STACK_STATE_STATE_SCANNING = 2;
public static final int BT_STACK_STATE_STATE_IDLE = 3;
+ /** @hide */
public BluetoothActivityEnergyInfo(long timestamp, int stackState,
long txTime, long rxTime, long idleTime, long energyUsed) {
mTimestamp = timestamp;
@@ -52,17 +71,18 @@
mControllerEnergyUsed = energyUsed;
}
- @SuppressWarnings("unchecked")
- BluetoothActivityEnergyInfo(Parcel in) {
+ /** @hide */
+ private BluetoothActivityEnergyInfo(Parcel in) {
mTimestamp = in.readLong();
mBluetoothStackState = in.readInt();
mControllerTxTimeMs = in.readLong();
mControllerRxTimeMs = in.readLong();
mControllerIdleTimeMs = in.readLong();
mControllerEnergyUsed = in.readLong();
- mUidTraffic = in.createTypedArray(UidTraffic.CREATOR);
+ mUidTraffic = in.createTypedArrayList(UidTraffic.CREATOR);
}
+ /** @hide */
@Override
public String toString() {
return "BluetoothActivityEnergyInfo{"
@@ -72,11 +92,11 @@
+ " mControllerRxTimeMs=" + mControllerRxTimeMs
+ " mControllerIdleTimeMs=" + mControllerIdleTimeMs
+ " mControllerEnergyUsed=" + mControllerEnergyUsed
- + " mUidTraffic=" + Arrays.toString(mUidTraffic)
+ + " mUidTraffic=" + mUidTraffic
+ " }";
}
- public static final @android.annotation.NonNull Parcelable.Creator<BluetoothActivityEnergyInfo> CREATOR =
+ public static final @NonNull Parcelable.Creator<BluetoothActivityEnergyInfo> CREATOR =
new Parcelable.Creator<BluetoothActivityEnergyInfo>() {
public BluetoothActivityEnergyInfo createFromParcel(Parcel in) {
return new BluetoothActivityEnergyInfo(in);
@@ -87,9 +107,8 @@
}
};
-
+ /** @hide */
@Override
- @SuppressWarnings("unchecked")
public void writeToParcel(Parcel out, int flags) {
out.writeLong(mTimestamp);
out.writeInt(mBluetoothStackState);
@@ -97,17 +116,21 @@
out.writeLong(mControllerRxTimeMs);
out.writeLong(mControllerIdleTimeMs);
out.writeLong(mControllerEnergyUsed);
- out.writeTypedArray(mUidTraffic, flags);
+ out.writeTypedList(mUidTraffic);
}
+ /** @hide */
@Override
public int describeContents() {
return 0;
}
/**
- * @return bt stack reported state
+ * Get the Bluetooth stack state associated with the energy info.
+ *
+ * @return one of {@link #BluetoothStackState} states
*/
+ @BluetoothStackState
public int getBluetoothStackState() {
return mBluetoothStackState;
}
@@ -134,7 +157,7 @@
}
/**
- * product of current(mA), voltage(V) and time(ms)
+ * Get the product of current (mA), voltage (V), and time (ms).
*
* @return energy used
*/
@@ -143,22 +166,31 @@
}
/**
- * @return timestamp(real time elapsed in milliseconds since boot) of record creation.
+ * @return timestamp (real time elapsed in milliseconds since boot) of record creation
*/
- public long getTimeStamp() {
+ public @ElapsedRealtimeLong long getTimestampMillis() {
return mTimestamp;
}
- public UidTraffic[] getUidTraffic() {
+ /**
+ * Get the {@link List} of each application {@link android.bluetooth.UidTraffic}.
+ *
+ * @return current {@link List} of {@link android.bluetooth.UidTraffic}
+ */
+ public @NonNull List<UidTraffic> getUidTraffic() {
+ if (mUidTraffic == null) {
+ return Collections.emptyList();
+ }
return mUidTraffic;
}
- public void setUidTraffic(UidTraffic[] traffic) {
+ /** @hide */
+ public void setUidTraffic(List<UidTraffic> traffic) {
mUidTraffic = traffic;
}
/**
- * @return if the record is valid
+ * @return true if the record Tx time, Rx time, and Idle time are more than 0.
*/
public boolean isValid() {
return ((mControllerTxTimeMs >= 0) && (mControllerRxTimeMs >= 0)
diff --git a/core/java/android/bluetooth/BluetoothAdapter.java b/core/java/android/bluetooth/BluetoothAdapter.java
index 06ce053..dac8ffe 100644
--- a/core/java/android/bluetooth/BluetoothAdapter.java
+++ b/core/java/android/bluetooth/BluetoothAdapter.java
@@ -2272,6 +2272,66 @@
return false;
}
+ /** @hide */
+ @Retention(RetentionPolicy.SOURCE)
+ @IntDef(value = {
+ BluetoothStatusCodes.SUCCESS,
+ BluetoothStatusCodes.ERROR_UNKNOWN,
+ BluetoothStatusCodes.ERROR_BLUETOOTH_NOT_ENABLED,
+ BluetoothStatusCodes.ERROR_FEATURE_NOT_SUPPORTED,
+ })
+ public @interface LeFeatureReturnValues {}
+
+ /**
+ * Returns {@link BluetoothStatusCodes#SUCCESS} if LE Connected Isochronous Stream Central
+ * feature is supported, returns {@link BluetoothStatusCodes#ERROR_FEATURE_NOT_SUPPORTED} if
+ * the feature is not supported or an error code.
+ *
+ * @return whether the chipset supports the LE Connected Isochronous Stream Central feature
+ */
+ @RequiresNoPermission
+ public @LeFeatureReturnValues int isCisCentralSupported() {
+ if (!getLeAccess()) {
+ return BluetoothStatusCodes.ERROR_BLUETOOTH_NOT_ENABLED;
+ }
+ try {
+ mServiceLock.readLock().lock();
+ if (mService != null) {
+ return mService.isCisCentralSupported();
+ }
+ } catch (RemoteException e) {
+ e.rethrowFromSystemServer();
+ } finally {
+ mServiceLock.readLock().unlock();
+ }
+ return BluetoothStatusCodes.ERROR_UNKNOWN;
+ }
+
+ /**
+ * Returns {@link BluetoothStatusCodes#SUCCESS} if LE Periodic Advertising Sync Transfer Sender
+ * feature is supported, returns {@link BluetoothStatusCodes#ERROR_FEATURE_NOT_SUPPORTED} if the
+ * feature is not supported or an error code
+ *
+ * @return whether the chipset supports the LE Periodic Advertising Sync Transfer Sender feature
+ */
+ @RequiresNoPermission
+ public @LeFeatureReturnValues int isLePeriodicAdvertisingSyncTransferSenderSupported() {
+ if (!getLeAccess()) {
+ return BluetoothStatusCodes.ERROR_BLUETOOTH_NOT_ENABLED;
+ }
+ try {
+ mServiceLock.readLock().lock();
+ if (mService != null) {
+ return mService.isLePeriodicAdvertisingSyncTransferSenderSupported();
+ }
+ } catch (RemoteException e) {
+ e.rethrowFromSystemServer();
+ } finally {
+ mServiceLock.readLock().unlock();
+ }
+ return BluetoothStatusCodes.ERROR_UNKNOWN;
+ }
+
/**
* Return the maximum LE advertising data length in bytes,
* if LE Extended Advertising feature is supported, 0 otherwise.
diff --git a/core/java/android/bluetooth/BluetoothDevice.java b/core/java/android/bluetooth/BluetoothDevice.java
index e968052..6e918bd 100644
--- a/core/java/android/bluetooth/BluetoothDevice.java
+++ b/core/java/android/bluetooth/BluetoothDevice.java
@@ -1186,6 +1186,11 @@
mAttributionSource = attributionSource;
}
+ /** {@hide} */
+ public void prepareToEnterProcess(@NonNull AttributionSource attributionSource) {
+ setAttributionSource(attributionSource);
+ }
+
@Override
public boolean equals(@Nullable Object o) {
if (o instanceof BluetoothDevice) {
diff --git a/core/java/android/bluetooth/BluetoothHeadsetClient.java b/core/java/android/bluetooth/BluetoothHeadsetClient.java
index 83108d2..a5a2470 100644
--- a/core/java/android/bluetooth/BluetoothHeadsetClient.java
+++ b/core/java/android/bluetooth/BluetoothHeadsetClient.java
@@ -817,7 +817,7 @@
@RequiresBluetoothConnectPermission
@RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)
public Bundle getCurrentAgEvents(BluetoothDevice device) {
- if (DBG) log("getCurrentCalls()");
+ if (DBG) log("getCurrentAgEvents()");
final IBluetoothHeadsetClient service =
getService();
if (service != null && isEnabled() && isValidDevice(device)) {
diff --git a/core/java/android/bluetooth/BluetoothManager.java b/core/java/android/bluetooth/BluetoothManager.java
index b5df4db..20152f3 100644
--- a/core/java/android/bluetooth/BluetoothManager.java
+++ b/core/java/android/bluetooth/BluetoothManager.java
@@ -62,15 +62,15 @@
private static final String TAG = "BluetoothManager";
private static final boolean DBG = false;
- private static AttributionSource sAttributionSource = null;
+ private final AttributionSource mAttributionSource;
private final BluetoothAdapter mAdapter;
/**
* @hide
*/
public BluetoothManager(Context context) {
- sAttributionSource = resolveAttributionSource(context);
- mAdapter = BluetoothAdapter.createAdapter(sAttributionSource);
+ mAttributionSource = resolveAttributionSource(context);
+ mAdapter = BluetoothAdapter.createAdapter(mAttributionSource);
}
/** {@hide} */
@@ -79,9 +79,6 @@
if (context != null) {
res = context.getAttributionSource();
}
- else if (sAttributionSource != null) {
- return sAttributionSource;
- }
if (res == null) {
res = ActivityThread.currentAttributionSource();
}
@@ -201,8 +198,8 @@
IBluetoothGatt iGatt = managerService.getBluetoothGatt();
if (iGatt == null) return devices;
devices = Attributable.setAttributionSource(
- iGatt.getDevicesMatchingConnectionStates(states, sAttributionSource),
- sAttributionSource);
+ iGatt.getDevicesMatchingConnectionStates(states, mAttributionSource),
+ mAttributionSource);
} catch (RemoteException e) {
Log.e(TAG, "", e);
}
diff --git a/core/java/android/bluetooth/BluetoothStatusCodes.java b/core/java/android/bluetooth/BluetoothStatusCodes.java
index 3e46c49..63e84ed 100644
--- a/core/java/android/bluetooth/BluetoothStatusCodes.java
+++ b/core/java/android/bluetooth/BluetoothStatusCodes.java
@@ -79,6 +79,11 @@
public static final int ERROR_MISSING_BLUETOOTH_SCAN_PERMISSION = 7;
/**
+ * Error code indicating that the feature is not supported.
+ */
+ public static final int ERROR_FEATURE_NOT_SUPPORTED = 8;
+
+ /**
* If another application has already requested {@link OobData} then another fetch will be
* disallowed until the callback is removed.
*
diff --git a/core/java/android/bluetooth/BluetoothUuid.java b/core/java/android/bluetooth/BluetoothUuid.java
index 858819e..bb537dd 100644
--- a/core/java/android/bluetooth/BluetoothUuid.java
+++ b/core/java/android/bluetooth/BluetoothUuid.java
@@ -189,7 +189,7 @@
@NonNull
@SystemApi
public static final ParcelUuid CAP =
- ParcelUuid.fromString("EEEEEEEE-EEEE-EEEE-EEEE-EEEEEEEEEEEE");
+ ParcelUuid.fromString("00008FE0-0000-1000-8000-00805F9B34FB");
/** @hide */
@NonNull
@SystemApi
diff --git a/core/java/android/bluetooth/UidTraffic.java b/core/java/android/bluetooth/UidTraffic.java
index 2ee786a..9982fa6 100644
--- a/core/java/android/bluetooth/UidTraffic.java
+++ b/core/java/android/bluetooth/UidTraffic.java
@@ -15,6 +15,7 @@
*/
package android.bluetooth;
+import android.annotation.SystemApi;
import android.os.Parcel;
import android.os.Parcelable;
@@ -23,27 +24,27 @@
*
* @hide
*/
-public class UidTraffic implements Cloneable, Parcelable {
+@SystemApi(client = SystemApi.Client.PRIVILEGED_APPS)
+public final class UidTraffic implements Cloneable, Parcelable {
private final int mAppUid;
private long mRxBytes;
private long mTxBytes;
- public UidTraffic(int appUid) {
- mAppUid = appUid;
- }
-
+ /** @hide */
public UidTraffic(int appUid, long rx, long tx) {
mAppUid = appUid;
mRxBytes = rx;
mTxBytes = tx;
}
- UidTraffic(Parcel in) {
+ /** @hide */
+ private UidTraffic(Parcel in) {
mAppUid = in.readInt();
mRxBytes = in.readLong();
mTxBytes = in.readLong();
}
+ /** @hide */
@Override
public void writeToParcel(Parcel dest, int flags) {
dest.writeInt(mAppUid);
@@ -51,44 +52,60 @@
dest.writeLong(mTxBytes);
}
+ /** @hide */
public void setRxBytes(long bytes) {
mRxBytes = bytes;
}
+ /** @hide */
public void setTxBytes(long bytes) {
mTxBytes = bytes;
}
+ /** @hide */
public void addRxBytes(long bytes) {
mRxBytes += bytes;
}
+ /** @hide */
public void addTxBytes(long bytes) {
mTxBytes += bytes;
}
+ /**
+ * @return corresponding app Uid
+ */
public int getUid() {
return mAppUid;
}
+ /**
+ * @return rx bytes count
+ */
public long getRxBytes() {
return mRxBytes;
}
+ /**
+ * @return tx bytes count
+ */
public long getTxBytes() {
return mTxBytes;
}
+ /** @hide */
@Override
public int describeContents() {
return 0;
}
+ /** @hide */
@Override
public UidTraffic clone() {
return new UidTraffic(mAppUid, mRxBytes, mTxBytes);
}
+ /** @hide */
@Override
public String toString() {
return "UidTraffic{mAppUid=" + mAppUid + ", mRxBytes=" + mRxBytes + ", mTxBytes="
diff --git a/core/java/android/bluetooth/le/BluetoothLeUtils.java b/core/java/android/bluetooth/le/BluetoothLeUtils.java
index 6381f55..ed50b09 100644
--- a/core/java/android/bluetooth/le/BluetoothLeUtils.java
+++ b/core/java/android/bluetooth/le/BluetoothLeUtils.java
@@ -24,6 +24,7 @@
import java.util.Map;
import java.util.Objects;
import java.util.Set;
+import java.util.UUID;
/**
* Helper class for Bluetooth LE utils.
@@ -137,4 +138,21 @@
}
}
+ /**
+ * Compares two UUIDs with a UUID mask.
+ *
+ * @param data first {@link #UUID} to compare.
+ * @param uuid second {@link #UUID} to compare.
+ * @param mask mask {@link #UUID}.
+ * @return true if both UUIDs are equals when masked, false otherwise.
+ */
+ static boolean maskedEquals(UUID data, UUID uuid, UUID mask) {
+ if (mask == null) {
+ return Objects.equals(data, uuid);
+ }
+ return (data.getLeastSignificantBits() & mask.getLeastSignificantBits())
+ == (uuid.getLeastSignificantBits() & mask.getLeastSignificantBits())
+ && (data.getMostSignificantBits() & mask.getMostSignificantBits())
+ == (uuid.getMostSignificantBits() & mask.getMostSignificantBits());
+ }
}
diff --git a/core/java/android/bluetooth/le/ScanFilter.java b/core/java/android/bluetooth/le/ScanFilter.java
index 8ff0181..b059193 100644
--- a/core/java/android/bluetooth/le/ScanFilter.java
+++ b/core/java/android/bluetooth/le/ScanFilter.java
@@ -28,8 +28,6 @@
import android.os.ParcelUuid;
import android.os.Parcelable;
-import com.android.internal.util.BitUtils;
-
import java.util.Arrays;
import java.util.List;
import java.util.Objects;
@@ -448,7 +446,7 @@
// Check if the uuid pattern matches the particular service uuid.
private static boolean matchesServiceUuid(UUID uuid, UUID mask, UUID data) {
- return BitUtils.maskedEquals(data, uuid, mask);
+ return BluetoothLeUtils.maskedEquals(data, uuid, mask);
}
/**
@@ -478,7 +476,7 @@
// Check if the solicitation uuid pattern matches the particular service solicitation uuid.
private static boolean matchesServiceSolicitationUuid(UUID solicitationUuid,
UUID solicitationUuidMask, UUID data) {
- return BitUtils.maskedEquals(data, solicitationUuid, solicitationUuidMask);
+ return BluetoothLeUtils.maskedEquals(data, solicitationUuid, solicitationUuidMask);
}
// Check whether the data pattern matches the parsed data.
diff --git a/core/java/android/companion/Association.aidl b/core/java/android/companion/AssociationInfo.aidl
similarity index 95%
rename from core/java/android/companion/Association.aidl
rename to core/java/android/companion/AssociationInfo.aidl
index 2a28f1f..abab743 100644
--- a/core/java/android/companion/Association.aidl
+++ b/core/java/android/companion/AssociationInfo.aidl
@@ -15,4 +15,4 @@
*/
package android.companion;
-parcelable Association;
+parcelable AssociationInfo;
diff --git a/core/java/android/companion/Association.java b/core/java/android/companion/AssociationInfo.java
similarity index 91%
rename from core/java/android/companion/Association.java
rename to core/java/android/companion/AssociationInfo.java
index 7cea33d..ab1eb1f 100644
--- a/core/java/android/companion/Association.java
+++ b/core/java/android/companion/AssociationInfo.java
@@ -39,7 +39,7 @@
* TODO(b/1979395): un-hide and rename to AssociationInfo when implementing public APIs that use
* this class.
*/
-public final class Association implements Parcelable {
+public final class AssociationInfo implements Parcelable {
/**
* A unique ID of this Association record.
* Disclosed to the clients (ie. companion applications) for referring to this record (eg. in
@@ -63,7 +63,7 @@
*
* @hide
*/
- public Association(int associationId, @UserIdInt int userId, @NonNull String packageName,
+ public AssociationInfo(int associationId, @UserIdInt int userId, @NonNull String packageName,
@NonNull List<DeviceId> deviceIds, @Nullable String deviceProfile,
boolean managedByCompanionApp, boolean notifyOnDeviceNearby, long timeApprovedMs) {
if (associationId <= 0) {
@@ -178,8 +178,8 @@
@Override
public boolean equals(Object o) {
if (this == o) return true;
- if (!(o instanceof Association)) return false;
- final Association that = (Association) o;
+ if (!(o instanceof AssociationInfo)) return false;
+ final AssociationInfo that = (AssociationInfo) o;
return mAssociationId == that.mAssociationId
&& mUserId == that.mUserId
&& mManagedByCompanionApp == that.mManagedByCompanionApp
@@ -216,7 +216,7 @@
dest.writeLong(mTimeApprovedMs);
}
- private Association(@NonNull Parcel in) {
+ private AssociationInfo(@NonNull Parcel in) {
mAssociationId = in.readInt();
mUserId = in.readInt();
@@ -230,16 +230,16 @@
mTimeApprovedMs = in.readLong();
}
- public static final Parcelable.Creator<Association> CREATOR =
- new Parcelable.Creator<Association>() {
+ public static final Parcelable.Creator<AssociationInfo> CREATOR =
+ new Parcelable.Creator<AssociationInfo>() {
@Override
- public Association[] newArray(int size) {
- return new Association[size];
+ public AssociationInfo[] newArray(int size) {
+ return new AssociationInfo[size];
}
@Override
- public Association createFromParcel(@NonNull Parcel in) {
- return new Association(in);
+ public AssociationInfo createFromParcel(@NonNull Parcel in) {
+ return new AssociationInfo(in);
}
};
diff --git a/core/java/android/companion/CompanionDeviceManager.java b/core/java/android/companion/CompanionDeviceManager.java
index d42d6b4..a8fe602 100644
--- a/core/java/android/companion/CompanionDeviceManager.java
+++ b/core/java/android/companion/CompanionDeviceManager.java
@@ -319,13 +319,13 @@
}
/**
- * Gets all package-device {@link Association}s for the current user.
+ * Gets all package-device {@link AssociationInfo}s for the current user.
*
* @return the associations list
* @hide
*/
@RequiresPermission(android.Manifest.permission.MANAGE_COMPANION_DEVICES)
- public @NonNull List<Association> getAllAssociations() {
+ public @NonNull List<AssociationInfo> getAllAssociations() {
if (!checkFeaturePresent()) {
return Collections.emptyList();
}
diff --git a/core/java/android/companion/ICompanionDeviceDiscoveryService.aidl b/core/java/android/companion/ICompanionDeviceDiscoveryService.aidl
index 37bd6d1..71e5b24 100644
--- a/core/java/android/companion/ICompanionDeviceDiscoveryService.aidl
+++ b/core/java/android/companion/ICompanionDeviceDiscoveryService.aidl
@@ -28,4 +28,6 @@
in String callingPackage,
in IFindDeviceCallback findCallback,
in AndroidFuture<String> serviceCallback);
+
+ void onAssociationCreated();
}
diff --git a/core/java/android/companion/ICompanionDeviceManager.aidl b/core/java/android/companion/ICompanionDeviceManager.aidl
index 25c5cb3..101f948 100644
--- a/core/java/android/companion/ICompanionDeviceManager.aidl
+++ b/core/java/android/companion/ICompanionDeviceManager.aidl
@@ -18,7 +18,7 @@
import android.app.PendingIntent;
import android.companion.IFindDeviceCallback;
-import android.companion.Association;
+import android.companion.AssociationInfo;
import android.companion.AssociationRequest;
import android.content.ComponentName;
@@ -36,7 +36,7 @@
in String callingPackage);
List<String> getAssociations(String callingPackage, int userId);
- List<Association> getAssociationsForUser(int userId);
+ List<AssociationInfo> getAssociationsForUser(int userId);
void disassociate(String deviceMacAddress, String callingPackage);
diff --git a/core/java/android/companion/Association.aidl b/core/java/android/companion/virtual/IVirtualDevice.aidl
similarity index 74%
copy from core/java/android/companion/Association.aidl
copy to core/java/android/companion/virtual/IVirtualDevice.aidl
index 2a28f1f..0aa442b 100644
--- a/core/java/android/companion/Association.aidl
+++ b/core/java/android/companion/virtual/IVirtualDevice.aidl
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2019 The Android Open Source Project
+ * Copyright (C) 2021 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.
@@ -13,6 +13,14 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-package android.companion;
-parcelable Association;
+package android.companion.virtual;
+
+/**
+ * Interface for a virtual device.
+ *
+ * @hide
+ */
+interface IVirtualDevice {
+ void close();
+}
diff --git a/core/java/android/companion/Association.aidl b/core/java/android/companion/virtual/IVirtualDeviceManager.aidl
similarity index 62%
copy from core/java/android/companion/Association.aidl
copy to core/java/android/companion/virtual/IVirtualDeviceManager.aidl
index 2a28f1f..91e717d 100644
--- a/core/java/android/companion/Association.aidl
+++ b/core/java/android/companion/virtual/IVirtualDeviceManager.aidl
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2019 The Android Open Source Project
+ * Copyright (C) 2021 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.
@@ -13,6 +13,17 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-package android.companion;
-parcelable Association;
+package android.companion.virtual;
+
+import android.companion.virtual.IVirtualDevice;
+
+/**
+ * Interface for communication between VirtualDeviceManager and VirtualDeviceManagerService.
+ *
+ * @hide
+ */
+interface IVirtualDeviceManager {
+
+ IVirtualDevice createVirtualDevice();
+}
diff --git a/core/java/android/companion/virtual/VirtualDeviceManager.java b/core/java/android/companion/virtual/VirtualDeviceManager.java
new file mode 100644
index 0000000..6187de5
--- /dev/null
+++ b/core/java/android/companion/virtual/VirtualDeviceManager.java
@@ -0,0 +1,93 @@
+/*
+ * Copyright (C) 2021 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.companion.virtual;
+
+import android.annotation.NonNull;
+import android.annotation.Nullable;
+import android.annotation.RequiresPermission;
+import android.annotation.SystemApi;
+import android.annotation.SystemService;
+import android.content.Context;
+import android.os.RemoteException;
+
+/**
+ * System level service for managing virtual devices.
+ *
+ * @hide
+ */
+@SystemApi
+@SystemService(Context.VIRTUAL_DEVICE_SERVICE)
+public final class VirtualDeviceManager {
+
+ private static final boolean DEBUG = false;
+ private static final String LOG_TAG = "VirtualDeviceManager";
+
+ private final IVirtualDeviceManager mService;
+ private final Context mContext;
+
+ /** @hide */
+ public VirtualDeviceManager(
+ @Nullable IVirtualDeviceManager service, @NonNull Context context) {
+ mService = service;
+ mContext = context;
+ }
+
+ /**
+ * Creates a virtual device.
+ *
+ * @hide
+ */
+ @RequiresPermission(android.Manifest.permission.CREATE_VIRTUAL_DEVICE)
+ @Nullable
+ public VirtualDevice createVirtualDevice() {
+ // TODO(b/194949534): Add CDM association ID here and unhide this API
+ try {
+ IVirtualDevice virtualDevice = mService.createVirtualDevice();
+ return new VirtualDevice(mContext, virtualDevice);
+ } catch (RemoteException e) {
+ throw e.rethrowFromSystemServer();
+ }
+ }
+
+ /**
+ * A virtual device has its own virtual display, audio output, microphone, and camera etc. The
+ * creator of a virtual device can take the output from the virtual display and stream it over
+ * to another device, and inject input events that are received from the remote device.
+ */
+ public static class VirtualDevice implements AutoCloseable {
+
+ private final Context mContext;
+ private final IVirtualDevice mVirtualDevice;
+
+ private VirtualDevice(Context context, IVirtualDevice virtualDevice) {
+ mContext = context.getApplicationContext();
+ mVirtualDevice = virtualDevice;
+ }
+
+ /**
+ * Closes the virtual device, stopping and tearing down any virtual displays,
+ * audio policies, and event injection that's currently in progress.
+ */
+ public void close() {
+ try {
+ mVirtualDevice.close();
+ } catch (RemoteException e) {
+ throw e.rethrowFromSystemServer();
+ }
+ }
+ }
+}
diff --git a/core/java/android/content/Context.java b/core/java/android/content/Context.java
index cfd3417..fc94fb2 100644
--- a/core/java/android/content/Context.java
+++ b/core/java/android/content/Context.java
@@ -3777,6 +3777,7 @@
PRINT_SERVICE,
CONSUMER_IR_SERVICE,
//@hide: TRUST_SERVICE,
+ TV_IAPP_SERVICE,
TV_INPUT_SERVICE,
//@hide: TV_TUNER_RESOURCE_MGR_SERVICE,
//@hide: NETWORK_SCORE_SERVICE,
@@ -3799,6 +3800,7 @@
//@hide: INCIDENT_COMPANION_SERVICE,
//@hide: STATS_COMPANION_SERVICE,
COMPANION_DEVICE_SERVICE,
+ //@hide: VIRTUAL_DEVICE_SERVICE,
CROSS_PROFILE_APPS_SERVICE,
//@hide: SYSTEM_UPDATE_SERVICE,
//@hide: TIME_DETECTOR_SERVICE,
@@ -5262,6 +5264,16 @@
/**
* Use with {@link #getSystemService(String)} to retrieve a
+ * {@link android.companion.virtual.VirtualDeviceManager} for managing virtual devices.
+ *
+ * @see #getSystemService(String)
+ * @see android.companion.virtual.VirtualDeviceManager
+ * @hide
+ */
+ public static final String VIRTUAL_DEVICE_SERVICE = "virtualdevice";
+
+ /**
+ * Use with {@link #getSystemService(String)} to retrieve a
* {@link android.hardware.ConsumerIrManager} for transmitting infrared
* signals from the device.
*
@@ -5280,6 +5292,16 @@
/**
* Use with {@link #getSystemService(String)} to retrieve a
+ * {@link android.media.tv.interactive.TvIAppManager} for interacting with TV interactive
+ * applications (TV iApp) on the device.
+ *
+ * @see #getSystemService(String)
+ * @see android.media.tv.interactive.TvIAppManager
+ */
+ public static final String TV_IAPP_SERVICE = "tv_iapp";
+
+ /**
+ * Use with {@link #getSystemService(String)} to retrieve a
* {@link android.media.tv.TvInputManager} for interacting with TV inputs
* on the device.
*
diff --git a/core/java/android/content/Intent.java b/core/java/android/content/Intent.java
index 6446b44..e838d93 100644
--- a/core/java/android/content/Intent.java
+++ b/core/java/android/content/Intent.java
@@ -32,6 +32,7 @@
import android.annotation.TestApi;
import android.app.ActivityThread;
import android.app.AppGlobals;
+import android.bluetooth.BluetoothDevice;
import android.compat.annotation.UnsupportedAppUsage;
import android.content.pm.ActivityInfo;
import android.content.pm.ApplicationInfo;
@@ -11688,6 +11689,16 @@
if (fromProtectedComponent) {
mLocalFlags |= LOCAL_FLAG_FROM_PROTECTED_COMPONENT;
}
+
+ // Special attribution fix-up logic for any BluetoothDevice extras
+ // passed via Bluetooth intents
+ if (mAction != null && mAction.startsWith("android.bluetooth.")
+ && hasExtra(BluetoothDevice.EXTRA_DEVICE)) {
+ final BluetoothDevice device = getParcelableExtra(BluetoothDevice.EXTRA_DEVICE);
+ if (device != null) {
+ device.prepareToEnterProcess(source);
+ }
+ }
}
/** @hide */
diff --git a/core/java/android/content/OWNERS b/core/java/android/content/OWNERS
index c7f92c9..660368a 100644
--- a/core/java/android/content/OWNERS
+++ b/core/java/android/content/OWNERS
@@ -2,11 +2,9 @@
per-file Context.java = *
per-file ContextWrapper.java = *
per-file Content* = file:/services/core/java/com/android/server/am/OWNERS
-per-file IntentFilter.java = toddke@google.com
-per-file IntentFilter.java = patb@google.com
+per-file IntentFilter.java = file:/PACKAGE_MANAGER_OWNERS
per-file IntentFilter.java = file:/services/core/java/com/android/server/am/OWNERS
-per-file Intent.java = toddke@google.com
-per-file Intent.java = patb@google.com
+per-file Intent.java = file:/PACKAGE_MANAGER_OWNERS
per-file Intent.java = file:/services/core/java/com/android/server/wm/OWNERS
per-file Intent.java = file:/services/core/java/com/android/server/am/OWNERS
per-file AutofillOptions* = file:/core/java/android/service/autofill/OWNERS
diff --git a/core/java/android/content/pm/ActivityInfo.java b/core/java/android/content/pm/ActivityInfo.java
index 172a51a..cbb5c2b 100644
--- a/core/java/android/content/pm/ActivityInfo.java
+++ b/core/java/android/content/pm/ActivityInfo.java
@@ -995,9 +995,10 @@
* OVERRIDE_MIN_ASPECT_RATIO_MEDIUM
* OVERRIDE_MIN_ASPECT_RATIO_LARGE
*
- * If OVERRIDE_MIN_ASPECT_RATIO is applied, the min aspect ratio given in the app's
- * manifest will be overridden to the largest enabled aspect ratio treatment unless the app's
- * manifest value is higher.
+ * If OVERRIDE_MIN_ASPECT_RATIO is applied, and the activity's orientation is fixed to
+ * portrait, the min aspect ratio given in the app's manifest will be overridden to the
+ * largest enabled aspect ratio treatment unless the app's manifest value is higher.
+ * TODO(b/203647190): add OVERRIDE_MIN_ASPECT_RATIO_PORTRAIT_ONLY instead of portrait by default
* @hide
*/
@ChangeId
@@ -1233,8 +1234,8 @@
* Returns true if the activity has maximum or minimum aspect ratio.
* @hide
*/
- public boolean hasFixedAspectRatio() {
- return getMaxAspectRatio() != 0 || getMinAspectRatio() != 0;
+ public boolean hasFixedAspectRatio(@ScreenOrientation int orientation) {
+ return getMaxAspectRatio() != 0 || getMinAspectRatio(orientation) != 0;
}
/**
@@ -1393,10 +1394,14 @@
* {@code getManifestMinAspectRatio}.
* @hide
*/
- public float getMinAspectRatio() {
+ public float getMinAspectRatio(@ScreenOrientation int orientation) {
+ // TODO(b/203647190): check orientation only if OVERRIDE_MIN_ASPECT_RATIO_PORTRAIT_ONLY
+ // In case the activity's orientation isn't fixed to portrait, OVERRIDE_MIN_ASPECT_RATIO
+ // shouldn't be applied.
if (applicationInfo == null || !CompatChanges.isChangeEnabled(OVERRIDE_MIN_ASPECT_RATIO,
applicationInfo.packageName,
- UserHandle.getUserHandleForUid(applicationInfo.uid))) {
+ UserHandle.getUserHandleForUid(applicationInfo.uid))
+ || !isFixedOrientationPortrait(orientation)) {
return mMinAspectRatio;
}
@@ -1522,9 +1527,10 @@
if (getMaxAspectRatio() != 0) {
pw.println(prefix + "maxAspectRatio=" + getMaxAspectRatio());
}
- if (getMinAspectRatio() != 0) {
- pw.println(prefix + "minAspectRatio=" + getMinAspectRatio());
- if (getManifestMinAspectRatio() != getMinAspectRatio()) {
+ final float minAspectRatio = getMinAspectRatio(screenOrientation);
+ if (minAspectRatio != 0) {
+ pw.println(prefix + "minAspectRatio=" + minAspectRatio);
+ if (getManifestMinAspectRatio() != minAspectRatio) {
pw.println(prefix + "getManifestMinAspectRatio=" + getManifestMinAspectRatio());
}
}
diff --git a/core/java/android/content/pm/TEST_MAPPING b/core/java/android/content/pm/TEST_MAPPING
index 0d8fdcc..cc4782a 100644
--- a/core/java/android/content/pm/TEST_MAPPING
+++ b/core/java/android/content/pm/TEST_MAPPING
@@ -1,6 +1,15 @@
{
"imports": [
{
+ "path": "frameworks/base/services/tests/PackageManagerServiceTests"
+ },
+ {
+ "path": "frameworks/base/services/tests/PackageManager"
+ },
+ {
+ "path": "frameworks/base/services/tests/PackageManagerComponentOverrideTests"
+ },
+ {
"path": "cts/tests/tests/packageinstaller"
},
{
diff --git a/core/java/android/content/res/AssetFileDescriptor.java b/core/java/android/content/res/AssetFileDescriptor.java
index e93ec00..dd00c3a 100644
--- a/core/java/android/content/res/AssetFileDescriptor.java
+++ b/core/java/android/content/res/AssetFileDescriptor.java
@@ -21,6 +21,8 @@
import android.os.Parcel;
import android.os.ParcelFileDescriptor;
import android.os.Parcelable;
+import android.system.ErrnoException;
+import android.system.Os;
import java.io.Closeable;
import java.io.FileDescriptor;
@@ -40,7 +42,7 @@
* the data extends to the end of the file.
*/
public static final long UNKNOWN_LENGTH = -1;
-
+
@UnsupportedAppUsage
private final ParcelFileDescriptor mFd;
@UnsupportedAppUsage
@@ -52,11 +54,11 @@
/**
* Create a new AssetFileDescriptor from the given values.
*
- * @param fd The underlying file descriptor.
+ * @param fd The underlying file descriptor.
* @param startOffset The location within the file that the asset starts.
- * This must be 0 if length is UNKNOWN_LENGTH.
- * @param length The number of bytes of the asset, or
- * {@link #UNKNOWN_LENGTH} if it extends to the end of the file.
+ * This must be 0 if length is UNKNOWN_LENGTH.
+ * @param length The number of bytes of the asset, or
+ * {@link #UNKNOWN_LENGTH} if it extends to the end of the file.
*/
public AssetFileDescriptor(ParcelFileDescriptor fd, long startOffset,
long length) {
@@ -66,13 +68,13 @@
/**
* Create a new AssetFileDescriptor from the given values.
*
- * @param fd The underlying file descriptor.
+ * @param fd The underlying file descriptor.
* @param startOffset The location within the file that the asset starts.
- * This must be 0 if length is UNKNOWN_LENGTH.
- * @param length The number of bytes of the asset, or
- * {@link #UNKNOWN_LENGTH} if it extends to the end of the file.
- * @param extras additional details that can be used to interpret the
- * underlying file descriptor. May be null.
+ * This must be 0 if length is UNKNOWN_LENGTH.
+ * @param length The number of bytes of the asset, or
+ * {@link #UNKNOWN_LENGTH} if it extends to the end of the file.
+ * @param extras additional details that can be used to interpret the
+ * underlying file descriptor. May be null.
*/
public AssetFileDescriptor(ParcelFileDescriptor fd, long startOffset,
long length, Bundle extras) {
@@ -97,7 +99,7 @@
public ParcelFileDescriptor getParcelFileDescriptor() {
return mFd;
}
-
+
/**
* Returns the FileDescriptor that can be used to read the data in the
* file.
@@ -105,7 +107,7 @@
public FileDescriptor getFileDescriptor() {
return mFd.getFileDescriptor();
}
-
+
/**
* Returns the byte offset where this asset entry's data starts.
*/
@@ -129,7 +131,7 @@
* ParcelFileDescriptor.getStatSize()} to find the total size of the file,
* returning that number if found or {@link #UNKNOWN_LENGTH} if it could
* not be determined.
- *
+ *
* @see #getDeclaredLength()
*/
public long getLength() {
@@ -139,19 +141,19 @@
long len = mFd.getStatSize();
return len >= 0 ? len : UNKNOWN_LENGTH;
}
-
+
/**
* Return the actual number of bytes that were declared when the
* AssetFileDescriptor was constructed. Will be
* {@link #UNKNOWN_LENGTH} if the length was not declared, meaning data
* should be read to the end of the file.
- *
+ *
* @see #getDeclaredLength()
*/
public long getDeclaredLength() {
return mLength;
}
-
+
/**
* Convenience for calling <code>getParcelFileDescriptor().close()</code>.
*/
@@ -174,7 +176,7 @@
}
return new AutoCloseInputStream(this);
}
-
+
/**
* Create and return a new auto-close output stream for this asset. This
* will either return a full asset {@link AutoCloseOutputStream}, or
@@ -189,13 +191,13 @@
}
return new AutoCloseOutputStream(this);
}
-
+
@Override
public String toString() {
return "{AssetFileDescriptor: " + mFd
+ " start=" + mStartOffset + " len=" + mLength + "}";
}
-
+
/**
* An InputStream you can create on a ParcelFileDescriptor, which will
* take care of calling {@link ParcelFileDescriptor#close
@@ -203,19 +205,24 @@
*/
public static class AutoCloseInputStream
extends ParcelFileDescriptor.AutoCloseInputStream {
- private long mRemaining;
-
+ private final long mSizeFromStartOffset;
+ private final long mStartOffset;
+ private long mPosFromStartOffset;
+
public AutoCloseInputStream(AssetFileDescriptor fd) throws IOException {
super(fd.getParcelFileDescriptor());
+ // this skip is necessary if getChannel() is called
super.skip(fd.getStartOffset());
- mRemaining = (int)fd.getLength();
+ mSizeFromStartOffset = fd.getLength();
+ mStartOffset = fd.getStartOffset();
}
@Override
public int available() throws IOException {
- return mRemaining >= 0
- ? (mRemaining < 0x7fffffff ? (int)mRemaining : 0x7fffffff)
- : super.available();
+ long available = mSizeFromStartOffset - mPosFromStartOffset;
+ return available >= 0
+ ? (available < 0x7fffffff ? (int) available : 0x7fffffff)
+ : 0;
}
@Override
@@ -227,15 +234,24 @@
@Override
public int read(byte[] buffer, int offset, int count) throws IOException {
- if (mRemaining >= 0) {
- if (mRemaining == 0) return -1;
- if (count > mRemaining) count = (int)mRemaining;
- int res = super.read(buffer, offset, count);
- if (res >= 0) mRemaining -= res;
- return res;
+ int available = available();
+
+ if (available <= 0) {
+ return -1;
+ } else {
+ if (count > available) count = available;
+ try {
+ int res = Os.pread(getFD(), buffer, offset, count,
+ mStartOffset + mPosFromStartOffset);
+ // pread returns 0 at end of file, while java's InputStream interface
+ // requires -1
+ if (res == 0) res = -1;
+ if (res >= 0) mPosFromStartOffset += res;
+ return res;
+ } catch (ErrnoException e) {
+ throw new IOException(e);
+ }
}
-
- return super.read(buffer, offset, count);
}
@Override
@@ -245,41 +261,31 @@
@Override
public long skip(long count) throws IOException {
- if (mRemaining >= 0) {
- if (mRemaining == 0) return -1;
- if (count > mRemaining) count = mRemaining;
- long res = super.skip(count);
- if (res >= 0) mRemaining -= res;
- return res;
+ int available = available();
+ if (available <= 0) {
+ return -1;
+ } else {
+ if (count > available) count = available;
+ mPosFromStartOffset += count;
+ return count;
}
-
- return super.skip(count);
}
@Override
public void mark(int readlimit) {
- if (mRemaining >= 0) {
- // Not supported.
- return;
- }
- super.mark(readlimit);
+ // Not supported.
+ return;
}
@Override
public boolean markSupported() {
- if (mRemaining >= 0) {
- return false;
- }
- return super.markSupported();
+ return false;
}
@Override
public synchronized void reset() throws IOException {
- if (mRemaining >= 0) {
- // Not supported.
- return;
- }
- super.reset();
+ // Not supported.
+ return;
}
}
@@ -291,25 +297,25 @@
public static class AutoCloseOutputStream
extends ParcelFileDescriptor.AutoCloseOutputStream {
private long mRemaining;
-
+
public AutoCloseOutputStream(AssetFileDescriptor fd) throws IOException {
super(fd.getParcelFileDescriptor());
if (fd.getParcelFileDescriptor().seekTo(fd.getStartOffset()) < 0) {
throw new IOException("Unable to seek");
}
- mRemaining = (int)fd.getLength();
+ mRemaining = (int) fd.getLength();
}
@Override
public void write(byte[] buffer, int offset, int count) throws IOException {
if (mRemaining >= 0) {
if (mRemaining == 0) return;
- if (count > mRemaining) count = (int)mRemaining;
+ if (count > mRemaining) count = (int) mRemaining;
super.write(buffer, offset, count);
mRemaining -= count;
return;
}
-
+
super.write(buffer, offset, count);
}
@@ -318,12 +324,12 @@
if (mRemaining >= 0) {
if (mRemaining == 0) return;
int count = buffer.length;
- if (count > mRemaining) count = (int)mRemaining;
+ if (count > mRemaining) count = (int) mRemaining;
super.write(buffer);
mRemaining -= count;
return;
}
-
+
super.write(buffer);
}
@@ -335,7 +341,7 @@
mRemaining--;
return;
}
-
+
super.write(oneByte);
}
}
@@ -375,6 +381,7 @@
public AssetFileDescriptor createFromParcel(Parcel in) {
return new AssetFileDescriptor(in);
}
+
public AssetFileDescriptor[] newArray(int size) {
return new AssetFileDescriptor[size];
}
diff --git a/core/java/android/hardware/SensorDirectChannel.java b/core/java/android/hardware/SensorDirectChannel.java
index 214d3ec..293d8b0 100644
--- a/core/java/android/hardware/SensorDirectChannel.java
+++ b/core/java/android/hardware/SensorDirectChannel.java
@@ -64,7 +64,7 @@
/** @hide */
@Retention(RetentionPolicy.SOURCE)
- @IntDef(flag = true, prefix = { "RATE_" }, value = {
+ @IntDef(prefix = { "RATE_" }, value = {
RATE_STOP,
RATE_NORMAL,
RATE_FAST,
diff --git a/core/java/android/hardware/camera2/CameraExtensionCharacteristics.java b/core/java/android/hardware/camera2/CameraExtensionCharacteristics.java
index 395c655..5c636c7 100644
--- a/core/java/android/hardware/camera2/CameraExtensionCharacteristics.java
+++ b/core/java/android/hardware/camera2/CameraExtensionCharacteristics.java
@@ -15,12 +15,13 @@
*/
package android.hardware.camera2;
+import android.annotation.IntDef;
+import android.annotation.NonNull;
import android.annotation.Nullable;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.ServiceConnection;
-import android.content.pm.PackageManager;
import android.graphics.ImageFormat;
import android.hardware.camera2.extension.IAdvancedExtenderImpl;
import android.hardware.camera2.extension.ICameraExtensionsProxyService;
@@ -35,24 +36,22 @@
import android.os.IBinder;
import android.os.RemoteException;
import android.os.SystemProperties;
-import android.annotation.IntDef;
-import android.annotation.NonNull;
import android.util.Log;
import android.util.Pair;
import android.util.Range;
import android.util.Size;
-import java.util.HashSet;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Objects;
import java.util.concurrent.Future;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException;
-import java.util.List;
-import java.util.Objects;
/**
* <p>Allows clients to query availability and supported resolutions of camera extensions.</p>
@@ -96,7 +95,15 @@
* Device-specific extension implementation which tends to smooth the skin and apply other
* cosmetic effects to people's faces.
*/
- public static final int EXTENSION_BEAUTY = 1;
+ public static final int EXTENSION_FACE_RETOUCH = 1;
+
+ /**
+ * Device-specific extension implementation which tends to smooth the skin and apply other
+ * cosmetic effects to people's faces.
+ *
+ * @deprecated Use {@link #EXTENSION_FACE_RETOUCH} instead.
+ */
+ public @Deprecated static final int EXTENSION_BEAUTY = EXTENSION_FACE_RETOUCH;
/**
* Device-specific extension implementation which can blur certain regions of the final image
@@ -121,7 +128,7 @@
*/
@Retention(RetentionPolicy.SOURCE)
@IntDef(flag = true, value = {EXTENSION_AUTOMATIC,
- EXTENSION_BEAUTY,
+ EXTENSION_FACE_RETOUCH,
EXTENSION_BOKEH,
EXTENSION_HDR,
EXTENSION_NIGHT})
@@ -145,7 +152,7 @@
private static final @Extension
int[] EXTENSION_LIST = new int[]{
EXTENSION_AUTOMATIC,
- EXTENSION_BEAUTY,
+ EXTENSION_FACE_RETOUCH,
EXTENSION_BOKEH,
EXTENSION_HDR,
EXTENSION_NIGHT};
diff --git a/core/java/android/net/NetworkIdentity.java b/core/java/android/net/NetworkIdentity.java
index 1d07a03..eb8f43e 100644
--- a/core/java/android/net/NetworkIdentity.java
+++ b/core/java/android/net/NetworkIdentity.java
@@ -220,8 +220,10 @@
String networkId = null;
boolean roaming = !snapshot.getNetworkCapabilities().hasCapability(
NetworkCapabilities.NET_CAPABILITY_NOT_ROAMING);
- boolean metered = !snapshot.getNetworkCapabilities().hasCapability(
- NetworkCapabilities.NET_CAPABILITY_NOT_METERED);
+ boolean metered = !(snapshot.getNetworkCapabilities().hasCapability(
+ NetworkCapabilities.NET_CAPABILITY_NOT_METERED)
+ || snapshot.getNetworkCapabilities().hasCapability(
+ NetworkCapabilities.NET_CAPABILITY_TEMPORARILY_NOT_METERED));
final int oemManaged = getOemBitfield(snapshot.getNetworkCapabilities());
diff --git a/core/java/android/net/NetworkTemplate.java b/core/java/android/net/NetworkTemplate.java
index 08f75df..74506da 100644
--- a/core/java/android/net/NetworkTemplate.java
+++ b/core/java/android/net/NetworkTemplate.java
@@ -160,19 +160,19 @@
}
/**
- * Template to match cellular networks with the given IMSI and {@code ratType}.
- * Use {@link #NETWORK_TYPE_ALL} to include all network types when filtering.
- * See {@code TelephonyManager.NETWORK_TYPE_*}.
+ * Template to match cellular networks with the given IMSI, {@code ratType} and
+ * {@code metered}. Use {@link #NETWORK_TYPE_ALL} to include all network types when
+ * filtering. See {@code TelephonyManager.NETWORK_TYPE_*}.
*/
public static NetworkTemplate buildTemplateMobileWithRatType(@Nullable String subscriberId,
- @NetworkType int ratType) {
+ @NetworkType int ratType, int metered) {
if (TextUtils.isEmpty(subscriberId)) {
return new NetworkTemplate(MATCH_MOBILE_WILDCARD, null, null, null,
- METERED_ALL, ROAMING_ALL, DEFAULT_NETWORK_ALL, ratType, OEM_MANAGED_ALL,
+ metered, ROAMING_ALL, DEFAULT_NETWORK_ALL, ratType, OEM_MANAGED_ALL,
SUBSCRIBER_ID_MATCH_RULE_EXACT);
}
return new NetworkTemplate(MATCH_MOBILE, subscriberId, new String[]{subscriberId}, null,
- METERED_ALL, ROAMING_ALL, DEFAULT_NETWORK_ALL, ratType, OEM_MANAGED_ALL,
+ metered, ROAMING_ALL, DEFAULT_NETWORK_ALL, ratType, OEM_MANAGED_ALL,
SUBSCRIBER_ID_MATCH_RULE_EXACT);
}
@@ -305,6 +305,7 @@
}
}
+ // TODO: Deprecate this constructor, mark it @UnsupportedAppUsage(maxTargetSdk = S)
@UnsupportedAppUsage
public NetworkTemplate(int matchRule, String subscriberId, String networkId) {
this(matchRule, subscriberId, new String[] { subscriberId }, networkId);
@@ -312,9 +313,14 @@
public NetworkTemplate(int matchRule, String subscriberId, String[] matchSubscriberIds,
String networkId) {
- this(matchRule, subscriberId, matchSubscriberIds, networkId, METERED_ALL, ROAMING_ALL,
- DEFAULT_NETWORK_ALL, NETWORK_TYPE_ALL, OEM_MANAGED_ALL,
- SUBSCRIBER_ID_MATCH_RULE_EXACT);
+ // Older versions used to only match MATCH_MOBILE and MATCH_MOBILE_WILDCARD templates
+ // to metered networks. It is now possible to match mobile with any meteredness, but
+ // in order to preserve backward compatibility of @UnsupportedAppUsage methods, this
+ //constructor passes METERED_YES for these types.
+ this(matchRule, subscriberId, matchSubscriberIds, networkId,
+ (matchRule == MATCH_MOBILE || matchRule == MATCH_MOBILE_WILDCARD) ? METERED_YES
+ : METERED_ALL , ROAMING_ALL, DEFAULT_NETWORK_ALL, NETWORK_TYPE_ALL,
+ OEM_MANAGED_ALL, SUBSCRIBER_ID_MATCH_RULE_EXACT);
}
// TODO: Remove it after updating all of the caller.
@@ -589,11 +595,7 @@
// TODO: consider matching against WiMAX subscriber identity
return true;
} else {
- // Only metered mobile network would be matched regardless of metered filter.
- // This is used to exclude non-metered APNs, e.g. IMS. See ag/908650.
- // TODO: Respect metered filter and remove mMetered condition.
- return (ident.mType == TYPE_MOBILE && ident.mMetered)
- && !ArrayUtils.isEmpty(mMatchSubscriberIds)
+ return ident.mType == TYPE_MOBILE && !ArrayUtils.isEmpty(mMatchSubscriberIds)
&& ArrayUtils.contains(mMatchSubscriberIds, ident.mSubscriberId)
&& matchesCollapsedRatType(ident);
}
@@ -707,8 +709,7 @@
if (ident.mType == TYPE_WIMAX) {
return true;
} else {
- return (ident.mType == TYPE_MOBILE && ident.mMetered)
- && matchesCollapsedRatType(ident);
+ return ident.mType == TYPE_MOBILE && matchesCollapsedRatType(ident);
}
}
diff --git a/core/java/android/os/BatteryConsumer.java b/core/java/android/os/BatteryConsumer.java
index 1c1fc2c..ba9332d 100644
--- a/core/java/android/os/BatteryConsumer.java
+++ b/core/java/android/os/BatteryConsumer.java
@@ -174,7 +174,7 @@
public static final int PROCESS_STATE_BACKGROUND = 2;
public static final int PROCESS_STATE_FOREGROUND_SERVICE = 3;
- static final int PROCESS_STATE_COUNT = 4;
+ public static final int PROCESS_STATE_COUNT = 4;
private static final String[] sProcessStateNames = new String[PROCESS_STATE_COUNT];
@@ -757,6 +757,11 @@
}
@Nullable
+ public Key[] getKeys(@PowerComponent int componentId) {
+ return mData.getKeys(componentId);
+ }
+
+ @Nullable
public Key getKey(@PowerComponent int componentId, @ProcessState int processState) {
return mData.getKey(componentId, processState);
}
diff --git a/core/java/android/os/BatteryStats.java b/core/java/android/os/BatteryStats.java
index 30613b9..be36027 100644
--- a/core/java/android/os/BatteryStats.java
+++ b/core/java/android/os/BatteryStats.java
@@ -654,6 +654,25 @@
}
/**
+ * Maps BatteryStats.Uid process state to the BatteryConsumer process state.
+ */
+ public static @BatteryConsumer.ProcessState int
+ mapUidProcessStateToBatteryConsumerProcessState(int processState) {
+ switch (processState) {
+ case BatteryStats.Uid.PROCESS_STATE_TOP:
+ case BatteryStats.Uid.PROCESS_STATE_FOREGROUND:
+ return BatteryConsumer.PROCESS_STATE_FOREGROUND;
+ case BatteryStats.Uid.PROCESS_STATE_BACKGROUND:
+ case BatteryStats.Uid.PROCESS_STATE_TOP_SLEEPING:
+ return BatteryConsumer.PROCESS_STATE_BACKGROUND;
+ case BatteryStats.Uid.PROCESS_STATE_FOREGROUND_SERVICE:
+ return BatteryConsumer.PROCESS_STATE_FOREGROUND_SERVICE;
+ default:
+ return BatteryConsumer.PROCESS_STATE_ANY;
+ }
+ }
+
+ /**
* Returns true if battery consumption is tracked on a per-process-state basis.
*/
public abstract boolean isProcessStateDataAvailable();
@@ -1010,6 +1029,16 @@
public abstract long getCpuMeasuredBatteryConsumptionUC();
/**
+ * Returns the battery consumption (in microcoulombs) of the uid's cpu usage when in the
+ * specified process state.
+ * Will return {@link #POWER_DATA_UNAVAILABLE} if data is unavailable.
+ *
+ * {@hide}
+ */
+ public abstract long getCpuMeasuredBatteryConsumptionUC(
+ @BatteryConsumer.ProcessState int processState);
+
+ /**
* Returns the battery consumption (in microcoulombs) of the uid's GNSS usage, derived from
* on device power measurement data.
* Will return {@link #POWER_DATA_UNAVAILABLE} if data is unavailable.
diff --git a/core/java/android/os/BatteryUsageStatsQuery.java b/core/java/android/os/BatteryUsageStatsQuery.java
index 187b64f..81e49e9 100644
--- a/core/java/android/os/BatteryUsageStatsQuery.java
+++ b/core/java/android/os/BatteryUsageStatsQuery.java
@@ -111,6 +111,10 @@
return (mFlags & FLAG_BATTERY_USAGE_STATS_POWER_PROFILE_MODEL) != 0;
}
+ public boolean isProcessStateDataNeeded() {
+ return (mFlags & FLAG_BATTERY_USAGE_STATS_INCLUDE_PROCESS_STATE_DATA) != 0;
+ }
+
/**
* Returns the client's tolerance for stale battery stats. The data is allowed to be up to
* this many milliseconds out-of-date.
diff --git a/core/java/android/os/Binder.java b/core/java/android/os/Binder.java
index 635f581..b677b69 100644
--- a/core/java/android/os/Binder.java
+++ b/core/java/android/os/Binder.java
@@ -313,7 +313,7 @@
* @hide
*/
@CriticalNative
- public static final native boolean isHandlingTransaction();
+ public static final native boolean isDirectlyHandlingTransaction();
/**
* Return the Linux uid assigned to the process that sent the transaction
@@ -323,7 +323,7 @@
* executing an incoming transaction.
*/
public static final int getCallingUidOrThrow() {
- if (!isHandlingTransaction()) {
+ if (!isDirectlyHandlingTransaction()) {
throw new IllegalStateException(
"Thread is not in a binder transcation");
}
diff --git a/core/java/android/os/Build.java b/core/java/android/os/Build.java
index 394d270..743468a 100755
--- a/core/java/android/os/Build.java
+++ b/core/java/android/os/Build.java
@@ -1024,7 +1024,7 @@
* will also enable {@link StrictMode.ThreadPolicy.Builder#detectUnbufferedIo}.</li>
* <li>{@link android.provider.DocumentsContract}'s various methods will throw failure
* exceptions back to the caller instead of returning null.
- * <li>{@link View#hasFocusable View.hasFocusable} now includes auto-focusable views.</li>
+ * <li>{@link View#hasFocusable() View.hasFocusable} now includes auto-focusable views.</li>
* <li>{@link android.view.SurfaceView} will no longer always change the underlying
* Surface object when something about it changes; apps need to look at the current
* state of the object to determine which things they are interested in have changed.</li>
@@ -1132,6 +1132,13 @@
public static final int S = 31;
/**
+ * S V2.
+ *
+ * Once more unto the breach, dear friends, once more.
+ */
+ public static final int S_V2 = 32;
+
+ /**
* Tiramisu.
*/
public static final int TIRAMISU = CUR_DEVELOPMENT;
diff --git a/core/java/android/os/BytesMatcher.java b/core/java/android/os/BytesMatcher.java
deleted file mode 100644
index 8974c5e..0000000
--- a/core/java/android/os/BytesMatcher.java
+++ /dev/null
@@ -1,315 +0,0 @@
-/*
- * Copyright (C) 2021 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.os;
-
-import android.annotation.NonNull;
-import android.annotation.Nullable;
-import android.bluetooth.BluetoothUuid;
-import android.net.MacAddress;
-import android.text.TextUtils;
-import android.util.Log;
-
-import com.android.internal.util.HexDump;
-
-import java.util.ArrayList;
-import java.util.function.Predicate;
-
-/**
- * Predicate that tests if a given {@code byte[]} value matches a set of
- * configured rules.
- * <p>
- * Rules are tested in the order in which they were originally added, which
- * means a narrow rule can reject a specific value before a later broader rule
- * might accept that same value, or vice versa.
- * <p>
- * Matchers can contain rules of varying lengths, and tested values will only be
- * matched against rules of the exact same length. This is designed to support
- * {@link BluetoothUuid} style values which can be variable length.
- *
- * @hide
- */
-public class BytesMatcher implements Predicate<byte[]> {
- private static final String TAG = "BytesMatcher";
-
- private static final char TYPE_EXACT_ACCEPT = '+';
- private static final char TYPE_EXACT_REJECT = '-';
- private static final char TYPE_PREFIX_ACCEPT = '⊆';
- private static final char TYPE_PREFIX_REJECT = '⊈';
-
- private final ArrayList<Rule> mRules = new ArrayList<>();
-
- private static class Rule {
- public final char type;
- public final @NonNull byte[] value;
- public final @Nullable byte[] mask;
-
- public Rule(char type, @NonNull byte[] value, @Nullable byte[] mask) {
- if (mask != null && value.length != mask.length) {
- throw new IllegalArgumentException(
- "Expected length " + value.length + " but found " + mask.length);
- }
- this.type = type;
- this.value = value;
- this.mask = mask;
- }
-
- @Override
- public String toString() {
- StringBuilder builder = new StringBuilder();
- encode(builder);
- return builder.toString();
- }
-
- public void encode(@NonNull StringBuilder builder) {
- builder.append(type);
- builder.append(HexDump.toHexString(value));
- if (mask != null) {
- builder.append('/');
- builder.append(HexDump.toHexString(mask));
- }
- }
-
- public boolean test(@NonNull byte[] value) {
- switch (type) {
- case TYPE_EXACT_ACCEPT:
- case TYPE_EXACT_REJECT:
- if (value.length != this.value.length) {
- return false;
- }
- break;
- case TYPE_PREFIX_ACCEPT:
- case TYPE_PREFIX_REJECT:
- if (value.length < this.value.length) {
- return false;
- }
- break;
- }
- for (int i = 0; i < this.value.length; i++) {
- byte local = this.value[i];
- byte remote = value[i];
- if (this.mask != null) {
- local &= this.mask[i];
- remote &= this.mask[i];
- }
- if (local != remote) {
- return false;
- }
- }
- return true;
- }
- }
-
- /**
- * Add a rule that will result in {@link #test(byte[])} returning
- * {@code true} when a value being tested matches it. This rule will only
- * match values of the exact same length.
- * <p>
- * Rules are tested in the order in which they were originally added, which
- * means a narrow rule can reject a specific value before a later broader
- * rule might accept that same value, or vice versa.
- *
- * @param value to be matched
- * @param mask to be applied to both values before testing for equality; if
- * {@code null} then both values must match exactly
- */
- public void addExactAcceptRule(@NonNull byte[] value, @Nullable byte[] mask) {
- mRules.add(new Rule(TYPE_EXACT_ACCEPT, value, mask));
- }
-
- /**
- * Add a rule that will result in {@link #test(byte[])} returning
- * {@code false} when a value being tested matches it. This rule will only
- * match values of the exact same length.
- * <p>
- * Rules are tested in the order in which they were originally added, which
- * means a narrow rule can reject a specific value before a later broader
- * rule might accept that same value, or vice versa.
- *
- * @param value to be matched
- * @param mask to be applied to both values before testing for equality; if
- * {@code null} then both values must match exactly
- */
- public void addExactRejectRule(@NonNull byte[] value, @Nullable byte[] mask) {
- mRules.add(new Rule(TYPE_EXACT_REJECT, value, mask));
- }
-
- /**
- * Add a rule that will result in {@link #test(byte[])} returning
- * {@code true} when a value being tested matches it. This rule will match
- * values of the exact same length or longer.
- * <p>
- * Rules are tested in the order in which they were originally added, which
- * means a narrow rule can reject a specific value before a later broader
- * rule might accept that same value, or vice versa.
- *
- * @param value to be matched
- * @param mask to be applied to both values before testing for equality; if
- * {@code null} then both values must match exactly
- */
- public void addPrefixAcceptRule(@NonNull byte[] value, @Nullable byte[] mask) {
- mRules.add(new Rule(TYPE_PREFIX_ACCEPT, value, mask));
- }
-
- /**
- * Add a rule that will result in {@link #test(byte[])} returning
- * {@code false} when a value being tested matches it. This rule will match
- * values of the exact same length or longer.
- * <p>
- * Rules are tested in the order in which they were originally added, which
- * means a narrow rule can reject a specific value before a later broader
- * rule might accept that same value, or vice versa.
- *
- * @param value to be matched
- * @param mask to be applied to both values before testing for equality; if
- * {@code null} then both values must match exactly
- */
- public void addPrefixRejectRule(@NonNull byte[] value, @Nullable byte[] mask) {
- mRules.add(new Rule(TYPE_PREFIX_REJECT, value, mask));
- }
-
- /**
- * Test if the given {@code ParcelUuid} value matches the set of rules
- * configured in this matcher.
- */
- public boolean testBluetoothUuid(@NonNull ParcelUuid value) {
- return test(BluetoothUuid.uuidToBytes(value));
- }
-
- /**
- * Test if the given {@code MacAddress} value matches the set of rules
- * configured in this matcher.
- */
- public boolean testMacAddress(@NonNull MacAddress value) {
- return test(value.toByteArray());
- }
-
- /**
- * Test if the given {@code byte[]} value matches the set of rules
- * configured in this matcher.
- */
- @Override
- public boolean test(@NonNull byte[] value) {
- return test(value, false);
- }
-
- /**
- * Test if the given {@code byte[]} value matches the set of rules
- * configured in this matcher.
- */
- public boolean test(@NonNull byte[] value, boolean defaultValue) {
- final int size = mRules.size();
- for (int i = 0; i < size; i++) {
- final Rule rule = mRules.get(i);
- if (rule.test(value)) {
- switch (rule.type) {
- case TYPE_EXACT_ACCEPT:
- case TYPE_PREFIX_ACCEPT:
- return true;
- case TYPE_EXACT_REJECT:
- case TYPE_PREFIX_REJECT:
- return false;
- }
- }
- }
- return defaultValue;
- }
-
- /**
- * Encode the given matcher into a human-readable {@link String} which can
- * be used to transport matchers across device boundaries.
- * <p>
- * The human-readable format is an ordered list separated by commas, where
- * each rule is a {@code +} or {@code -} symbol indicating if the match
- * should be accepted or rejected, then followed by a hex value and an
- * optional hex mask. For example, {@code -caff,+cafe/ff00} is a valid
- * encoded matcher.
- *
- * @see #decode(String)
- */
- public static @NonNull String encode(@NonNull BytesMatcher matcher) {
- final StringBuilder builder = new StringBuilder();
- final int size = matcher.mRules.size();
- for (int i = 0; i < size; i++) {
- final Rule rule = matcher.mRules.get(i);
- rule.encode(builder);
- builder.append(',');
- }
- if (builder.length() > 0) {
- builder.deleteCharAt(builder.length() - 1);
- }
- return builder.toString();
- }
-
- /**
- * Decode the given human-readable {@link String} used to transport matchers
- * across device boundaries.
- * <p>
- * The human-readable format is an ordered list separated by commas, where
- * each rule is a {@code +} or {@code -} symbol indicating if the match
- * should be accepted or rejected, then followed by a hex value and an
- * optional hex mask. For example, {@code -caff,+cafe/ff00} is a valid
- * encoded matcher.
- *
- * @see #encode(BytesMatcher)
- */
- public static @NonNull BytesMatcher decode(@Nullable String value) {
- final BytesMatcher matcher = new BytesMatcher();
- if (TextUtils.isEmpty(value)) return matcher;
-
- final int length = value.length();
- for (int i = 0; i < length;) {
- final char type = value.charAt(i);
-
- int nextRule = value.indexOf(',', i);
- int nextMask = value.indexOf('/', i);
-
- if (nextRule == -1) nextRule = length;
- if (nextMask > nextRule) nextMask = -1;
-
- final byte[] ruleValue;
- final byte[] ruleMask;
- if (nextMask >= 0) {
- ruleValue = HexDump.hexStringToByteArray(value.substring(i + 1, nextMask));
- ruleMask = HexDump.hexStringToByteArray(value.substring(nextMask + 1, nextRule));
- } else {
- ruleValue = HexDump.hexStringToByteArray(value.substring(i + 1, nextRule));
- ruleMask = null;
- }
-
- switch (type) {
- case TYPE_EXACT_ACCEPT:
- matcher.addExactAcceptRule(ruleValue, ruleMask);
- break;
- case TYPE_EXACT_REJECT:
- matcher.addExactRejectRule(ruleValue, ruleMask);
- break;
- case TYPE_PREFIX_ACCEPT:
- matcher.addPrefixAcceptRule(ruleValue, ruleMask);
- break;
- case TYPE_PREFIX_REJECT:
- matcher.addPrefixRejectRule(ruleValue, ruleMask);
- break;
- default:
- Log.w(TAG, "Ignoring unknown type " + type);
- break;
- }
-
- i = nextRule + 1;
- }
- return matcher;
- }
-}
diff --git a/core/java/android/os/Parcel.java b/core/java/android/os/Parcel.java
index ab2c8c0..61882ff 100644
--- a/core/java/android/os/Parcel.java
+++ b/core/java/android/os/Parcel.java
@@ -20,6 +20,7 @@
import android.annotation.NonNull;
import android.annotation.Nullable;
+import android.annotation.SuppressLint;
import android.annotation.TestApi;
import android.app.AppOpsManager;
import android.compat.annotation.UnsupportedAppUsage;
@@ -380,6 +381,8 @@
private static native void nativeUnmarshall(
long nativePtr, byte[] data, int offset, int length);
private static native int nativeCompareData(long thisNativePtr, long otherNativePtr);
+ private static native boolean nativeCompareDataInRange(
+ long ptrA, int offsetA, long ptrB, int offsetB, int length);
private static native void nativeAppendFrom(
long thisNativePtr, long otherNativePtr, int offset, int length);
@CriticalNative
@@ -677,11 +680,16 @@
}
/** @hide */
- public final int compareData(Parcel other) {
+ public int compareData(Parcel other) {
return nativeCompareData(mNativePtr, other.mNativePtr);
}
/** @hide */
+ public static boolean compareData(Parcel a, int offsetA, Parcel b, int offsetB, int length) {
+ return nativeCompareDataInRange(a.mNativePtr, offsetA, b.mNativePtr, offsetB, length);
+ }
+
+ /** @hide */
public final void setClassCookie(Class clz, Object cookie) {
if (mClassCookies == null) {
mClassCookies = new ArrayMap<>();
@@ -3094,14 +3102,24 @@
* Parcelables.
*/
@Nullable
- public final ArrayList readArrayList(@Nullable ClassLoader loader) {
- int N = readInt();
- if (N < 0) {
- return null;
- }
- ArrayList l = new ArrayList(N);
- readListInternal(l, N, loader, /* clazz */ null);
- return l;
+ public ArrayList readArrayList(@Nullable ClassLoader loader) {
+ return readArrayListInternal(loader, /* clazz */ null);
+ }
+
+ /**
+ * Same as {@link #readArrayList(ClassLoader)} but accepts {@code clazz} parameter as
+ * the type required for each item.
+ *
+ * @throws BadParcelableException Throws BadParcelableException if the item to be deserialized
+ * is not an instance of that class or any of its children classes or there was an error
+ * trying to instantiate an element.
+ */
+ @SuppressLint({"ConcreteCollection", "NullableCollection"})
+ @Nullable
+ public <T> ArrayList<T> readArrayList(@Nullable ClassLoader loader,
+ @NonNull Class<? extends T> clazz) {
+ Objects.requireNonNull(clazz);
+ return readArrayListInternal(loader, clazz);
}
/**
@@ -3111,14 +3129,23 @@
* Parcelables.
*/
@Nullable
- public final Object[] readArray(@Nullable ClassLoader loader) {
- int N = readInt();
- if (N < 0) {
- return null;
- }
- Object[] l = new Object[N];
- readArrayInternal(l, N, loader);
- return l;
+ public Object[] readArray(@Nullable ClassLoader loader) {
+ return readArrayInternal(loader, /* clazz */ null);
+ }
+
+ /**
+ * Same as {@link #readArray(ClassLoader)} but accepts {@code clazz} parameter as
+ * the type required for each item.
+ *
+ * @throws BadParcelableException Throws BadParcelableException if the item to be deserialized
+ * is not an instance of that class or any of its children classes or there was an error
+ * trying to instantiate an element.
+ */
+ @SuppressLint({"ArrayReturn", "NullableCollection"})
+ @Nullable
+ public <T> T[] readArray(@Nullable ClassLoader loader, @NonNull Class<T> clazz) {
+ Objects.requireNonNull(clazz);
+ return readArrayInternal(loader, clazz);
}
/**
@@ -3128,14 +3155,23 @@
* Parcelables.
*/
@Nullable
- public final <T> SparseArray<T> readSparseArray(@Nullable ClassLoader loader) {
- int N = readInt();
- if (N < 0) {
- return null;
- }
- SparseArray sa = new SparseArray(N);
- readSparseArrayInternal(sa, N, loader);
- return sa;
+ public <T> SparseArray<T> readSparseArray(@Nullable ClassLoader loader) {
+ return readSparseArrayInternal(loader, /* clazz */ null);
+ }
+
+ /**
+ * Same as {@link #readSparseArray(ClassLoader)} but accepts {@code clazz} parameter as
+ * the type required for each item.
+ *
+ * @throws BadParcelableException Throws BadParcelableException if the item to be deserialized
+ * is not an instance of that class or any of its children classes or there was an error
+ * trying to instantiate an element.
+ */
+ @Nullable
+ public <T> SparseArray<T> readSparseArray(@Nullable ClassLoader loader,
+ @NonNull Class<? extends T> clazz) {
+ Objects.requireNonNull(clazz);
+ return readSparseArrayInternal(loader, clazz);
}
/**
@@ -3580,7 +3616,6 @@
private final int mType;
@Nullable private final ClassLoader mLoader;
@Nullable private Object mObject;
- @Nullable private volatile Parcel mValueParcel;
/**
* This goes from non-null to null once. Always check the nullability of this object before
@@ -3678,7 +3713,7 @@
return false;
}
// Finally we compare the payload.
- return getValueParcel(source).compareData(value.getValueParcel(otherSource)) == 0;
+ return Parcel.compareData(source, mPosition, otherSource, value.mPosition, mLength);
}
@Override
@@ -3686,17 +3721,6 @@
// Accessing mSource first to provide memory barrier for mObject
return Objects.hash(mSource == null, mObject, mLoader, mType, mLength);
}
-
- /** This extracts the parcel section responsible for the object and returns it. */
- private Parcel getValueParcel(Parcel source) {
- Parcel parcel = mValueParcel;
- if (parcel == null) {
- parcel = Parcel.obtain();
- parcel.appendFrom(source, mPosition, mLength);
- mValueParcel = parcel;
- }
- return parcel;
- }
}
/**
@@ -3851,7 +3875,7 @@
"Parcel " + this + ": Unmarshalling unknown type code " + type
+ " at offset " + off);
}
- if (clazz != null && !clazz.isInstance(object)) {
+ if (object != null && clazz != null && !clazz.isInstance(object)) {
throw new BadParcelableException("Unparcelled object " + object
+ " is not an instance of required class " + clazz.getName()
+ " provided in the parameter");
@@ -3910,7 +3934,6 @@
}
/**
- *
* @param clazz The type of the parcelable expected or {@code null} for performing no checks.
*/
@SuppressWarnings("unchecked")
@@ -3969,7 +3992,7 @@
* as the required type.
*
* @throws BadParcelableException Throws BadParcelableException if the item to be deserialized
- * is not an instance of that class or any of its children class or there there was an error
+ * is not an instance of that class or any of its children classes or there there was an error
* trying to read the {@link Parcelable.Creator}.
*/
@Nullable
@@ -4092,17 +4115,25 @@
return p;
}
- /** @hide */
+ /**
+ * Same as {@link #readParcelableArray(ClassLoader)} but accepts {@code clazz} parameter as
+ * the type required for each item.
+ *
+ * @throws BadParcelableException Throws BadParcelableException if the item to be deserialized
+ * is not an instance of that class or any of its children classes or there was an error
+ * trying to instantiate an element.
+ */
+ @SuppressLint({"ArrayReturn", "NullableCollection"})
+ @SuppressWarnings("unchecked")
@Nullable
- public final <T extends Parcelable> T[] readParcelableArray(@Nullable ClassLoader loader,
- @NonNull Class<T> clazz) {
- int N = readInt();
- if (N < 0) {
+ public <T> T[] readParcelableArray(@Nullable ClassLoader loader, @NonNull Class<T> clazz) {
+ int n = readInt();
+ if (n < 0) {
return null;
}
- T[] p = (T[]) Array.newInstance(clazz, N);
- for (int i = 0; i < N; i++) {
- p[i] = readParcelable(loader);
+ T[] p = (T[]) Array.newInstance(clazz, n);
+ for (int i = 0; i < n; i++) {
+ p[i] = readParcelableInternal(loader, clazz);
}
return p;
}
@@ -4320,9 +4351,12 @@
return result;
}
- private void readListInternal(@NonNull List outVal, int n,
- @Nullable ClassLoader loader) {
- readListInternal(outVal, n, loader, null);
+ /**
+ * The method is replaced by {@link #readListInternal(List, int, ClassLoader, Class)}, however
+ * we are keeping this unused method here to allow unsupported app usages.
+ */
+ private void readListInternal(@NonNull List outVal, int n, @Nullable ClassLoader loader) {
+ readListInternal(outVal, n, loader, /* clazz */ null);
}
/**
@@ -4338,26 +4372,88 @@
}
}
+ /**
+ * @param clazz The type of the object expected or {@code null} for performing no checks.
+ */
+ @SuppressLint({"ConcreteCollection", "NullableCollection"})
+ @Nullable
+ private <T> ArrayList<T> readArrayListInternal(@Nullable ClassLoader loader,
+ @Nullable Class<? extends T> clazz) {
+ int n = readInt();
+ if (n < 0) {
+ return null;
+ }
+ ArrayList<T> l = new ArrayList<>(n);
+ readListInternal(l, n, loader, clazz);
+ return l;
+ }
+
+ /**
+ * The method is replaced by {@link #readArrayInternal(ClassLoader, Class)}, however
+ * we are keeping this unused method here to allow unsupported app usages.
+ */
private void readArrayInternal(@NonNull Object[] outVal, int N,
@Nullable ClassLoader loader) {
for (int i = 0; i < N; i++) {
- Object value = readValue(loader);
- //Log.d(TAG, "Unmarshalling value=" + value);
+ Object value = readValue(loader, /* clazz */ null);
outVal[i] = value;
}
}
+ /**
+ * @param clazz The type of the object expected or {@code null} for performing no checks.
+ */
+ @SuppressWarnings("unchecked")
+ @Nullable
+ private <T> T[] readArrayInternal(@Nullable ClassLoader loader, @Nullable Class<T> clazz) {
+ int n = readInt();
+ if (n < 0) {
+ return null;
+ }
+ T[] outVal = (T[]) ((clazz == null) ? new Object[n] : Array.newInstance(clazz, n));
+
+ for (int i = 0; i < n; i++) {
+ T value = readValue(loader, clazz);
+ outVal[i] = value;
+ }
+ return outVal;
+ }
+
+ /**
+ * The method is replaced by {@link #readSparseArray(ClassLoader, Class)}, however
+ * we are keeping this unused method here to allow unsupported app usages.
+ */
private void readSparseArrayInternal(@NonNull SparseArray outVal, int N,
@Nullable ClassLoader loader) {
while (N > 0) {
int key = readInt();
Object value = readValue(loader);
- //Log.i(TAG, "Unmarshalling key=" + key + " value=" + value);
outVal.append(key, value);
N--;
}
}
+ /**
+ * @param clazz The type of the object expected or {@code null} for performing no checks.
+ */
+ @Nullable
+ private <T> SparseArray<T> readSparseArrayInternal(@Nullable ClassLoader loader,
+ @Nullable Class<? extends T> clazz) {
+ int n = readInt();
+ if (n < 0) {
+ return null;
+ }
+ SparseArray<T> outVal = new SparseArray<>(n);
+
+ while (n > 0) {
+ int key = readInt();
+ T value = readValue(loader, clazz);
+ outVal.append(key, value);
+ n--;
+ }
+ return outVal;
+ }
+
private void readSparseBooleanArrayInternal(@NonNull SparseBooleanArray outVal, int N) {
while (N > 0) {
diff --git a/core/java/android/provider/Telephony.java b/core/java/android/provider/Telephony.java
index 387fc39..aa1bbc5 100644
--- a/core/java/android/provider/Telephony.java
+++ b/core/java/android/provider/Telephony.java
@@ -5366,5 +5366,13 @@
public static final String COLUMN_D2D_STATUS_SHARING_SELECTED_CONTACTS =
"d2d_sharing_contacts";
+ /**
+ * TelephonyProvider column name for NR Advanced calling
+ * Determines if the user has enabled VoNR settings for this subscription.
+ *
+ * @hide
+ */
+ public static final String COLUMN_NR_ADVANCED_CALLING_ENABLED =
+ "nr_advanced_calling_enabled";
}
}
diff --git a/core/java/android/security/attestationverification/OWNERS b/core/java/android/security/attestationverification/OWNERS
new file mode 100644
index 0000000..80a1f44
--- /dev/null
+++ b/core/java/android/security/attestationverification/OWNERS
@@ -0,0 +1,4 @@
+# Bug component: 1111194
+
+dlm@google.com
+dkrahn@google.com
diff --git a/core/java/android/service/dreams/DreamService.java b/core/java/android/service/dreams/DreamService.java
index 9819648..096595f 100644
--- a/core/java/android/service/dreams/DreamService.java
+++ b/core/java/android/service/dreams/DreamService.java
@@ -26,7 +26,10 @@
import android.app.AlarmManager;
import android.app.Service;
import android.compat.annotation.UnsupportedAppUsage;
+import android.content.ComponentName;
+import android.content.Context;
import android.content.Intent;
+import android.content.ServiceConnection;
import android.os.Build;
import android.os.Handler;
import android.os.IBinder;
@@ -58,6 +61,8 @@
import java.io.FileDescriptor;
import java.io.PrintWriter;
+import java.util.ArrayDeque;
+import java.util.function.Consumer;
/**
* Extend this class to implement a custom dream (available to the user as a "Daydream").
@@ -170,6 +175,13 @@
"android.service.dreams.DreamService";
/**
+ * The name of the extra where the dream overlay component is stored.
+ * @hide
+ */
+ public static final String EXTRA_DREAM_OVERLAY_COMPONENT =
+ "android.service.dream.DreamService.dream_overlay_component";
+
+ /**
* Name under which a Dream publishes information about itself.
* This meta-data must reference an XML resource containing
* a <code><{@link android.R.styleable#Dream dream}></code>
@@ -191,6 +203,7 @@
private boolean mCanDoze;
private boolean mDozing;
private boolean mWindowless;
+ private boolean mOverlayServiceBound;
private int mDozeScreenState = Display.STATE_UNKNOWN;
private int mDozeScreenBrightness = PowerManager.BRIGHTNESS_DEFAULT;
@@ -199,8 +212,62 @@
private DreamServiceWrapper mDreamServiceWrapper;
private Runnable mDispatchAfterOnAttachedToWindow;
+ private OverlayConnection mOverlayConnection;
+
+ private static class OverlayConnection implements ServiceConnection {
+ // Overlay set during onBind.
+ private IDreamOverlay mOverlay;
+ // A Queue of pending requests to execute on the overlay.
+ private ArrayDeque<Consumer<IDreamOverlay>> mRequests;
+
+ OverlayConnection() {
+ mRequests = new ArrayDeque<>();
+ }
+
+ public void request(Consumer<IDreamOverlay> request) {
+ mRequests.push(request);
+ evaluate();
+ }
+
+ private void evaluate() {
+ if (mOverlay == null) {
+ return;
+ }
+
+ // Any new requests that arrive during this loop will be processed synchronously after
+ // the loop exits.
+ while (!mRequests.isEmpty()) {
+ final Consumer<IDreamOverlay> request = mRequests.pop();
+ request.accept(mOverlay);
+ }
+ }
+
+ @Override
+ public void onServiceConnected(ComponentName name, IBinder service) {
+ // Store Overlay and execute pending requests.
+ mOverlay = IDreamOverlay.Stub.asInterface(service);
+ evaluate();
+ }
+
+ @Override
+ public void onServiceDisconnected(ComponentName name) {
+ // Clear Overlay binder to prevent further request processing.
+ mOverlay = null;
+ }
+ }
+
+ private IDreamOverlayCallback mOverlayCallback = new IDreamOverlayCallback.Stub() {
+ @Override
+ public void onExitRequested() {
+ // Simply finish dream when exit is requested.
+ finish();
+ }
+ };
+
+
public DreamService() {
mDreamManager = IDreamManager.Stub.asInterface(ServiceManager.getService(DREAM_SERVICE));
+ mOverlayConnection = new OverlayConnection();
}
/**
@@ -861,6 +928,18 @@
public final IBinder onBind(Intent intent) {
if (mDebug) Slog.v(TAG, "onBind() intent = " + intent);
mDreamServiceWrapper = new DreamServiceWrapper();
+
+ // Connect to the overlay service if present.
+ final ComponentName overlayComponent =
+ intent.getParcelableExtra(EXTRA_DREAM_OVERLAY_COMPONENT);
+ if (overlayComponent != null && !mWindowless) {
+ final Intent overlayIntent = new Intent();
+ overlayIntent.setComponent(overlayComponent);
+
+ mOverlayServiceBound = getApplicationContext().bindService(overlayIntent,
+ mOverlayConnection, Context.BIND_AUTO_CREATE | Context.BIND_FOREGROUND_SERVICE);
+ }
+
return mDreamServiceWrapper;
}
@@ -894,6 +973,11 @@
return;
}
+ if (!mWindowless && mOverlayServiceBound) {
+ unbindService(mOverlayConnection);
+ mOverlayServiceBound = false;
+ }
+
try {
// finishSelf will unbind the dream controller from the dream service. This will
// trigger DreamService.this.onDestroy and DreamService.this will die.
@@ -1101,6 +1185,16 @@
}
}
});
+
+ // Request the DreamOverlay be told to dream with dream's window parameters once the service
+ // has connected.
+ mOverlayConnection.request(overlay -> {
+ try {
+ overlay.startDream(mWindow.getAttributes(), mOverlayCallback);
+ } catch (RemoteException e) {
+ Log.e(TAG, "could not send window attributes:" + e);
+ }
+ });
}
private boolean getWindowFlagValue(int flag, boolean defaultValue) {
diff --git a/core/java/android/service/dreams/IDreamManager.aidl b/core/java/android/service/dreams/IDreamManager.aidl
index 0ce9cfa..3e0deeb 100644
--- a/core/java/android/service/dreams/IDreamManager.aidl
+++ b/core/java/android/service/dreams/IDreamManager.aidl
@@ -41,4 +41,5 @@
void forceAmbientDisplayEnabled(boolean enabled);
ComponentName[] getDreamComponentsForUser(int userId);
void setDreamComponentsForUser(int userId, in ComponentName[] componentNames);
+ void registerDreamOverlayService(in ComponentName componentName);
}
diff --git a/core/java/android/service/dreams/IDreamOverlay.aidl b/core/java/android/service/dreams/IDreamOverlay.aidl
new file mode 100644
index 0000000..2b6633d
--- /dev/null
+++ b/core/java/android/service/dreams/IDreamOverlay.aidl
@@ -0,0 +1,37 @@
+/**
+ * Copyright (c) 2021, 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.dreams;
+
+import android.service.dreams.IDreamOverlayCallback;
+import android.view.WindowManager.LayoutParams;
+
+/**
+* {@link IDreamOverlay} provides a way for a component to annotate a dream with additional view
+* elements. Registered through the DreamManager, a IDreamOverlay is bound to by the dream and
+* passed the necessary window details to participate in the user interface.
+
+* @hide
+*/
+interface IDreamOverlay {
+ /**
+ * @param params The {@link LayoutParams} for the associated DreamWindow, including the window
+ token of the Dream Activity.
+ * @param callback The {@link IDreamOverlayCallback} for requesting actions such as exiting the
+ * dream.
+ */
+ void startDream(in LayoutParams params, in IDreamOverlayCallback callback);
+}
diff --git a/core/java/android/service/dreams/IDreamOverlayCallback.aidl b/core/java/android/service/dreams/IDreamOverlayCallback.aidl
new file mode 100644
index 0000000..ec76a33
--- /dev/null
+++ b/core/java/android/service/dreams/IDreamOverlayCallback.aidl
@@ -0,0 +1,31 @@
+/**
+ * Copyright (c) 2021, 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.dreams;
+
+/**
+* {@link IDreamOverlayCallback} defines the interactions a dream overlay can have with its
+* associated dream. It is the discretion of the {@link DreamService}) to honor any inbound requests
+* from this callback.
+*
+* @hide
+*/
+interface IDreamOverlayCallback {
+ /**
+ * Invoked to request the dream exit.
+ */
+ void onExitRequested();
+}
\ No newline at end of file
diff --git a/core/java/android/view/KeyEvent.java b/core/java/android/view/KeyEvent.java
index d12ed8f..1460cb2 100644
--- a/core/java/android/view/KeyEvent.java
+++ b/core/java/android/view/KeyEvent.java
@@ -832,13 +832,45 @@
* consuming content. May be consumed by system to set account globally.
*/
public static final int KEYCODE_PROFILE_SWITCH = 288;
+ /** Key code constant: Video Application key #1. */
+ public static final int KEYCODE_VIDEO_APP_1 = 289;
+ /** Key code constant: Video Application key #2. */
+ public static final int KEYCODE_VIDEO_APP_2 = 290;
+ /** Key code constant: Video Application key #3. */
+ public static final int KEYCODE_VIDEO_APP_3 = 291;
+ /** Key code constant: Video Application key #4. */
+ public static final int KEYCODE_VIDEO_APP_4 = 292;
+ /** Key code constant: Video Application key #5. */
+ public static final int KEYCODE_VIDEO_APP_5 = 293;
+ /** Key code constant: Video Application key #6. */
+ public static final int KEYCODE_VIDEO_APP_6 = 294;
+ /** Key code constant: Video Application key #7. */
+ public static final int KEYCODE_VIDEO_APP_7 = 295;
+ /** Key code constant: Video Application key #8. */
+ public static final int KEYCODE_VIDEO_APP_8 = 296;
+ /** Key code constant: Featured Application key #1. */
+ public static final int KEYCODE_FEATURED_APP_1 = 297;
+ /** Key code constant: Featured Application key #2. */
+ public static final int KEYCODE_FEATURED_APP_2 = 298;
+ /** Key code constant: Featured Application key #3. */
+ public static final int KEYCODE_FEATURED_APP_3 = 299;
+ /** Key code constant: Featured Application key #4. */
+ public static final int KEYCODE_FEATURED_APP_4 = 300;
+ /** Key code constant: Demo Application key #1. */
+ public static final int KEYCODE_DEMO_APP_1 = 301;
+ /** Key code constant: Demo Application key #2. */
+ public static final int KEYCODE_DEMO_APP_2 = 302;
+ /** Key code constant: Demo Application key #3. */
+ public static final int KEYCODE_DEMO_APP_3 = 303;
+ /** Key code constant: Demo Application key #4. */
+ public static final int KEYCODE_DEMO_APP_4 = 304;
- /**
+ /**
* Integer value of the last KEYCODE. Increases as new keycodes are added to KeyEvent.
* @hide
*/
@TestApi
- public static final int LAST_KEYCODE = KEYCODE_PROFILE_SWITCH;
+ public static final int LAST_KEYCODE = KEYCODE_DEMO_APP_4;
// NOTE: If you add a new keycode here you must also add it to:
// isSystem()
diff --git a/core/java/android/view/VelocityTracker.java b/core/java/android/view/VelocityTracker.java
index e1c4305..2b79bbf 100644
--- a/core/java/android/view/VelocityTracker.java
+++ b/core/java/android/view/VelocityTracker.java
@@ -19,7 +19,7 @@
import android.annotation.IntDef;
import android.compat.annotation.UnsupportedAppUsage;
import android.os.Build;
-import android.os.SystemProperties;
+import android.sysprop.InputProperties;
import android.util.ArrayMap;
import android.util.Pools.SynchronizedPool;
@@ -279,8 +279,7 @@
// If user has not selected a specific strategy
if (strategy == VELOCITY_TRACKER_STRATEGY_DEFAULT) {
// Check if user specified strategy by overriding system property.
- String strategyProperty =
- SystemProperties.get("persist.input.velocitytracker.strategy");
+ String strategyProperty = InputProperties.velocitytracker_strategy().orElse(null);
if (strategyProperty == null || strategyProperty.isEmpty()) {
mStrategy = strategy;
} else {
diff --git a/core/java/android/view/ViewRootImpl.java b/core/java/android/view/ViewRootImpl.java
index 89e1e08..4879206 100644
--- a/core/java/android/view/ViewRootImpl.java
+++ b/core/java/android/view/ViewRootImpl.java
@@ -57,12 +57,15 @@
import static android.view.WindowInsetsController.APPEARANCE_LOW_PROFILE_BARS;
import static android.view.WindowInsetsController.BEHAVIOR_DEFAULT;
import static android.view.WindowInsetsController.BEHAVIOR_SHOW_TRANSIENT_BARS_BY_SWIPE;
+import static android.view.WindowLayout.UNSPECIFIED_LENGTH;
import static android.view.WindowManager.LayoutParams.FIRST_APPLICATION_WINDOW;
+import static android.view.WindowManager.LayoutParams.FIRST_SUB_WINDOW;
import static android.view.WindowManager.LayoutParams.FLAG_FULLSCREEN;
import static android.view.WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN;
import static android.view.WindowManager.LayoutParams.FLAG_TRANSLUCENT_NAVIGATION;
import static android.view.WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS;
import static android.view.WindowManager.LayoutParams.LAST_APPLICATION_WINDOW;
+import static android.view.WindowManager.LayoutParams.LAST_SUB_WINDOW;
import static android.view.WindowManager.LayoutParams.LAYOUT_IN_DISPLAY_CUTOUT_MODE_ALWAYS;
import static android.view.WindowManager.LayoutParams.LAYOUT_IN_DISPLAY_CUTOUT_MODE_SHORT_EDGES;
import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_APPEARANCE_CONTROLLED;
@@ -72,6 +75,7 @@
import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_INSET_PARENT_FRAME_BY_IME;
import static android.view.WindowManager.LayoutParams.SOFT_INPUT_ADJUST_RESIZE;
import static android.view.WindowManager.LayoutParams.SOFT_INPUT_MASK_ADJUST;
+import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION_ATTACHED_DIALOG;
import static android.view.WindowManager.LayoutParams.TYPE_INPUT_METHOD;
import static android.view.WindowManager.LayoutParams.TYPE_STATUS_BAR_ADDITIONAL;
import static android.view.WindowManager.LayoutParams.TYPE_SYSTEM_ALERT;
@@ -90,6 +94,7 @@
import android.app.ActivityManager;
import android.app.ActivityThread;
import android.app.ResourcesManager;
+import android.app.WindowConfiguration;
import android.compat.annotation.UnsupportedAppUsage;
import android.content.ClipData;
import android.content.ClipDescription;
@@ -515,6 +520,8 @@
private final WindowLayout mWindowLayout = new WindowLayout();
+ private ViewRootImpl mParentViewRoot;
+
// This is used to reduce the race between window focus changes being dispatched from
// the window manager and input events coming through the input system.
@GuardedBy("this")
@@ -796,11 +803,7 @@
context);
mCompatibleVisibilityInfo = new SystemUiVisibilityInfo();
mAccessibilityManager = AccessibilityManager.getInstance(context);
- mAccessibilityManager.addAccessibilityStateChangeListener(
- mAccessibilityInteractionConnectionManager, mHandler);
mHighContrastTextManager = new HighContrastTextManager();
- mAccessibilityManager.addHighTextContrastStateChangeListener(
- mHighContrastTextManager, mHandler);
mViewConfiguration = ViewConfiguration.get(context);
mDensity = context.getResources().getDisplayMetrics().densityDpi;
mNoncompatDensity = context.getResources().getDisplayMetrics().noncompatDensityDpi;
@@ -977,8 +980,6 @@
mView = view;
mAttachInfo.mDisplayState = mDisplay.getState();
- mDisplayManager.registerDisplayListener(mDisplayListener, mHandler);
-
mViewLayoutDirectionInitial = mView.getRawLayoutDirection();
mFallbackEventHandler.setView(view);
mWindowAttributes.copyFrom(attrs);
@@ -1059,6 +1060,7 @@
if (panelParentView != null) {
mAttachInfo.mPanelParentWindowToken
= panelParentView.getApplicationWindowToken();
+ mParentViewRoot = panelParentView.getViewRootImpl();
}
mAdded = true;
int res; /* = WindowManagerImpl.ADD_OKAY; */
@@ -1119,10 +1121,13 @@
final InsetsState state = mInsetsController.getState();
final Rect displayCutoutSafe = mTempRect;
state.getDisplayCutoutSafe(displayCutoutSafe);
+ final WindowConfiguration winConfig = getConfiguration().windowConfiguration;
mWindowLayout.computeWindowFrames(mWindowAttributes, state,
- displayCutoutSafe, getConfiguration().windowConfiguration.getBounds(),
+ displayCutoutSafe, winConfig.getBounds(), winConfig.getWindowingMode(),
+ UNSPECIFIED_LENGTH, UNSPECIFIED_LENGTH,
mInsetsController.getRequestedVisibilities(),
- null /* attachedWindowFrame */, mTmpFrames.frame, mTempRect2);
+ getAttachedWindowFrame(), 1f /* compactScale */,
+ mTmpFrames.displayFrame, mTempRect2, mTmpFrames.frame);
setFrame(mTmpFrames.frame);
if (DEBUG_LAYOUT) Log.v(mTag, "Added window " + mWindow);
if (res < WindowManagerGlobal.ADD_OKAY) {
@@ -1176,6 +1181,7 @@
"Unable to add window -- unknown error code " + res);
}
+ registerListeners();
if ((res & WindowManagerGlobal.ADD_FLAG_USE_BLAST) != 0) {
mUseBLASTAdapter = true;
}
@@ -1232,6 +1238,36 @@
}
}
+ private Rect getAttachedWindowFrame() {
+ final int type = mWindowAttributes.type;
+ final boolean layoutAttached = (mParentViewRoot != null
+ && type >= FIRST_SUB_WINDOW && type <= LAST_SUB_WINDOW
+ && type != TYPE_APPLICATION_ATTACHED_DIALOG);
+ return layoutAttached ? mParentViewRoot.mWinFrame : null;
+ }
+
+ /**
+ * Register any kind of listeners if setView was success.
+ */
+ private void registerListeners() {
+ mAccessibilityManager.addAccessibilityStateChangeListener(
+ mAccessibilityInteractionConnectionManager, mHandler);
+ mAccessibilityManager.addHighTextContrastStateChangeListener(
+ mHighContrastTextManager, mHandler);
+ mDisplayManager.registerDisplayListener(mDisplayListener, mHandler);
+ }
+
+ /**
+ * Unregister all listeners while detachedFromWindow.
+ */
+ private void unregisterListeners() {
+ mAccessibilityManager.removeAccessibilityStateChangeListener(
+ mAccessibilityInteractionConnectionManager);
+ mAccessibilityManager.removeHighTextContrastStateChangeListener(
+ mHighContrastTextManager);
+ mDisplayManager.unregisterDisplayListener(mDisplayListener);
+ }
+
private void setTag() {
final String[] split = mWindowAttributes.getTitle().toString().split("\\.");
if (split.length > 0) {
@@ -4912,10 +4948,6 @@
}
mAccessibilityInteractionConnectionManager.ensureNoConnection();
- mAccessibilityManager.removeAccessibilityStateChangeListener(
- mAccessibilityInteractionConnectionManager);
- mAccessibilityManager.removeHighTextContrastStateChangeListener(
- mHighContrastTextManager);
removeSendWindowContentChangedCallback();
destroyHardwareRenderer();
@@ -4948,8 +4980,7 @@
mInputEventReceiver = null;
}
- mDisplayManager.unregisterDisplayListener(mDisplayListener);
-
+ unregisterListeners();
unscheduleTraversals();
}
diff --git a/core/java/android/view/WindowLayout.java b/core/java/android/view/WindowLayout.java
index cdc1977..7dfc95e 100644
--- a/core/java/android/view/WindowLayout.java
+++ b/core/java/android/view/WindowLayout.java
@@ -19,29 +19,44 @@
import static android.view.InsetsState.ITYPE_IME;
import static android.view.InsetsState.ITYPE_NAVIGATION_BAR;
import static android.view.InsetsState.ITYPE_STATUS_BAR;
+import static android.view.ViewGroup.LayoutParams.MATCH_PARENT;
import static android.view.WindowManager.LayoutParams.FLAG_LAYOUT_INSET_DECOR;
import static android.view.WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN;
+import static android.view.WindowManager.LayoutParams.FLAG_LAYOUT_NO_LIMITS;
+import static android.view.WindowManager.LayoutParams.FLAG_SCALED;
import static android.view.WindowManager.LayoutParams.LAYOUT_IN_DISPLAY_CUTOUT_MODE_ALWAYS;
import static android.view.WindowManager.LayoutParams.LAYOUT_IN_DISPLAY_CUTOUT_MODE_DEFAULT;
import static android.view.WindowManager.LayoutParams.LAYOUT_IN_DISPLAY_CUTOUT_MODE_SHORT_EDGES;
import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_INSET_PARENT_FRAME_BY_IME;
+import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_LAYOUT_CHILD_WINDOW_IN_PARENT_FRAME;
import static android.view.WindowManager.LayoutParams.TYPE_BASE_APPLICATION;
import static android.view.WindowManager.LayoutParams.TYPE_INPUT_METHOD;
+import static android.view.WindowManager.LayoutParams.TYPE_SYSTEM_ERROR;
+import android.app.WindowConfiguration;
+import android.app.WindowConfiguration.WindowingMode;
import android.graphics.Insets;
import android.graphics.Rect;
+import android.util.Log;
/**
* Computes window frames.
* @hide
*/
public class WindowLayout {
+ private static final String TAG = WindowLayout.class.getSimpleName();
+ private static final boolean DEBUG = false;
+
+ public static final int UNSPECIFIED_LENGTH = -1;
+
private final Rect mTempDisplayCutoutSafeExceptMaybeBarsRect = new Rect();
private final Rect mTempRect = new Rect();
public boolean computeWindowFrames(WindowManager.LayoutParams attrs, InsetsState state,
- Rect displayCutoutSafe, Rect windowBounds, InsetsVisibilities requestedVisibilities,
- Rect attachedWindowFrame, Rect outDisplayFrame, Rect outParentFrame) {
+ Rect displayCutoutSafe, Rect windowBounds, @WindowingMode int windowingMode,
+ int requestedWidth, int requestedHeight, InsetsVisibilities requestedVisibilities,
+ Rect attachedWindowFrame, float compatScale, Rect outDisplayFrame, Rect outParentFrame,
+ Rect outFrame) {
final int type = attrs.type;
final int fl = attrs.flags;
final int pfl = attrs.privateFlags;
@@ -72,18 +87,14 @@
}
// Compute bounds restricted by display cutout
+ final int cutoutMode = attrs.layoutInDisplayCutoutMode;
final DisplayCutout cutout = state.getDisplayCutout();
- if (cutout.isEmpty()) {
- return false;
- }
- boolean clippedByDisplayCutout = false;
final Rect displayCutoutSafeExceptMaybeBars = mTempDisplayCutoutSafeExceptMaybeBarsRect;
displayCutoutSafeExceptMaybeBars.set(displayCutoutSafe);
-
- // Ensure that windows with a non-ALWAYS display cutout mode are laid out in
- // the cutout safe zone.
- final int cutoutMode = attrs.layoutInDisplayCutoutMode;
- if (cutoutMode != LAYOUT_IN_DISPLAY_CUTOUT_MODE_ALWAYS) {
+ boolean clippedByDisplayCutout = false;
+ if (cutoutMode != LAYOUT_IN_DISPLAY_CUTOUT_MODE_ALWAYS && !cutout.isEmpty()) {
+ // Ensure that windows with a non-ALWAYS display cutout mode are laid out in
+ // the cutout safe zone.
final Rect displayFrame = state.getDisplayFrame();
final InsetsSource statusBarSource = state.peekSource(ITYPE_STATUS_BAR);
if (statusBarSource != null && displayCutoutSafe.top > displayFrame.top) {
@@ -147,6 +158,118 @@
}
outDisplayFrame.intersectUnchecked(displayCutoutSafeExceptMaybeBars);
}
+
+ final boolean noLimits = (attrs.flags & FLAG_LAYOUT_NO_LIMITS) != 0;
+ final boolean inMultiWindowMode = WindowConfiguration.inMultiWindowMode(windowingMode);
+
+ // TYPE_SYSTEM_ERROR is above the NavigationBar so it can't be allowed to extend over it.
+ // Also, we don't allow windows in multi-window mode to extend out of the screen.
+ if (noLimits && type != TYPE_SYSTEM_ERROR && !inMultiWindowMode) {
+ outDisplayFrame.left = outDisplayFrame.top = -10000;
+ outDisplayFrame.right = outDisplayFrame.bottom = 10000;
+ }
+
+ final boolean hasCompatScale = compatScale != 1f;
+ final int pw = outParentFrame.width();
+ final int ph = outParentFrame.height();
+ int rw = requestedWidth;
+ int rh = requestedHeight;
+ float x, y;
+ int w, h;
+
+ // If the view hierarchy hasn't been measured, the requested width and height would be
+ // UNSPECIFIED_LENGTH. This can happen in the first layout of a window or in the simulated
+ // layout.
+ if (rw == UNSPECIFIED_LENGTH) {
+ rw = attrs.width >= 0 ? attrs.width : pw;
+ }
+ if (rh == UNSPECIFIED_LENGTH) {
+ rh = attrs.height >= 0 ? attrs.height : ph;
+ }
+
+ if ((attrs.flags & FLAG_SCALED) != 0) {
+ if (attrs.width < 0) {
+ w = pw;
+ } else if (hasCompatScale) {
+ w = (int) (attrs.width * compatScale + .5f);
+ } else {
+ w = attrs.width;
+ }
+ if (attrs.height < 0) {
+ h = ph;
+ } else if (hasCompatScale) {
+ h = (int) (attrs.height * compatScale + .5f);
+ } else {
+ h = attrs.height;
+ }
+ } else {
+ if (attrs.width == MATCH_PARENT) {
+ w = pw;
+ } else if (hasCompatScale) {
+ w = (int) (rw * compatScale + .5f);
+ } else {
+ w = rw;
+ }
+ if (attrs.height == MATCH_PARENT) {
+ h = ph;
+ } else if (hasCompatScale) {
+ h = (int) (rh * compatScale + .5f);
+ } else {
+ h = rh;
+ }
+ }
+
+ if (hasCompatScale) {
+ x = attrs.x * compatScale;
+ y = attrs.y * compatScale;
+ } else {
+ x = attrs.x;
+ y = attrs.y;
+ }
+
+ if (inMultiWindowMode
+ && (attrs.privateFlags & PRIVATE_FLAG_LAYOUT_CHILD_WINDOW_IN_PARENT_FRAME) == 0) {
+ // Make sure window fits in parent frame since it is in a non-fullscreen task as
+ // required by {@link Gravity#apply} call.
+ w = Math.min(w, pw);
+ h = Math.min(h, ph);
+ }
+
+ // We need to fit it to the display if either
+ // a) The window is in a fullscreen container, or we don't have a task (we assume fullscreen
+ // for the taskless windows)
+ // b) If it's a secondary app window, we also need to fit it to the display unless
+ // FLAG_LAYOUT_NO_LIMITS is set. This is so we place Popups, dialogs, and similar windows on
+ // screen, but SurfaceViews want to be always at a specific location so we don't fit it to
+ // the display.
+ final boolean fitToDisplay = !inMultiWindowMode
+ || ((attrs.type != TYPE_BASE_APPLICATION) && !noLimits);
+
+ // Set mFrame
+ Gravity.apply(attrs.gravity, w, h, outParentFrame,
+ (int) (x + attrs.horizontalMargin * pw),
+ (int) (y + attrs.verticalMargin * ph), outFrame);
+ // Now make sure the window fits in the overall display frame.
+ if (fitToDisplay) {
+ Gravity.applyDisplay(attrs.gravity, outDisplayFrame, outFrame);
+ }
+
+ if (DEBUG) Log.d(TAG, "computeWindowFrames " + attrs.getTitle()
+ + " outFrame=" + outFrame.toShortString()
+ + " outParentFrame=" + outParentFrame.toShortString()
+ + " outDisplayFrame=" + outDisplayFrame.toShortString()
+ + " attachedWindowFrame=" + (attachedWindowFrame != null
+ ? attachedWindowFrame.toShortString()
+ : "null")
+ + " requestedWidth=" + requestedWidth
+ + " requestedHeight=" + requestedHeight
+ + " compatScale=" + compatScale
+ + " windowingMode=" + WindowConfiguration.windowingModeToString(windowingMode)
+ + " displayCutoutSafe=" + displayCutoutSafe
+ + " attrs=" + attrs
+ + " state=" + state
+ + " requestedVisibilities=" + requestedVisibilities);
+
return clippedByDisplayCutout;
}
}
diff --git a/core/java/android/view/translation/UiTranslationController.java b/core/java/android/view/translation/UiTranslationController.java
index 3db7136..69b4187 100644
--- a/core/java/android/view/translation/UiTranslationController.java
+++ b/core/java/android/view/translation/UiTranslationController.java
@@ -371,6 +371,10 @@
Log.v(TAG, "onVirtualViewTranslationCompleted: received response for "
+ "AutofillId " + autofillId);
}
+ view.onVirtualViewTranslationResponses(virtualChildResponse);
+ if (mCurrentState == STATE_UI_TRANSLATION_PAUSED) {
+ return;
+ }
mActivity.runOnUiThread(() -> {
if (view.getViewTranslationCallback() == null) {
if (DEBUG) {
@@ -379,7 +383,6 @@
}
return;
}
- view.onVirtualViewTranslationResponses(virtualChildResponse);
if (view.getViewTranslationCallback() != null) {
view.getViewTranslationCallback().onShowTranslation(view);
}
@@ -427,6 +430,8 @@
+ " may be gone.");
continue;
}
+ int currentState;
+ currentState = mCurrentState;
mActivity.runOnUiThread(() -> {
ViewTranslationCallback callback = view.getViewTranslationCallback();
if (view.getViewTranslationResponse() != null
@@ -460,6 +465,9 @@
callback.enableContentPadding();
}
view.onViewTranslationResponse(response);
+ if (currentState == STATE_UI_TRANSLATION_PAUSED) {
+ return;
+ }
callback.onShowTranslation(view);
});
}
diff --git a/core/java/android/widget/RemoteViews.java b/core/java/android/widget/RemoteViews.java
index fe5eb08..2357d13 100644
--- a/core/java/android/widget/RemoteViews.java
+++ b/core/java/android/widget/RemoteViews.java
@@ -34,6 +34,7 @@
import android.app.ActivityOptions;
import android.app.ActivityThread;
import android.app.Application;
+import android.app.LoadedApk;
import android.app.PendingIntent;
import android.app.RemoteInput;
import android.appwidget.AppWidgetHostView;
@@ -5475,7 +5476,8 @@
// user. So build a context that loads resources from that user but
// still returns the current users userId so settings like data / time formats
// are loaded without requiring cross user persmissions.
- final Context contextForResources = getContextForResources(context);
+ final Context contextForResources =
+ getContextForResourcesEnsuringCorrectCachedApkPaths(context);
if (colorResources != null) {
colorResources.apply(contextForResources);
}
@@ -5793,7 +5795,7 @@
// across orientation change, and has the RemoteViews re-applied in the new orientation,
// we throw an exception, since the layouts may be completely unrelated.
if (hasMultipleLayouts()) {
- if ((Integer) v.getTag(R.id.widget_frame) != rvToApply.getLayoutId()) {
+ if (!rvToApply.canRecycleView(v)) {
throw new RuntimeException("Attempting to re-apply RemoteViews to a view that" +
" that does not share the same root layout id.");
}
@@ -5853,13 +5855,14 @@
}
}
- private Context getContextForResources(Context context) {
+ private Context getContextForResourcesEnsuringCorrectCachedApkPaths(Context context) {
if (mApplication != null) {
if (context.getUserId() == UserHandle.getUserId(mApplication.uid)
&& context.getPackageName().equals(mApplication.packageName)) {
return context;
}
try {
+ LoadedApk.checkAndUpdateApkPaths(mApplication);
return context.createApplicationContext(mApplication,
Context.CONTEXT_RESTRICTED);
} catch (NameNotFoundException e) {
diff --git a/core/java/android/widget/RemoteViewsAdapter.java b/core/java/android/widget/RemoteViewsAdapter.java
index 6b33428..8e293f4 100644
--- a/core/java/android/widget/RemoteViewsAdapter.java
+++ b/core/java/android/widget/RemoteViewsAdapter.java
@@ -408,7 +408,7 @@
}
@Override
- protected Context getRemoteContext() {
+ protected Context getRemoteContextEnsuringCorrectCachedApkPath() {
return null;
}
diff --git a/core/java/android/widget/TextView.java b/core/java/android/widget/TextView.java
index 3eaf852..8fba583 100644
--- a/core/java/android/widget/TextView.java
+++ b/core/java/android/widget/TextView.java
@@ -8751,6 +8751,11 @@
return mEditor != null && mEditor.mInputType != EditorInfo.TYPE_NULL;
}
+ private boolean hasEditorInFocusSearchDirection(@FocusRealDirection int direction) {
+ final View nextView = focusSearch(direction);
+ return nextView != null && nextView.onCheckIsTextEditor();
+ }
+
@Override
public InputConnection onCreateInputConnection(EditorInfo outAttrs) {
if (onCheckIsTextEditor() && isEnabled()) {
@@ -8767,10 +8772,10 @@
outAttrs.imeOptions = EditorInfo.IME_NULL;
outAttrs.hintLocales = null;
}
- if (focusSearch(FOCUS_DOWN) != null) {
+ if (hasEditorInFocusSearchDirection(FOCUS_DOWN)) {
outAttrs.imeOptions |= EditorInfo.IME_FLAG_NAVIGATE_NEXT;
}
- if (focusSearch(FOCUS_UP) != null) {
+ if (hasEditorInFocusSearchDirection(FOCUS_UP)) {
outAttrs.imeOptions |= EditorInfo.IME_FLAG_NAVIGATE_PREVIOUS;
}
if ((outAttrs.imeOptions & EditorInfo.IME_MASK_ACTION)
diff --git a/core/java/com/android/internal/app/procstats/ProcessState.java b/core/java/com/android/internal/app/procstats/ProcessState.java
index d259b7f..87e8ac1 100644
--- a/core/java/com/android/internal/app/procstats/ProcessState.java
+++ b/core/java/com/android/internal/app/procstats/ProcessState.java
@@ -473,6 +473,7 @@
}
}
mCurCombinedState = state;
+ mStats.mUidStates.get(mUid).updateCombinedState(state, now);
}
}
diff --git a/core/java/com/android/internal/app/procstats/ProcessStats.java b/core/java/com/android/internal/app/procstats/ProcessStats.java
index fd16662..b7abe73 100644
--- a/core/java/com/android/internal/app/procstats/ProcessStats.java
+++ b/core/java/com/android/internal/app/procstats/ProcessStats.java
@@ -179,17 +179,19 @@
public static final int REPORT_PKG_ASC_STATS = 0x08;
// Should report package stats.
public static final int REPORT_PKG_STATS = 0x0E;
+ // Should report uid stats.
+ public static final int REPORT_UID_STATS = 0x10;
// Should report all stats.
- public static final int REPORT_ALL = 0x0F;
+ public static final int REPORT_ALL = 0x1F;
public static final int[] OPTIONS =
{REPORT_PROC_STATS, REPORT_PKG_PROC_STATS, REPORT_PKG_SVC_STATS, REPORT_PKG_ASC_STATS,
- REPORT_PKG_STATS, REPORT_ALL};
+ REPORT_PKG_STATS, REPORT_UID_STATS, REPORT_ALL};
public static final String[] OPTIONS_STR =
- {"proc", "pkg-proc", "pkg-svc", "pkg-asc", "pkg-all", "all"};
+ {"proc", "pkg-proc", "pkg-svc", "pkg-asc", "pkg-all", "uid", "all"};
// Current version of the parcel format.
- private static final int PARCEL_VERSION = 40;
+ private static final int PARCEL_VERSION = 41;
// In-memory Parcel magic number, used to detect attempts to unmarshall bad data
private static final int MAGIC = 0x50535454;
@@ -200,6 +202,8 @@
public final ProcessMap<LongSparseArray<PackageState>> mPackages = new ProcessMap<>();
public final ProcessMap<ProcessState> mProcesses = new ProcessMap<>();
+ public final SparseArray<UidState> mUidStates = new SparseArray<>();
+
public final ArrayList<AssociationState.SourceState> mTrackingAssociations = new ArrayList<>();
public final long[] mMemFactorDurations = new long[ADJ_COUNT];
@@ -337,6 +341,18 @@
}
}
+ SparseArray<UidState> uidStates = other.mUidStates;
+ for (int ip = 0, size = uidStates.size(); ip < size; ip++) {
+ final int uid = uidStates.keyAt(ip);
+ UidState uidState = mUidStates.get(uid);
+ if (uidState == null) {
+ uidState = uidStates.valueAt(ip).clone();
+ mUidStates.put(uid, uidState);
+ } else {
+ uidState.add(uidStates.valueAt(ip));
+ }
+ }
+
ArrayMap<String, SparseArray<ProcessState>> procMap = other.mProcesses.getMap();
for (int ip=0; ip<procMap.size(); ip++) {
SparseArray<ProcessState> uids = procMap.valueAt(ip);
@@ -358,9 +374,21 @@
}
}
thisProc.add(otherProc);
+ if (thisProc.isActive()) {
+ UidState uidState = mUidStates.get(uid);
+ if (uidState == null) {
+ uidState = new UidState(this, uid);
+ mUidStates.put(uid, uidState);
+ }
+ uidState.addProcess(thisProc);
+ }
}
}
+ for (int ip = 0, size = mUidStates.size(); ip < size; ip++) {
+ mUidStates.valueAt(ip).updateCombinedState(-1);
+ }
+
for (int i=0; i<ADJ_COUNT; i++) {
if (DEBUG) Slog.d(TAG, "Total duration #" + i + " inc by "
+ other.mMemFactorDurations[i] + " from "
@@ -488,6 +516,7 @@
resetCommon();
mPackages.getMap().clear();
mProcesses.getMap().clear();
+ mUidStates.clear();
mMemFactor = STATE_NOTHING;
mStartTime = 0;
if (DEBUG) Slog.d(TAG, "State reset; now " + mTimePeriodStartClockStr);
@@ -580,6 +609,7 @@
}
} else {
ps.makeDead();
+ mUidStates.get(uids.keyAt(iu)).removeProcess(ps, now);
uids.removeAt(iu);
}
}
@@ -588,6 +618,15 @@
}
}
+ for (int ip = mUidStates.size() - 1; ip >= 0; ip--) {
+ final UidState uidState = mUidStates.valueAt(ip);
+ if (uidState.isInUse()) {
+ mUidStates.valueAt(ip).resetSafely(now);
+ } else {
+ mUidStates.removeAt(ip);
+ }
+ }
+
mStartTime = now;
if (DEBUG) Slog.d(TAG, "State reset; now " + mTimePeriodStartClockStr);
}
@@ -900,6 +939,13 @@
mSysMemUsage.writeToParcel(out);
+ final int numOfUids = mUidStates.size();
+ out.writeInt(numOfUids);
+ for (int ip = 0; ip < numOfUids; ip++) {
+ out.writeInt(mUidStates.keyAt(ip));
+ mUidStates.valueAt(ip).writeToParcel(out, now);
+ }
+
out.writeInt(NPROC);
for (int ip=0; ip<NPROC; ip++) {
writeCommonString(out, procMap.keyAt(ip));
@@ -1026,7 +1072,8 @@
public void readFromParcel(Parcel in) {
final boolean hadData = mPackages.getMap().size() > 0
- || mProcesses.getMap().size() > 0;
+ || mProcesses.getMap().size() > 0
+ || mUidStates.size() > 0;
if (hadData) {
resetSafely();
}
@@ -1083,6 +1130,16 @@
return;
}
+ final int numOfUids = in.readInt();
+ for (int ip = 0; ip < numOfUids; ip++) {
+ final int uid = in.readInt();
+ final UidState uidState = new UidState(this, uid);
+ if (!uidState.readFromParcel(in)) {
+ return;
+ }
+ mUidStates.put(uid, uidState);
+ }
+
int NPROC = in.readInt();
if (NPROC < 0) {
mReadError = "bad process count: " + NPROC;
@@ -1127,9 +1184,17 @@
if (DEBUG_PARCEL) Slog.d(TAG, "Adding process: " + procName + " " + uid
+ " " + proc);
mProcesses.put(procName, uid, proc);
+
+ if (proc.isActive()) {
+ mUidStates.get(uid).addProcess(proc);
+ }
}
}
+ for (int ip = 0; ip < numOfUids; ip++) {
+ mUidStates.valueAt(ip).updateCombinedState(-1);
+ }
+
if (DEBUG_PARCEL) Slog.d(TAG, "Read " + mProcesses.getMap().size() + " processes");
int NPKG = in.readInt();
@@ -1327,6 +1392,12 @@
commonProc = new ProcessState(this, pkgState.mPackageName, pkgState.mUid,
pkgState.mVersionCode, processName);
mProcesses.put(processName, pkgState.mUid, commonProc);
+ UidState uidState = mUidStates.get(pkgState.mUid);
+ if (uidState == null) {
+ uidState = new UidState(this, pkgState.mUid);
+ mUidStates.put(pkgState.mUid, uidState);
+ }
+ uidState.addProcess(commonProc);
if (DEBUG) Slog.d(TAG, "GETPROC created new common " + commonProc);
}
if (!commonProc.isMultiPackage()) {
@@ -1787,6 +1858,42 @@
pw.print(" shown of "); pw.print(numTotalProcs); pw.println(" total");
}
+ if ((section & REPORT_UID_STATS) != 0) {
+ SparseArray<UidState> uidStates = mUidStates;
+ int numShownUids = 0, numTotalUids = 0;
+ printedHeader = false;
+ for (int iu = 0, size = uidStates.size(); iu < size; iu++) {
+ final int uid = uidStates.keyAt(iu);
+ final UidState uidState = uidStates.valueAt(iu);
+ numTotalUids++;
+ if (reqPackage != null && !uidState.hasPackage(reqPackage)) {
+ continue;
+ }
+ numShownUids++;
+ pw.println();
+ if (!printedHeader) {
+ pw.println("Per-UID Stats:");
+ printedHeader = true;
+ }
+ if (activeOnly && !uidState.isInUse()) {
+ pw.print(" (Not active: ");
+ pw.print(UserHandle.formatUid(uid));
+ pw.println(")");
+ continue;
+ }
+ pw.print(" * ");
+ UserHandle.formatUid(pw, uid);
+ pw.print(" (");
+ pw.print(uidState.getDurationsBucketCount());
+ pw.print(" entries)");
+ pw.println(":");
+ uidState.dumpState(pw, " ", ALL_SCREEN_ADJ, ALL_MEM_ADJ,
+ ALL_PROC_STATES, now);
+ }
+ pw.print(" Total UIDs: "); pw.print(numShownUids);
+ pw.print(" shown of "); pw.print(numTotalUids); pw.println(" total");
+ }
+
if (dumpAll) {
pw.println();
if (mTrackingAssociations.size() > 0) {
diff --git a/core/java/com/android/internal/app/procstats/ProcessStatsInternal.java b/core/java/com/android/internal/app/procstats/ProcessStatsInternal.java
new file mode 100644
index 0000000..2f23008
--- /dev/null
+++ b/core/java/com/android/internal/app/procstats/ProcessStatsInternal.java
@@ -0,0 +1,31 @@
+/*
+ * Copyright (C) 2021 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.internal.app.procstats;
+
+import android.util.SparseArray;
+
+/**
+ * The internal interface to access the process stats service, to be used within
+ * system_server only.
+ */
+public abstract class ProcessStatsInternal {
+ /**
+ * Return the duration over the given time, that an UID spent in each processs state
+ * which is defined in the {@link ProcessStats}, the key of the array is the uid.
+ */
+ public abstract SparseArray<long[]> getUidProcStateStatsOverTime(long minTime);
+}
diff --git a/core/java/com/android/internal/app/procstats/UidState.java b/core/java/com/android/internal/app/procstats/UidState.java
new file mode 100644
index 0000000..8761b74
--- /dev/null
+++ b/core/java/com/android/internal/app/procstats/UidState.java
@@ -0,0 +1,315 @@
+/*
+ * Copyright (C) 2021 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.internal.app.procstats;
+
+import static com.android.internal.app.procstats.ProcessStats.STATE_COUNT;
+import static com.android.internal.app.procstats.ProcessStats.STATE_NOTHING;
+
+import android.os.Parcel;
+import android.os.UserHandle;
+import android.text.TextUtils;
+import android.util.ArraySet;
+import android.util.TimeUtils;
+
+import java.io.PrintWriter;
+
+/**
+ * The class to track the individual time-in-state of a UID.
+ */
+public final class UidState {
+ private static final String TAG = "ProcessStats";
+
+ private final ProcessStats mStats;
+ private final int mUid;
+ private final DurationsTable mDurations;
+
+ private ArraySet<ProcessState> mProcesses = new ArraySet<>();
+ private int mCurCombinedState = STATE_NOTHING;
+ private long mStartTime;
+
+ private long mTotalRunningStartTime;
+ private long mTotalRunningDuration;
+
+ /**
+ * Create a new UID state. The initial state is not running.
+ */
+ public UidState(ProcessStats processStats, int uid) {
+ mStats = processStats;
+ mUid = uid;
+ mDurations = new DurationsTable(processStats.mTableData);
+ }
+
+ /**
+ * Create a copy of this instance.
+ */
+ public UidState clone() {
+ UidState unew = new UidState(mStats, mUid);
+ unew.mDurations.addDurations(mDurations);
+ unew.mCurCombinedState = mCurCombinedState;
+ unew.mStartTime = mStartTime;
+ unew.mTotalRunningStartTime = mTotalRunningStartTime;
+ unew.mTotalRunningDuration = mTotalRunningDuration;
+ return unew;
+ }
+
+ /**
+ * Update the current state of the UID, it should be a combination
+ * of all running processes in this UID.
+ */
+ public void updateCombinedState(int state, long now) {
+ if (mCurCombinedState != state) {
+ updateCombinedState(now);
+ }
+ }
+
+ /**
+ * Update the current state of the UID, it should be a combination
+ * of all running processes in this UID.
+ */
+ public void updateCombinedState(long now) {
+ setCombinedStateInner(calcCombinedState(), now);
+ }
+
+ private int calcCombinedState() {
+ int minCombined = STATE_NOTHING;
+ int min = STATE_NOTHING;
+ for (int i = 0, size = mProcesses.size(); i < size; i++) {
+ final int combinedState = mProcesses.valueAt(i).getCombinedState();
+ final int state = combinedState % STATE_COUNT;
+ if (combinedState != STATE_NOTHING) {
+ if (min == STATE_NOTHING || state < min) {
+ minCombined = combinedState;
+ min = state;
+ }
+ }
+ }
+ return minCombined;
+ }
+
+ /**
+ * Set the combined state and commit the state.
+ *
+ * @param now When it's negative, the previous state won't be committed.
+ */
+ private void setCombinedStateInner(int state, long now) {
+ if (mCurCombinedState != state) {
+ if (now >= 0) {
+ commitStateTime(now);
+ if (state == STATE_NOTHING) {
+ // We are transitioning to a no longer running state... stop counting run time.
+ mTotalRunningDuration += now - mTotalRunningStartTime;
+ } else if (mCurCombinedState == STATE_NOTHING) {
+ // We previously weren't running... now starting again, clear out total
+ // running info.
+ mTotalRunningDuration = 0;
+ }
+ }
+ mCurCombinedState = state;
+ }
+ }
+
+ /**
+ * @return The current combine state of the UID.
+ */
+ public int getCombinedState() {
+ return mCurCombinedState;
+ }
+
+ /**
+ * Commit the current state's duration into stats.
+ */
+ public void commitStateTime(long now) {
+ if (mCurCombinedState != STATE_NOTHING) {
+ long dur = now - mStartTime;
+ if (dur > 0) {
+ mDurations.addDuration(mCurCombinedState, dur);
+ }
+ mTotalRunningDuration += now - mTotalRunningStartTime;
+ mTotalRunningStartTime = now;
+ }
+ mStartTime = now;
+ }
+
+ /**
+ * Reset the UID stats safely.
+ */
+ public void resetSafely(long now) {
+ mDurations.resetTable();
+ mStartTime = now;
+ }
+
+ /**
+ * @return Whether this UID stats is still being used or not.
+ */
+ public boolean isInUse() {
+ for (int i = 0, size = mProcesses.size(); i < size; i++) {
+ if (mProcesses.valueAt(i).isInUse()) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ /**
+ * @return Whether the given package belongs to this UID or not.
+ */
+ public boolean hasPackage(String packageName) {
+ for (int i = 0, size = mProcesses.size(); i < size; i++) {
+ final ProcessState proc = mProcesses.valueAt(i);
+ if (TextUtils.equals(packageName, proc.getName())
+ && TextUtils.equals(packageName, proc.getPackage())) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ /**
+ * Add stats data from another instance to this one.
+ */
+ public void add(UidState other) {
+ mDurations.addDurations(other.mDurations);
+ mTotalRunningDuration += other.mTotalRunningDuration;
+ }
+
+ void addProcess(ProcessState proc) {
+ mProcesses.add(proc);
+ }
+
+ void addProcess(ProcessState proc, long now) {
+ mProcesses.add(proc);
+ setCombinedStateInner(proc.getCombinedState(), now);
+ }
+
+ void removeProcess(ProcessState proc, long now) {
+ mProcesses.remove(proc);
+ setCombinedStateInner(proc.getCombinedState(), now);
+ }
+
+ /**
+ * @return The total amount of stats it's currently tracking.
+ */
+ public int getDurationsBucketCount() {
+ return mDurations.getKeyCount();
+ }
+
+ /**
+ * @return The total running duration of this UID.
+ */
+ public long getTotalRunningDuration(long now) {
+ return mTotalRunningDuration
+ + (mTotalRunningStartTime != 0 ? (now - mTotalRunningStartTime) : 0);
+ }
+
+ /**
+ * @return The duration in the given state.
+ */
+ public long getDuration(int state, long now) {
+ long time = mDurations.getValueForId((byte) state);
+ if (mCurCombinedState == state) {
+ time += now - mStartTime;
+ }
+ return time;
+ }
+
+ /**
+ * @return The durations in each process state, the mem/screen factors
+ * are consolidated into the bucket with the same process state.
+ */
+ public long[] getAggregatedDurationsInStates() {
+ final long[] states = new long[STATE_COUNT];
+ final int numOfBuckets = getDurationsBucketCount();
+ for (int i = 0; i < numOfBuckets; i++) {
+ final int key = mDurations.getKeyAt(i);
+ final int combinedState = SparseMappingTable.getIdFromKey(key);
+ states[combinedState % STATE_COUNT] += mDurations.getValue(key);
+ }
+ return states;
+ }
+
+ void writeToParcel(Parcel out, long now) {
+ mDurations.writeToParcel(out);
+ out.writeLong(getTotalRunningDuration(now));
+ }
+
+ boolean readFromParcel(Parcel in) {
+ if (!mDurations.readFromParcel(in)) {
+ return false;
+ }
+ mTotalRunningDuration = in.readLong();
+ return true;
+ }
+
+ @Override
+ public String toString() {
+ StringBuilder sb = new StringBuilder(128);
+ sb.append("UidState{").append(Integer.toHexString(System.identityHashCode(this)))
+ .append(" ").append(UserHandle.formatUid(mUid)).append("}");
+ return sb.toString();
+ }
+
+ void dumpState(PrintWriter pw, String prefix,
+ int[] screenStates, int[] memStates, int[] procStates, long now) {
+ long totalTime = 0;
+ int printedScreen = -1;
+ for (int is = 0; is < screenStates.length; is++) {
+ int printedMem = -1;
+ for (int im = 0; im < memStates.length; im++) {
+ for (int ip = 0; ip < procStates.length; ip++) {
+ final int iscreen = screenStates[is];
+ final int imem = memStates[im];
+ final int bucket = ((iscreen + imem) * STATE_COUNT) + procStates[ip];
+ long time = mDurations.getValueForId((byte) bucket);
+ String running = "";
+ if (mCurCombinedState == bucket) {
+ running = " (running)";
+ time += now - mStartTime;
+ }
+ if (time != 0) {
+ pw.print(prefix);
+ if (screenStates.length > 1) {
+ DumpUtils.printScreenLabel(pw, printedScreen != iscreen
+ ? iscreen : STATE_NOTHING);
+ printedScreen = iscreen;
+ }
+ if (memStates.length > 1) {
+ DumpUtils.printMemLabel(pw,
+ printedMem != imem ? imem : STATE_NOTHING, '/');
+ printedMem = imem;
+ }
+ pw.print(DumpUtils.STATE_LABELS[procStates[ip]]); pw.print(": ");
+ TimeUtils.formatDuration(time, pw); pw.println(running);
+ totalTime += time;
+ }
+ }
+ }
+ }
+ if (totalTime != 0) {
+ pw.print(prefix);
+ if (screenStates.length > 1) {
+ DumpUtils.printScreenLabel(pw, STATE_NOTHING);
+ }
+ if (memStates.length > 1) {
+ DumpUtils.printMemLabel(pw, STATE_NOTHING, '/');
+ }
+ pw.print(DumpUtils.STATE_LABEL_TOTAL);
+ pw.print(": ");
+ TimeUtils.formatDuration(totalTime, pw);
+ pw.println();
+ }
+ }
+}
diff --git a/core/java/com/android/internal/content/om/OverlayConfig.java b/core/java/com/android/internal/content/om/OverlayConfig.java
index 6c73e70..29b31d3 100644
--- a/core/java/com/android/internal/content/om/OverlayConfig.java
+++ b/core/java/com/android/internal/content/om/OverlayConfig.java
@@ -26,20 +26,25 @@
import android.util.IndentingPrintWriter;
import android.util.Log;
+import com.android.apex.ApexInfo;
+import com.android.apex.XmlParser;
import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.content.om.OverlayConfigParser.OverlayPartition;
import com.android.internal.content.om.OverlayConfigParser.ParsedConfiguration;
import com.android.internal.content.om.OverlayScanner.ParsedOverlayInfo;
import com.android.internal.util.Preconditions;
+import com.android.internal.util.function.TriConsumer;
import java.io.File;
+import java.io.FileInputStream;
import java.io.PrintWriter;
import java.util.ArrayList;
import java.util.Arrays;
+import java.util.Collections;
import java.util.Comparator;
import java.util.HashMap;
+import java.util.List;
import java.util.Map;
-import java.util.function.BiConsumer;
import java.util.function.Supplier;
/**
@@ -77,7 +82,7 @@
public interface PackageProvider {
/** Performs the given action for each package. */
- void forEachPackage(BiConsumer<ParsingPackageRead, Boolean> p);
+ void forEachPackage(TriConsumer<ParsingPackageRead, Boolean, File> p);
}
private static final Comparator<ParsedConfiguration> sStaticOverlayComparator = (c1, c2) -> {
@@ -119,6 +124,8 @@
p)));
}
+ ArrayMap<Integer, List<String>> activeApexesPerPartition = getActiveApexes(partitions);
+
boolean foundConfigFile = false;
final Map<String, ParsedOverlayInfo> packageManagerOverlayInfos =
packageProvider == null ? null : getOverlayPackageInfos(packageProvider);
@@ -129,7 +136,9 @@
final OverlayScanner scanner = (scannerFactory == null) ? null : scannerFactory.get();
final ArrayList<ParsedConfiguration> partitionOverlays =
OverlayConfigParser.getConfigurations(partition, scanner,
- packageManagerOverlayInfos);
+ packageManagerOverlayInfos,
+ activeApexesPerPartition.getOrDefault(partition.type,
+ Collections.emptyList()));
if (partitionOverlays != null) {
foundConfigFile = true;
overlays.addAll(partitionOverlays);
@@ -147,7 +156,8 @@
// Filter out overlays not present in the partition.
partitionOverlayInfos = new ArrayList<>(packageManagerOverlayInfos.values());
for (int j = partitionOverlayInfos.size() - 1; j >= 0; j--) {
- if (!partition.containsFile(partitionOverlayInfos.get(j).path)) {
+ if (!partition.containsFile(partitionOverlayInfos.get(j)
+ .getOriginalPartitionPath())) {
partitionOverlayInfos.remove(j);
}
}
@@ -294,16 +304,50 @@
private static Map<String, ParsedOverlayInfo> getOverlayPackageInfos(
@NonNull PackageProvider packageManager) {
final HashMap<String, ParsedOverlayInfo> overlays = new HashMap<>();
- packageManager.forEachPackage((ParsingPackageRead p, Boolean isSystem) -> {
+ packageManager.forEachPackage((ParsingPackageRead p, Boolean isSystem,
+ @Nullable File preInstalledApexPath) -> {
if (p.getOverlayTarget() != null && isSystem) {
overlays.put(p.getPackageName(), new ParsedOverlayInfo(p.getPackageName(),
p.getOverlayTarget(), p.getTargetSdkVersion(), p.isOverlayIsStatic(),
- p.getOverlayPriority(), new File(p.getBaseApkPath())));
+ p.getOverlayPriority(), new File(p.getBaseApkPath()),
+ preInstalledApexPath));
}
});
return overlays;
}
+ /** Returns a map of PartitionType to List of active APEX module names. */
+ @NonNull
+ private static ArrayMap<Integer, List<String>> getActiveApexes(
+ @NonNull List<OverlayPartition> partitions) {
+ // An Overlay in an APEX, which is an update of an APEX in a given partition,
+ // is considered as belonging to that partition.
+ ArrayMap<Integer, List<String>> result = new ArrayMap<>();
+ for (OverlayPartition partition : partitions) {
+ result.put(partition.type, new ArrayList<String>());
+ }
+ // Read from apex-info-list because ApexManager is not accessible to zygote.
+ File apexInfoList = new File("/apex/apex-info-list.xml");
+ if (apexInfoList.exists() && apexInfoList.canRead()) {
+ try (FileInputStream stream = new FileInputStream(apexInfoList)) {
+ List<ApexInfo> apexInfos = XmlParser.readApexInfoList(stream).getApexInfo();
+ for (ApexInfo info : apexInfos) {
+ if (info.getIsActive()) {
+ for (OverlayPartition partition : partitions) {
+ if (partition.containsPath(info.getPreinstalledModulePath())) {
+ result.get(partition.type).add(info.getModuleName());
+ break;
+ }
+ }
+ }
+ }
+ } catch (Exception e) {
+ Log.w(TAG, "Error reading apex-info-list: " + e);
+ }
+ }
+ return result;
+ }
+
/** Represents a single call to idmap create-multiple. */
@VisibleForTesting
public static class IdmapInvocation {
diff --git a/core/java/com/android/internal/content/om/OverlayConfigParser.java b/core/java/com/android/internal/content/om/OverlayConfigParser.java
index 053a341..0ab7b3d 100644
--- a/core/java/com/android/internal/content/om/OverlayConfigParser.java
+++ b/core/java/com/android/internal/content/om/OverlayConfigParser.java
@@ -41,6 +41,7 @@
import java.io.FileReader;
import java.io.IOException;
import java.util.ArrayList;
+import java.util.List;
import java.util.Map;
/**
@@ -195,13 +196,19 @@
@Nullable
static ArrayList<ParsedConfiguration> getConfigurations(
@NonNull OverlayPartition partition, @Nullable OverlayScanner scanner,
- @Nullable Map<String, ParsedOverlayInfo> packageManagerOverlayInfos) {
- if (partition.getOverlayFolder() == null) {
- return null;
+ @Nullable Map<String, ParsedOverlayInfo> packageManagerOverlayInfos,
+ @NonNull List<String> activeApexes) {
+ if (scanner != null) {
+ if (partition.getOverlayFolder() != null) {
+ scanner.scanDir(partition.getOverlayFolder());
+ }
+ for (String apex : activeApexes) {
+ scanner.scanDir(new File("/apex/" + apex + "/overlay/"));
+ }
}
- if (scanner != null) {
- scanner.scanDir(partition.getOverlayFolder());
+ if (partition.getOverlayFolder() == null) {
+ return null;
}
final File configFile = new File(partition.getOverlayFolder(), CONFIG_DEFAULT_FILENAME);
diff --git a/core/java/com/android/internal/content/om/OverlayScanner.java b/core/java/com/android/internal/content/om/OverlayScanner.java
index 4387d1b..e4e0228 100644
--- a/core/java/com/android/internal/content/om/OverlayScanner.java
+++ b/core/java/com/android/internal/content/om/OverlayScanner.java
@@ -54,23 +54,38 @@
public final boolean isStatic;
public final int priority;
public final File path;
+ @Nullable public final File preInstalledApexPath;
public ParsedOverlayInfo(String packageName, String targetPackageName,
- int targetSdkVersion, boolean isStatic, int priority, File path) {
+ int targetSdkVersion, boolean isStatic, int priority, File path,
+ @Nullable File preInstalledApexPath) {
this.packageName = packageName;
this.targetPackageName = targetPackageName;
this.targetSdkVersion = targetSdkVersion;
this.isStatic = isStatic;
this.priority = priority;
this.path = path;
+ this.preInstalledApexPath = preInstalledApexPath;
}
@Override
public String toString() {
return getClass().getSimpleName() + String.format("{packageName=%s"
+ ", targetPackageName=%s, targetSdkVersion=%s, isStatic=%s"
- + ", priority=%s, path=%s}",
- packageName, targetPackageName, targetSdkVersion, isStatic, priority, path);
+ + ", priority=%s, path=%s, preInstalledApexPath=%s}",
+ packageName, targetPackageName, targetSdkVersion, isStatic,
+ priority, path, preInstalledApexPath);
+ }
+
+ /**
+ * Retrieves the path of the overlay in its original installation partition.
+ *
+ * An Overlay in an APEX, which is an update of an APEX in a given partition,
+ * is considered as belonging to that partition.
+ */
+ @NonNull
+ public File getOriginalPartitionPath() {
+ return preInstalledApexPath != null ? preInstalledApexPath : path;
}
}
@@ -189,6 +204,6 @@
}
return new ParsedOverlayInfo(apkLite.getPackageName(), apkLite.getTargetPackageName(),
apkLite.getTargetSdkVersion(), apkLite.isOverlayIsStatic(),
- apkLite.getOverlayPriority(), new File(apkLite.getPath()));
+ apkLite.getOverlayPriority(), new File(apkLite.getPath()), null);
}
}
diff --git a/core/java/com/android/internal/inputmethod/IInputContextInvoker.java b/core/java/com/android/internal/inputmethod/IInputContextInvoker.java
index 001e304..efdf483 100644
--- a/core/java/com/android/internal/inputmethod/IInputContextInvoker.java
+++ b/core/java/com/android/internal/inputmethod/IInputContextInvoker.java
@@ -59,7 +59,8 @@
@NonNull
InputConnectionCommandHeader createHeader() {
- return new InputConnectionCommandHeader();
+ // TODO(b/203086369): Propagate session ID for interruption
+ return new InputConnectionCommandHeader(0 /* sessionId */);
}
/**
diff --git a/core/java/com/android/internal/inputmethod/InputConnectionCommandHeader.java b/core/java/com/android/internal/inputmethod/InputConnectionCommandHeader.java
index 4bd8d0c..d9141bd 100644
--- a/core/java/com/android/internal/inputmethod/InputConnectionCommandHeader.java
+++ b/core/java/com/android/internal/inputmethod/InputConnectionCommandHeader.java
@@ -25,7 +25,19 @@
* {@link android.inputmethodservice.RemoteInputConnection}.
*/
public final class InputConnectionCommandHeader implements Parcelable {
- public InputConnectionCommandHeader() {
+ /**
+ * An identifier that is to be used when multiplexing multiple sessions into a single
+ * {@link com.android.internal.view.IInputContext}.
+ *
+ * <p>This ID is considered to belong to an implicit namespace defined for each
+ * {@link com.android.internal.view.IInputContext} instance. Uniqueness of the session ID
+ * across multiple instances of {@link com.android.internal.view.IInputContext} is not
+ * guaranteed unless explicitly noted in a higher layer.</p>
+ */
+ public final int mSessionId;
+
+ public InputConnectionCommandHeader(int sessionId) {
+ mSessionId = sessionId;
}
@Override
@@ -38,7 +50,8 @@
new Parcelable.Creator<InputConnectionCommandHeader>() {
@NonNull
public InputConnectionCommandHeader createFromParcel(Parcel in) {
- return new InputConnectionCommandHeader();
+ final int sessionId = in.readInt();
+ return new InputConnectionCommandHeader(sessionId);
}
@NonNull
@@ -49,5 +62,6 @@
@Override
public void writeToParcel(@NonNull Parcel dest, int flags) {
+ dest.writeInt(mSessionId);
}
}
diff --git a/core/java/com/android/internal/inputmethod/RemoteInputConnectionImpl.java b/core/java/com/android/internal/inputmethod/RemoteInputConnectionImpl.java
index 3867afd..21358ab 100644
--- a/core/java/com/android/internal/inputmethod/RemoteInputConnectionImpl.java
+++ b/core/java/com/android/internal/inputmethod/RemoteInputConnectionImpl.java
@@ -23,6 +23,8 @@
import static com.android.internal.inputmethod.InputConnectionProtoDumper.buildGetTextAfterCursorProto;
import static com.android.internal.inputmethod.InputConnectionProtoDumper.buildGetTextBeforeCursorProto;
+import static java.lang.annotation.RetentionPolicy.SOURCE;
+
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.os.Bundle;
@@ -45,7 +47,9 @@
import com.android.internal.infra.AndroidFuture;
import com.android.internal.view.IInputContext;
+import java.lang.annotation.Retention;
import java.lang.ref.WeakReference;
+import java.util.concurrent.atomic.AtomicInteger;
import java.util.function.Function;
import java.util.function.Supplier;
@@ -62,6 +66,11 @@
private static final String TAG = "RemoteInputConnectionImpl";
private static final boolean DEBUG = false;
+ @Retention(SOURCE)
+ private @interface Dispatching {
+ boolean cancellable();
+ }
+
@GuardedBy("mLock")
@Nullable
private InputConnection mInputConnection;
@@ -77,6 +86,9 @@
private final InputMethodManager mParentInputMethodManager;
private final WeakReference<View> mServedView;
+ // TODO(b/203086369): This is to be used when interruption is implemented.
+ private final AtomicInteger mCurrentSessionId = new AtomicInteger(0);
+
public RemoteInputConnectionImpl(@NonNull Looper looper,
@NonNull InputConnection inputConnection,
@NonNull InputMethodManager inputMethodManager, @Nullable View servedView) {
@@ -120,6 +132,7 @@
*
* <p>Multiple invocations will be simply ignored.</p>
*/
+ @Dispatching(cancellable = false)
public void deactivate() {
if (isFinished()) {
// This is a small performance optimization. Still only the 1st call of
@@ -214,6 +227,7 @@
* @param enabled the parameter to be passed to
* {@link InputConnection#reportFullscreenMode(boolean)}.
*/
+ @Dispatching(cancellable = false)
public void dispatchReportFullscreenMode(boolean enabled) {
dispatch(() -> {
final InputConnection ic = getInputConnection();
@@ -224,10 +238,14 @@
});
}
+ @Dispatching(cancellable = true)
@Override
public void getTextAfterCursor(InputConnectionCommandHeader header, int length, int flags,
AndroidFuture future /* T=CharSequence */) {
dispatchWithTracing("getTextAfterCursor", future, () -> {
+ if (header.mSessionId != mCurrentSessionId.get()) {
+ return null; // cancelled
+ }
final InputConnection ic = getInputConnection();
if (ic == null || !isActive()) {
Log.w(TAG, "getTextAfterCursor on inactive InputConnection");
@@ -242,10 +260,14 @@
}, useImeTracing() ? result -> buildGetTextAfterCursorProto(length, flags, result) : null);
}
+ @Dispatching(cancellable = true)
@Override
public void getTextBeforeCursor(InputConnectionCommandHeader header, int length, int flags,
AndroidFuture future /* T=CharSequence */) {
dispatchWithTracing("getTextBeforeCursor", future, () -> {
+ if (header.mSessionId != mCurrentSessionId.get()) {
+ return null; // cancelled
+ }
final InputConnection ic = getInputConnection();
if (ic == null || !isActive()) {
Log.w(TAG, "getTextBeforeCursor on inactive InputConnection");
@@ -260,10 +282,14 @@
}, useImeTracing() ? result -> buildGetTextBeforeCursorProto(length, flags, result) : null);
}
+ @Dispatching(cancellable = true)
@Override
public void getSelectedText(InputConnectionCommandHeader header, int flags,
AndroidFuture future /* T=CharSequence */) {
dispatchWithTracing("getSelectedText", future, () -> {
+ if (header.mSessionId != mCurrentSessionId.get()) {
+ return null; // cancelled
+ }
final InputConnection ic = getInputConnection();
if (ic == null || !isActive()) {
Log.w(TAG, "getSelectedText on inactive InputConnection");
@@ -278,10 +304,14 @@
}, useImeTracing() ? result -> buildGetSelectedTextProto(flags, result) : null);
}
+ @Dispatching(cancellable = true)
@Override
public void getSurroundingText(InputConnectionCommandHeader header, int beforeLength,
int afterLength, int flags, AndroidFuture future /* T=SurroundingText */) {
dispatchWithTracing("getSurroundingText", future, () -> {
+ if (header.mSessionId != mCurrentSessionId.get()) {
+ return null; // cancelled
+ }
final InputConnection ic = getInputConnection();
if (ic == null || !isActive()) {
Log.w(TAG, "getSurroundingText on inactive InputConnection");
@@ -302,10 +332,14 @@
beforeLength, afterLength, flags, result) : null);
}
+ @Dispatching(cancellable = true)
@Override
public void getCursorCapsMode(InputConnectionCommandHeader header, int reqModes,
AndroidFuture future /* T=Integer */) {
dispatchWithTracing("getCursorCapsMode", future, () -> {
+ if (header.mSessionId != mCurrentSessionId.get()) {
+ return 0; // cancelled
+ }
final InputConnection ic = getInputConnection();
if (ic == null || !isActive()) {
Log.w(TAG, "getCursorCapsMode on inactive InputConnection");
@@ -315,10 +349,14 @@
}, useImeTracing() ? result -> buildGetCursorCapsModeProto(reqModes, result) : null);
}
+ @Dispatching(cancellable = true)
@Override
public void getExtractedText(InputConnectionCommandHeader header, ExtractedTextRequest request,
int flags, AndroidFuture future /* T=ExtractedText */) {
dispatchWithTracing("getExtractedText", future, () -> {
+ if (header.mSessionId != mCurrentSessionId.get()) {
+ return null; // cancelled
+ }
final InputConnection ic = getInputConnection();
if (ic == null || !isActive()) {
Log.w(TAG, "getExtractedText on inactive InputConnection");
@@ -328,10 +366,14 @@
}, useImeTracing() ? result -> buildGetExtractedTextProto(request, flags, result) : null);
}
+ @Dispatching(cancellable = true)
@Override
public void commitText(InputConnectionCommandHeader header, CharSequence text,
int newCursorPosition) {
dispatchWithTracing("commitText", () -> {
+ if (header.mSessionId != mCurrentSessionId.get()) {
+ return; // cancelled
+ }
InputConnection ic = getInputConnection();
if (ic == null || !isActive()) {
Log.w(TAG, "commitText on inactive InputConnection");
@@ -341,9 +383,13 @@
});
}
+ @Dispatching(cancellable = true)
@Override
public void commitCompletion(InputConnectionCommandHeader header, CompletionInfo text) {
dispatchWithTracing("commitCompletion", () -> {
+ if (header.mSessionId != mCurrentSessionId.get()) {
+ return; // cancelled
+ }
InputConnection ic = getInputConnection();
if (ic == null || !isActive()) {
Log.w(TAG, "commitCompletion on inactive InputConnection");
@@ -353,9 +399,13 @@
});
}
+ @Dispatching(cancellable = true)
@Override
public void commitCorrection(InputConnectionCommandHeader header, CorrectionInfo info) {
dispatchWithTracing("commitCorrection", () -> {
+ if (header.mSessionId != mCurrentSessionId.get()) {
+ return; // cancelled
+ }
InputConnection ic = getInputConnection();
if (ic == null || !isActive()) {
Log.w(TAG, "commitCorrection on inactive InputConnection");
@@ -369,9 +419,13 @@
});
}
+ @Dispatching(cancellable = true)
@Override
public void setSelection(InputConnectionCommandHeader header, int start, int end) {
dispatchWithTracing("setSelection", () -> {
+ if (header.mSessionId != mCurrentSessionId.get()) {
+ return; // cancelled
+ }
InputConnection ic = getInputConnection();
if (ic == null || !isActive()) {
Log.w(TAG, "setSelection on inactive InputConnection");
@@ -381,9 +435,13 @@
});
}
+ @Dispatching(cancellable = true)
@Override
public void performEditorAction(InputConnectionCommandHeader header, int id) {
dispatchWithTracing("performEditorAction", () -> {
+ if (header.mSessionId != mCurrentSessionId.get()) {
+ return; // cancelled
+ }
InputConnection ic = getInputConnection();
if (ic == null || !isActive()) {
Log.w(TAG, "performEditorAction on inactive InputConnection");
@@ -393,9 +451,13 @@
});
}
+ @Dispatching(cancellable = true)
@Override
public void performContextMenuAction(InputConnectionCommandHeader header, int id) {
dispatchWithTracing("performContextMenuAction", () -> {
+ if (header.mSessionId != mCurrentSessionId.get()) {
+ return; // cancelled
+ }
InputConnection ic = getInputConnection();
if (ic == null || !isActive()) {
Log.w(TAG, "performContextMenuAction on inactive InputConnection");
@@ -405,9 +467,13 @@
});
}
+ @Dispatching(cancellable = true)
@Override
public void setComposingRegion(InputConnectionCommandHeader header, int start, int end) {
dispatchWithTracing("setComposingRegion", () -> {
+ if (header.mSessionId != mCurrentSessionId.get()) {
+ return; // cancelled
+ }
InputConnection ic = getInputConnection();
if (ic == null || !isActive()) {
Log.w(TAG, "setComposingRegion on inactive InputConnection");
@@ -421,10 +487,14 @@
});
}
+ @Dispatching(cancellable = true)
@Override
public void setComposingText(InputConnectionCommandHeader header, CharSequence text,
int newCursorPosition) {
dispatchWithTracing("setComposingText", () -> {
+ if (header.mSessionId != mCurrentSessionId.get()) {
+ return; // cancelled
+ }
InputConnection ic = getInputConnection();
if (ic == null || !isActive()) {
Log.w(TAG, "setComposingText on inactive InputConnection");
@@ -439,7 +509,9 @@
*
* <p>This method is intended to be called only from {@link InputMethodManager}.</p>
*/
+ @Dispatching(cancellable = true)
public void finishComposingTextFromImm() {
+ final int currentSessionId = mCurrentSessionId.get();
dispatchWithTracing("finishComposingTextFromImm", () -> {
if (isFinished()) {
// In this case, #finishComposingText() is guaranteed to be called already.
@@ -449,6 +521,9 @@
}
return;
}
+ if (currentSessionId != mCurrentSessionId.get()) {
+ return; // cancelled
+ }
InputConnection ic = getInputConnection();
// Note we do NOT check isActive() here, because this is safe
// for an IME to call at any time, and we need to allow it
@@ -462,6 +537,7 @@
});
}
+ @Dispatching(cancellable = true)
@Override
public void finishComposingText(InputConnectionCommandHeader header) {
dispatchWithTracing("finishComposingText", () -> {
@@ -473,6 +549,9 @@
}
return;
}
+ if (header.mSessionId != mCurrentSessionId.get()) {
+ return; // cancelled
+ }
InputConnection ic = getInputConnection();
// Note we do NOT check isActive() here, because this is safe
// for an IME to call at any time, and we need to allow it
@@ -486,9 +565,13 @@
});
}
+ @Dispatching(cancellable = true)
@Override
public void sendKeyEvent(InputConnectionCommandHeader header, KeyEvent event) {
dispatchWithTracing("sendKeyEvent", () -> {
+ if (header.mSessionId != mCurrentSessionId.get()) {
+ return; // cancelled
+ }
InputConnection ic = getInputConnection();
if (ic == null || !isActive()) {
Log.w(TAG, "sendKeyEvent on inactive InputConnection");
@@ -498,9 +581,13 @@
});
}
+ @Dispatching(cancellable = true)
@Override
public void clearMetaKeyStates(InputConnectionCommandHeader header, int states) {
dispatchWithTracing("clearMetaKeyStates", () -> {
+ if (header.mSessionId != mCurrentSessionId.get()) {
+ return; // cancelled
+ }
InputConnection ic = getInputConnection();
if (ic == null || !isActive()) {
Log.w(TAG, "clearMetaKeyStates on inactive InputConnection");
@@ -510,10 +597,14 @@
});
}
+ @Dispatching(cancellable = true)
@Override
public void deleteSurroundingText(InputConnectionCommandHeader header, int beforeLength,
int afterLength) {
dispatchWithTracing("deleteSurroundingText", () -> {
+ if (header.mSessionId != mCurrentSessionId.get()) {
+ return; // cancelled
+ }
InputConnection ic = getInputConnection();
if (ic == null || !isActive()) {
Log.w(TAG, "deleteSurroundingText on inactive InputConnection");
@@ -523,10 +614,14 @@
});
}
+ @Dispatching(cancellable = true)
@Override
public void deleteSurroundingTextInCodePoints(InputConnectionCommandHeader header,
int beforeLength, int afterLength) {
dispatchWithTracing("deleteSurroundingTextInCodePoints", () -> {
+ if (header.mSessionId != mCurrentSessionId.get()) {
+ return; // cancelled
+ }
InputConnection ic = getInputConnection();
if (ic == null || !isActive()) {
Log.w(TAG, "deleteSurroundingTextInCodePoints on inactive InputConnection");
@@ -540,9 +635,13 @@
});
}
+ @Dispatching(cancellable = true)
@Override
public void beginBatchEdit(InputConnectionCommandHeader header) {
dispatchWithTracing("beginBatchEdit", () -> {
+ if (header.mSessionId != mCurrentSessionId.get()) {
+ return; // cancelled
+ }
InputConnection ic = getInputConnection();
if (ic == null || !isActive()) {
Log.w(TAG, "beginBatchEdit on inactive InputConnection");
@@ -552,9 +651,13 @@
});
}
+ @Dispatching(cancellable = true)
@Override
public void endBatchEdit(InputConnectionCommandHeader header) {
dispatchWithTracing("endBatchEdit", () -> {
+ if (header.mSessionId != mCurrentSessionId.get()) {
+ return; // cancelled
+ }
InputConnection ic = getInputConnection();
if (ic == null || !isActive()) {
Log.w(TAG, "endBatchEdit on inactive InputConnection");
@@ -564,9 +667,13 @@
});
}
+ @Dispatching(cancellable = true)
@Override
public void performSpellCheck(InputConnectionCommandHeader header) {
dispatchWithTracing("performSpellCheck", () -> {
+ if (header.mSessionId != mCurrentSessionId.get()) {
+ return; // cancelled
+ }
InputConnection ic = getInputConnection();
if (ic == null || !isActive()) {
Log.w(TAG, "performSpellCheck on inactive InputConnection");
@@ -576,10 +683,14 @@
});
}
+ @Dispatching(cancellable = true)
@Override
public void performPrivateCommand(InputConnectionCommandHeader header, String action,
Bundle data) {
dispatchWithTracing("performPrivateCommand", () -> {
+ if (header.mSessionId != mCurrentSessionId.get()) {
+ return; // cancelled
+ }
InputConnection ic = getInputConnection();
if (ic == null || !isActive()) {
Log.w(TAG, "performPrivateCommand on inactive InputConnection");
@@ -589,10 +700,14 @@
});
}
+ @Dispatching(cancellable = true)
@Override
public void requestCursorUpdates(InputConnectionCommandHeader header, int cursorUpdateMode,
int imeDisplayId, AndroidFuture future /* T=Boolean */) {
dispatchWithTracing("requestCursorUpdates", future, () -> {
+ if (header.mSessionId != mCurrentSessionId.get()) {
+ return false; // cancelled
+ }
final InputConnection ic = getInputConnection();
if (ic == null || !isActive()) {
Log.w(TAG, "requestCursorAnchorInfo on inactive InputConnection");
@@ -611,11 +726,15 @@
});
}
+ @Dispatching(cancellable = true)
@Override
public void commitContent(InputConnectionCommandHeader header,
InputContentInfo inputContentInfo, int flags, Bundle opts,
AndroidFuture future /* T=Boolean */) {
dispatchWithTracing("commitContent", future, () -> {
+ if (header.mSessionId != mCurrentSessionId.get()) {
+ return false; // cancelled
+ }
final InputConnection ic = getInputConnection();
if (ic == null || !isActive()) {
Log.w(TAG, "commitContent on inactive InputConnection");
@@ -634,9 +753,13 @@
});
}
+ @Dispatching(cancellable = true)
@Override
public void setImeConsumesInput(InputConnectionCommandHeader header, boolean imeConsumesInput) {
dispatchWithTracing("setImeConsumesInput", () -> {
+ if (header.mSessionId != mCurrentSessionId.get()) {
+ return; // cancelled
+ }
InputConnection ic = getInputConnection();
if (ic == null || !isActive()) {
Log.w(TAG, "setImeConsumesInput on inactive InputConnection");
diff --git a/core/java/com/android/internal/os/BatteryStatsImpl.java b/core/java/com/android/internal/os/BatteryStatsImpl.java
index 985331c..9bdf608 100644
--- a/core/java/com/android/internal/os/BatteryStatsImpl.java
+++ b/core/java/com/android/internal/os/BatteryStatsImpl.java
@@ -160,7 +160,7 @@
private static final int MAGIC = 0xBA757475; // 'BATSTATS'
// Current on-disk Parcel version
- static final int VERSION = 202;
+ static final int VERSION = 203;
// The maximum number of names wakelocks we will keep track of
// per uid; once the limit is reached, we batch the remaining wakelocks
@@ -237,6 +237,10 @@
return mKernelMemoryStats;
}
+ private static final int[] SUPPORTED_PER_PROCESS_STATE_STANDARD_ENERGY_BUCKETS = {
+ MeasuredEnergyStats.POWER_BUCKET_CPU,
+ };
+
@GuardedBy("this")
public boolean mPerProcStateCpuTimesAvailable = true;
@@ -526,6 +530,7 @@
* mPendingRemovedUids queue.
*/
@GuardedBy("this")
+ @SuppressWarnings("GuardedBy") // errorprone false positive on removeLocked
public void clearPendingRemovedUidsLocked() {
long cutOffTimeMs = mClock.elapsedRealtime() - mConstants.UID_REMOVE_DELAY_MS;
while (!mPendingRemovedUids.isEmpty()
@@ -583,6 +588,10 @@
procState = u.mProcessState;
}
+ if (procState == ActivityManager.PROCESS_STATE_NONEXISTENT) {
+ continue;
+ }
+
final long timestampMs = mClock.elapsedRealtime();
final LongArrayMultiStateCounter onBatteryCounter =
u.getProcStateTimeCounter().getCounter();
@@ -1061,6 +1070,10 @@
int mWifiRadioPowerState = DataConnectionRealTimeInfo.DC_POWER_STATE_LOW;
+ @GuardedBy("this")
+ @VisibleForTesting
+ protected @Nullable MeasuredEnergyStats.Config mMeasuredEnergyStatsConfig;
+
/**
* Accumulated global (generally, device-wide total) charge consumption of various consumers
* while on battery.
@@ -3564,6 +3577,7 @@
// from a battery level change.
static final int BATTERY_DELTA_LEVEL_FLAG = 0x00000001;
+ @GuardedBy("this")
public void writeHistoryDelta(Parcel dest, HistoryItem cur, HistoryItem last) {
if (last == null || cur.cmd != HistoryItem.CMD_UPDATE) {
dest.writeInt(DELTA_TIME_ABS);
@@ -3836,11 +3850,13 @@
mLastStepStatIdleTimeMs = mCurStepStatIdleTimeMs;
}
+ @GuardedBy("this")
@Override
public void commitCurrentHistoryBatchLocked() {
mHistoryLastWritten.cmd = HistoryItem.CMD_NULL;
}
+ @GuardedBy("this")
public void createFakeHistoryEvents(long numEvents) {
final long elapsedRealtimeMs = mClock.elapsedRealtime();
final long uptimeMs = mClock.uptimeMillis();
@@ -3852,6 +3868,7 @@
}
}
+ @GuardedBy("this")
void addHistoryBufferLocked(long elapsedRealtimeMs, long uptimeMs, HistoryItem cur) {
if (!mHaveBatteryLevel || !mRecordingHistory) {
return;
@@ -3955,6 +3972,7 @@
addHistoryBufferLocked(elapsedRealtimeMs, HistoryItem.CMD_UPDATE, cur);
}
+ @GuardedBy("this")
private void addHistoryBufferLocked(long elapsedRealtimeMs, byte cmd, HistoryItem cur) {
if (mBatteryStatsHistoryIterator != null) {
throw new IllegalStateException("Can't do this while iterating history!");
@@ -3981,6 +3999,7 @@
int mChangedStates = 0;
int mChangedStates2 = 0;
+ @GuardedBy("this")
void addHistoryRecordLocked(long elapsedRealtimeMs, long uptimeMs) {
if (mTrackRunningHistoryElapsedRealtimeMs != 0) {
final long diffElapsedMs = elapsedRealtimeMs - mTrackRunningHistoryElapsedRealtimeMs;
@@ -4001,10 +4020,12 @@
addHistoryRecordInnerLocked(elapsedRealtimeMs, uptimeMs, mHistoryCur);
}
+ @GuardedBy("this")
void addHistoryRecordInnerLocked(long elapsedRealtimeMs, long uptimeMs, HistoryItem cur) {
addHistoryBufferLocked(elapsedRealtimeMs, uptimeMs, cur);
}
+ @GuardedBy("this")
public void addHistoryEventLocked(long elapsedRealtimeMs, long uptimeMs, int code,
String name, int uid) {
mHistoryCur.eventCode = code;
@@ -4014,6 +4035,7 @@
addHistoryRecordLocked(elapsedRealtimeMs, uptimeMs);
}
+ @GuardedBy("this")
void addHistoryRecordLocked(long elapsedRealtimeMs, long uptimeMs, byte cmd, HistoryItem cur) {
HistoryItem rec = mHistoryCache;
if (rec != null) {
@@ -4026,6 +4048,7 @@
addHistoryRecordLocked(rec);
}
+ @GuardedBy("this")
void addHistoryRecordLocked(HistoryItem rec) {
mNumHistoryItems++;
rec.next = null;
@@ -4038,6 +4061,7 @@
}
}
+ @GuardedBy("this")
void clearHistoryLocked() {
if (DEBUG_HISTORY) Slog.i(TAG, "********** CLEARING HISTORY!");
mHistoryBaseTimeMs = 0;
@@ -4100,6 +4124,7 @@
}
}
+ @GuardedBy("this")
private void updateBatteryPropertiesLocked() {
try {
IBatteryPropertiesRegistrar registrar = IBatteryPropertiesRegistrar.Stub.asInterface(
@@ -4112,11 +4137,14 @@
}
}
+ @GuardedBy("this")
public void addIsolatedUidLocked(int isolatedUid, int appUid) {
addIsolatedUidLocked(isolatedUid, appUid,
mClock.elapsedRealtime(), mClock.uptimeMillis());
}
+ @GuardedBy("this")
+ @SuppressWarnings("GuardedBy") // errorprone false positive on u.addIsolatedUid
public void addIsolatedUidLocked(int isolatedUid, int appUid,
long elapsedRealtimeMs, long uptimeMs) {
mIsolatedUids.put(isolatedUid, appUid);
@@ -4191,10 +4219,12 @@
return isolated > 0 ? isolated : uid;
}
+ @GuardedBy("this")
public void noteEventLocked(int code, String name, int uid) {
noteEventLocked(code, name, uid, mClock.elapsedRealtime(), mClock.uptimeMillis());
}
+ @GuardedBy("this")
public void noteEventLocked(int code, String name, int uid,
long elapsedRealtimeMs, long uptimeMs) {
uid = mapUid(uid);
@@ -4204,6 +4234,7 @@
addHistoryEventLocked(elapsedRealtimeMs, uptimeMs, code, name, uid);
}
+ @GuardedBy("this")
public void noteCurrentTimeChangedLocked() {
final long currentTime = mClock.currentTimeMillis();
final long elapsedRealtime = mClock.elapsedRealtime();
@@ -4211,15 +4242,18 @@
noteCurrentTimeChangedLocked(currentTime, elapsedRealtime, uptime);
}
+ @GuardedBy("this")
public void noteCurrentTimeChangedLocked(long currentTimeMs,
long elapsedRealtimeMs, long uptimeMs) {
recordCurrentTimeChangeLocked(currentTimeMs, elapsedRealtimeMs, uptimeMs);
}
+ @GuardedBy("this")
public void noteProcessStartLocked(String name, int uid) {
noteProcessStartLocked(name, uid, mClock.elapsedRealtime(), mClock.uptimeMillis());
}
+ @GuardedBy("this")
public void noteProcessStartLocked(String name, int uid,
long elapsedRealtimeMs, long uptimeMs) {
uid = mapUid(uid);
@@ -4236,10 +4270,12 @@
addHistoryEventLocked(elapsedRealtimeMs, uptimeMs, HistoryItem.EVENT_PROC_START, name, uid);
}
+ @GuardedBy("this")
public void noteProcessCrashLocked(String name, int uid) {
noteProcessCrashLocked(name, uid, mClock.elapsedRealtime(), mClock.uptimeMillis());
}
+ @GuardedBy("this")
public void noteProcessCrashLocked(String name, int uid,
long elapsedRealtimeMs, long uptimeMs) {
uid = mapUid(uid);
@@ -4249,10 +4285,12 @@
}
}
+ @GuardedBy("this")
public void noteProcessAnrLocked(String name, int uid) {
noteProcessAnrLocked(name, uid, mClock.elapsedRealtime(), mClock.uptimeMillis());
}
+ @GuardedBy("this")
public void noteProcessAnrLocked(String name, int uid, long elapsedRealtimeMs, long uptimeMs) {
uid = mapUid(uid);
if (isOnBattery()) {
@@ -4261,10 +4299,13 @@
}
}
+ @GuardedBy("this")
public void noteUidProcessStateLocked(int uid, int state) {
noteUidProcessStateLocked(uid, state, mClock.elapsedRealtime(), mClock.uptimeMillis());
}
+ @GuardedBy("this")
+ @SuppressWarnings("GuardedBy") // errorprone false positive on u.updateUidProcessStateLocked
public void noteUidProcessStateLocked(int uid, int state,
long elapsedRealtimeMs, long uptimeMs) {
int parentUid = mapUid(uid);
@@ -4282,10 +4323,12 @@
.updateUidProcessStateLocked(state, elapsedRealtimeMs, uptimeMs);
}
+ @GuardedBy("this")
public void noteProcessFinishLocked(String name, int uid) {
noteProcessFinishLocked(name, uid, mClock.elapsedRealtime(), mClock.uptimeMillis());
}
+ @GuardedBy("this")
public void noteProcessFinishLocked(String name, int uid,
long elapsedRealtimeMs, long uptimeMs) {
uid = mapUid(uid);
@@ -4299,10 +4342,12 @@
name, uid);
}
+ @GuardedBy("this")
public void noteSyncStartLocked(String name, int uid) {
noteSyncStartLocked(name, uid, mClock.elapsedRealtime(), mClock.uptimeMillis());
}
+ @GuardedBy("this")
public void noteSyncStartLocked(String name, int uid, long elapsedRealtimeMs, long uptimeMs) {
uid = mapUid(uid);
getUidStatsLocked(uid, elapsedRealtimeMs, uptimeMs)
@@ -4313,10 +4358,12 @@
addHistoryEventLocked(elapsedRealtimeMs, uptimeMs, HistoryItem.EVENT_SYNC_START, name, uid);
}
+ @GuardedBy("this")
public void noteSyncFinishLocked(String name, int uid) {
noteSyncFinishLocked(name, uid, mClock.elapsedRealtime(), mClock.uptimeMillis());
}
+ @GuardedBy("this")
public void noteSyncFinishLocked(String name, int uid, long elapsedRealtimeMs, long uptimeMs) {
uid = mapUid(uid);
getUidStatsLocked(uid, elapsedRealtimeMs, uptimeMs)
@@ -4328,10 +4375,12 @@
name, uid);
}
+ @GuardedBy("this")
public void noteJobStartLocked(String name, int uid) {
noteJobStartLocked(name, uid, mClock.elapsedRealtime(), mClock.uptimeMillis());
}
+ @GuardedBy("this")
public void noteJobStartLocked(String name, int uid, long elapsedRealtimeMs, long uptimeMs) {
uid = mapUid(uid);
getUidStatsLocked(uid, elapsedRealtimeMs, uptimeMs)
@@ -4342,11 +4391,13 @@
addHistoryEventLocked(elapsedRealtimeMs, uptimeMs, HistoryItem.EVENT_JOB_START, name, uid);
}
+ @GuardedBy("this")
public void noteJobFinishLocked(String name, int uid, int stopReason) {
noteJobFinishLocked(name, uid, stopReason,
mClock.elapsedRealtime(), mClock.uptimeMillis());
}
+ @GuardedBy("this")
public void noteJobFinishLocked(String name, int uid, int stopReason,
long elapsedRealtimeMs, long uptimeMs) {
uid = mapUid(uid);
@@ -4358,11 +4409,13 @@
addHistoryEventLocked(elapsedRealtimeMs, uptimeMs, HistoryItem.EVENT_JOB_FINISH, name, uid);
}
+ @GuardedBy("this")
public void noteJobsDeferredLocked(int uid, int numDeferred, long sinceLast) {
noteJobsDeferredLocked(uid, numDeferred, sinceLast,
mClock.elapsedRealtime(), mClock.uptimeMillis());
}
+ @GuardedBy("this")
public void noteJobsDeferredLocked(int uid, int numDeferred, long sinceLast,
long elapsedRealtimeMs, long uptimeMs) {
uid = mapUid(uid);
@@ -4370,34 +4423,33 @@
.noteJobsDeferredLocked(numDeferred, sinceLast);
}
+ @GuardedBy("this")
public void noteAlarmStartLocked(String name, WorkSource workSource, int uid) {
noteAlarmStartLocked(name, workSource, uid,
mClock.elapsedRealtime(), mClock.uptimeMillis());
}
+ @GuardedBy("this")
public void noteAlarmStartLocked(String name, WorkSource workSource, int uid,
long elapsedRealtimeMs, long uptimeMs) {
noteAlarmStartOrFinishLocked(HistoryItem.EVENT_ALARM_START, name, workSource, uid,
elapsedRealtimeMs, uptimeMs);
}
+ @GuardedBy("this")
public void noteAlarmFinishLocked(String name, WorkSource workSource, int uid) {
noteAlarmFinishLocked(name, workSource, uid,
mClock.elapsedRealtime(), mClock.uptimeMillis());
}
+ @GuardedBy("this")
public void noteAlarmFinishLocked(String name, WorkSource workSource, int uid,
long elapsedRealtimeMs, long uptimeMs) {
noteAlarmStartOrFinishLocked(HistoryItem.EVENT_ALARM_FINISH, name, workSource, uid,
elapsedRealtimeMs, uptimeMs);
}
- private void noteAlarmStartOrFinishLocked(int historyItem, String name, WorkSource workSource,
- int uid) {
- noteAlarmStartOrFinishLocked(historyItem, name, workSource, uid,
- mClock.elapsedRealtime(), mClock.uptimeMillis());
- }
-
+ @GuardedBy("this")
private void noteAlarmStartOrFinishLocked(int historyItem, String name, WorkSource workSource,
int uid, long elapsedRealtimeMs, long uptimeMs) {
if (!mRecordAllHistory) {
@@ -4430,12 +4482,14 @@
}
}
+ @GuardedBy("this")
public void noteWakupAlarmLocked(String packageName, int uid, WorkSource workSource,
String tag) {
noteWakupAlarmLocked(packageName, uid, workSource, tag,
mClock.elapsedRealtime(), mClock.uptimeMillis());
}
+ @GuardedBy("this")
public void noteWakupAlarmLocked(String packageName, int uid, WorkSource workSource,
String tag, long elapsedRealtimeMs, long uptimeMs) {
if (workSource != null) {
@@ -4481,6 +4535,7 @@
mExternalSync.scheduleCpuSyncDueToWakelockChange(0 /* delayMillis */);
}
+ @GuardedBy("this")
public void setRecordAllHistoryLocked(boolean enabled) {
mRecordAllHistory = enabled;
if (!enabled) {
@@ -4524,6 +4579,7 @@
mNoAutoReset = enabled;
}
+ @GuardedBy("this")
public void setPretendScreenOff(boolean pretendScreenOff) {
if (mPretendScreenOff != pretendScreenOff) {
mPretendScreenOff = pretendScreenOff;
@@ -4537,12 +4593,14 @@
private String mInitialAcquireWakeName;
private int mInitialAcquireWakeUid = -1;
+ @GuardedBy("this")
public void noteStartWakeLocked(int uid, int pid, WorkChain wc, String name, String historyName,
int type, boolean unimportantForLogging) {
noteStartWakeLocked(uid, pid, wc, name, historyName, type, unimportantForLogging,
mClock.elapsedRealtime(), mClock.uptimeMillis());
}
+ @GuardedBy("this")
public void noteStartWakeLocked(int uid, int pid, WorkChain wc, String name, String historyName,
int type, boolean unimportantForLogging, long elapsedRealtimeMs, long uptimeMs) {
final int mappedUid = mapUid(uid);
@@ -4613,12 +4671,14 @@
}
}
+ @GuardedBy("this")
public void noteStopWakeLocked(int uid, int pid, WorkChain wc, String name, String historyName,
int type) {
noteStopWakeLocked(uid, pid, wc, name, historyName, type,
mClock.elapsedRealtime(), mClock.uptimeMillis());
}
+ @GuardedBy("this")
public void noteStopWakeLocked(int uid, int pid, WorkChain wc, String name, String historyName,
int type, long elapsedRealtimeMs, long uptimeMs) {
final int mappedUid = mapUid(uid);
@@ -4701,12 +4761,14 @@
}
}
+ @GuardedBy("this")
public void noteStartWakeFromSourceLocked(WorkSource ws, int pid, String name,
String historyName, int type, boolean unimportantForLogging) {
noteStartWakeFromSourceLocked(ws, pid, name, historyName, type, unimportantForLogging,
mClock.elapsedRealtime(), mClock.uptimeMillis());
}
+ @GuardedBy("this")
public void noteStartWakeFromSourceLocked(WorkSource ws, int pid, String name,
String historyName, int type, boolean unimportantForLogging,
long elapsedRealtimeMs, long uptimeMs) {
@@ -4726,6 +4788,7 @@
}
}
+ @GuardedBy("this")
public void noteChangeWakelockFromSourceLocked(WorkSource ws, int pid, String name,
String historyName, int type, WorkSource newWs, int newPid, String newName,
String newHistoryName, int newType, boolean newUnimportantForLogging) {
@@ -4734,6 +4797,7 @@
mClock.elapsedRealtime(), mClock.uptimeMillis());
}
+ @GuardedBy("this")
public void noteChangeWakelockFromSourceLocked(WorkSource ws, int pid, String name,
String historyName, int type, WorkSource newWs, int newPid, String newName,
String newHistoryName, int newType, boolean newUnimportantForLogging,
@@ -4780,12 +4844,14 @@
}
}
+ @GuardedBy("this")
public void noteStopWakeFromSourceLocked(WorkSource ws, int pid, String name,
String historyName, int type) {
noteStopWakeFromSourceLocked(ws, pid, name, historyName, type,
mClock.elapsedRealtime(), mClock.uptimeMillis());
}
+ @GuardedBy("this")
public void noteStopWakeFromSourceLocked(WorkSource ws, int pid, String name,
String historyName, int type, long elapsedRealtimeMs, long uptimeMs) {
final int N = ws.size();
@@ -4804,23 +4870,27 @@
}
}
+ @GuardedBy("this")
public void noteLongPartialWakelockStart(String name, String historyName, int uid) {
noteLongPartialWakelockStart(name, historyName, uid,
mClock.elapsedRealtime(), mClock.uptimeMillis());
}
+ @GuardedBy("this")
public void noteLongPartialWakelockStart(String name, String historyName, int uid,
long elapsedRealtimeMs, long uptimeMs) {
uid = mapUid(uid);
noteLongPartialWakeLockStartInternal(name, historyName, uid, elapsedRealtimeMs, uptimeMs);
}
+ @GuardedBy("this")
public void noteLongPartialWakelockStartFromSource(String name, String historyName,
WorkSource workSource) {
noteLongPartialWakelockStartFromSource(name, historyName, workSource,
mClock.elapsedRealtime(), mClock.uptimeMillis());
}
+ @GuardedBy("this")
public void noteLongPartialWakelockStartFromSource(String name, String historyName,
WorkSource workSource, long elapsedRealtimeMs, long uptimeMs) {
final int N = workSource.size();
@@ -4841,6 +4911,7 @@
}
}
+ @GuardedBy("this")
private void noteLongPartialWakeLockStartInternal(String name, String historyName, int uid,
long elapsedRealtimeMs, long uptimeMs) {
if (historyName == null) {
@@ -4854,23 +4925,27 @@
historyName, uid);
}
+ @GuardedBy("this")
public void noteLongPartialWakelockFinish(String name, String historyName, int uid) {
noteLongPartialWakelockFinish(name, historyName, uid,
mClock.elapsedRealtime(), mClock.uptimeMillis());
}
+ @GuardedBy("this")
public void noteLongPartialWakelockFinish(String name, String historyName, int uid,
long elapsedRealtimeMs, long uptimeMs) {
uid = mapUid(uid);
noteLongPartialWakeLockFinishInternal(name, historyName, uid, elapsedRealtimeMs, uptimeMs);
}
+ @GuardedBy("this")
public void noteLongPartialWakelockFinishFromSource(String name, String historyName,
WorkSource workSource) {
noteLongPartialWakelockFinishFromSource(name, historyName, workSource,
mClock.elapsedRealtime(), mClock.uptimeMillis());
}
+ @GuardedBy("this")
public void noteLongPartialWakelockFinishFromSource(String name, String historyName,
WorkSource workSource, long elapsedRealtimeMs, long uptimeMs) {
final int N = workSource.size();
@@ -4891,6 +4966,7 @@
}
}
+ @GuardedBy("this")
private void noteLongPartialWakeLockFinishInternal(String name, String historyName, int uid,
long elapsedRealtimeMs, long uptimeMs) {
if (historyName == null) {
@@ -4904,6 +4980,7 @@
historyName, uid);
}
+ @GuardedBy("this")
void aggregateLastWakeupUptimeLocked(long elapsedRealtimeMs, long uptimeMs) {
if (mLastWakeupReason != null) {
long deltaUptimeMs = uptimeMs - mLastWakeupUptimeMs;
@@ -4915,10 +4992,12 @@
}
}
+ @GuardedBy("this")
public void noteWakeupReasonLocked(String reason) {
noteWakeupReasonLocked(reason, mClock.elapsedRealtime(), mClock.uptimeMillis());
}
+ @GuardedBy("this")
public void noteWakeupReasonLocked(String reason, long elapsedRealtimeMs, long uptimeMs) {
if (DEBUG_HISTORY) Slog.v(TAG, "Wakeup reason \"" + reason +"\": "
+ Integer.toHexString(mHistoryCur.states));
@@ -4931,11 +5010,13 @@
addHistoryRecordLocked(elapsedRealtimeMs, uptimeMs);
}
+ @GuardedBy("this")
public boolean startAddingCpuLocked() {
mExternalSync.cancelCpuSyncDueToWakelockChange();
return mOnBatteryInternal;
}
+ @GuardedBy("this")
public void finishAddingCpuLocked(int totalUTimeMs, int totalSTimeMs, int statUserTimeMs,
int statSystemTimeMs, int statIOWaitTimeMs, int statIrqTimeMs,
int statSoftIrqTimeMs, int statIdleTimeMs) {
@@ -4985,10 +5066,12 @@
int mSensorNesting;
+ @GuardedBy("this")
public void noteStartSensorLocked(int uid, int sensor) {
noteStartSensorLocked(uid, sensor, mClock.elapsedRealtime(), mClock.uptimeMillis());
}
+ @GuardedBy("this")
public void noteStartSensorLocked(int uid, int sensor, long elapsedRealtimeMs, long uptimeMs) {
uid = mapUid(uid);
if (mSensorNesting == 0) {
@@ -5002,10 +5085,12 @@
.noteStartSensor(sensor, elapsedRealtimeMs);
}
+ @GuardedBy("this")
public void noteStopSensorLocked(int uid, int sensor) {
noteStopSensorLocked(uid, sensor, mClock.elapsedRealtime(), mClock.uptimeMillis());
}
+ @GuardedBy("this")
public void noteStopSensorLocked(int uid, int sensor, long elapsedRealtimeMs, long uptimeMs) {
uid = mapUid(uid);
mSensorNesting--;
@@ -5021,10 +5106,12 @@
int mGpsNesting;
+ @GuardedBy("this")
public void noteGpsChangedLocked(WorkSource oldWs, WorkSource newWs) {
noteGpsChangedLocked(oldWs, newWs, mClock.elapsedRealtime(), mClock.uptimeMillis());
}
+ @GuardedBy("this")
public void noteGpsChangedLocked(WorkSource oldWs, WorkSource newWs,
long elapsedRealtimeMs, long uptimeMs) {
for (int i = 0; i < newWs.size(); ++i) {
@@ -5053,6 +5140,7 @@
}
}
+ @GuardedBy("this")
private void noteStartGpsLocked(int uid, WorkChain workChain,
long elapsedRealtimeMs, long uptimeMs) {
uid = getAttributionUid(uid, workChain);
@@ -5076,6 +5164,7 @@
getUidStatsLocked(uid, elapsedRealtimeMs, uptimeMs).noteStartGps(elapsedRealtimeMs);
}
+ @GuardedBy("this")
private void noteStopGpsLocked(int uid, WorkChain workChain,
long elapsedRealtimeMs, long uptimeMs) {
uid = getAttributionUid(uid, workChain);
@@ -5100,10 +5189,12 @@
getUidStatsLocked(uid, elapsedRealtimeMs, uptimeMs).noteStopGps(elapsedRealtimeMs);
}
+ @GuardedBy("this")
public void noteGpsSignalQualityLocked(int signalLevel) {
noteGpsSignalQualityLocked(signalLevel, mClock.elapsedRealtime(), mClock.uptimeMillis());
}
+ @GuardedBy("this")
public void noteGpsSignalQualityLocked(int signalLevel, long elapsedRealtimeMs, long uptimeMs) {
if (mGpsNesting == 0) {
return;
@@ -5372,6 +5463,7 @@
}
@UnsupportedAppUsage
+ @GuardedBy("this")
public void noteScreenBrightnessLocked(int brightness) {
noteScreenBrightnessLocked(0, brightness);
}
@@ -5379,6 +5471,7 @@
/**
* Note screen brightness change for a display.
*/
+ @GuardedBy("this")
public void noteScreenBrightnessLocked(int display, int brightness) {
noteScreenBrightnessLocked(display, brightness, mClock.elapsedRealtime(),
mClock.uptimeMillis());
@@ -5388,6 +5481,7 @@
/**
* Note screen brightness change for a display.
*/
+ @GuardedBy("this")
public void noteScreenBrightnessLocked(int display, int brightness, long elapsedRealtimeMs,
long uptimeMs) {
// Bin the brightness.
@@ -5425,6 +5519,7 @@
maybeUpdateOverallScreenBrightness(overallBin, elapsedRealtimeMs, uptimeMs);
}
+ @GuardedBy("this")
private int evaluateOverallScreenBrightnessBinLocked() {
int overallBin = -1;
final int numDisplays = getDisplayCount();
@@ -5442,6 +5537,7 @@
return overallBin;
}
+ @GuardedBy("this")
private void maybeUpdateOverallScreenBrightness(int overallBin, long elapsedRealtimeMs,
long uptimeMs) {
if (mScreenBrightnessBin != overallBin) {
@@ -5469,10 +5565,12 @@
}
@UnsupportedAppUsage
+ @GuardedBy("this")
public void noteUserActivityLocked(int uid, int event) {
noteUserActivityLocked(uid, event, mClock.elapsedRealtime(), mClock.uptimeMillis());
}
+ @GuardedBy("this")
public void noteUserActivityLocked(int uid, int event, long elapsedRealtimeMs, long uptimeMs) {
if (mOnBatteryInternal) {
uid = mapUid(uid);
@@ -5480,20 +5578,24 @@
}
}
+ @GuardedBy("this")
public void noteWakeUpLocked(String reason, int reasonUid) {
noteWakeUpLocked(reason, reasonUid, mClock.elapsedRealtime(), mClock.uptimeMillis());
}
+ @GuardedBy("this")
public void noteWakeUpLocked(String reason, int reasonUid,
long elapsedRealtimeMs, long uptimeMs) {
addHistoryEventLocked(elapsedRealtimeMs, uptimeMs, HistoryItem.EVENT_SCREEN_WAKE_UP,
reason, reasonUid);
}
+ @GuardedBy("this")
public void noteInteractiveLocked(boolean interactive) {
noteInteractiveLocked(interactive, mClock.elapsedRealtime());
}
+ @GuardedBy("this")
public void noteInteractiveLocked(boolean interactive, long elapsedRealtimeMs) {
if (mInteractive != interactive) {
mInteractive = interactive;
@@ -5506,11 +5608,13 @@
}
}
+ @GuardedBy("this")
public void noteConnectivityChangedLocked(int type, String extra) {
noteConnectivityChangedLocked(type, extra,
mClock.elapsedRealtime(), mClock.uptimeMillis());
}
+ @GuardedBy("this")
public void noteConnectivityChangedLocked(int type, String extra,
long elapsedRealtimeMs, long uptimeMs) {
addHistoryEventLocked(elapsedRealtimeMs, uptimeMs, HistoryItem.EVENT_CONNECTIVITY_CHANGED,
@@ -5518,6 +5622,7 @@
mNumConnectivityChange++;
}
+ @GuardedBy("this")
private void noteMobileRadioApWakeupLocked(final long elapsedRealtimeMillis,
final long uptimeMillis, int uid) {
uid = mapUid(uid);
@@ -5529,11 +5634,13 @@
/**
* Updates the radio power state and returns true if an external stats collection should occur.
*/
+ @GuardedBy("this")
public boolean noteMobileRadioPowerStateLocked(int powerState, long timestampNs, int uid) {
return noteMobileRadioPowerStateLocked(powerState, timestampNs, uid,
mClock.elapsedRealtime(), mClock.uptimeMillis());
}
+ @GuardedBy("this")
public boolean noteMobileRadioPowerStateLocked(int powerState, long timestampNs, int uid,
long elapsedRealtimeMs, long uptimeMs) {
if (mMobileRadioPowerState != powerState) {
@@ -5578,6 +5685,7 @@
return false;
}
+ @GuardedBy("this")
public void notePowerSaveModeLocked(boolean enabled) {
notePowerSaveModeLocked(enabled, mClock.elapsedRealtime(), mClock.uptimeMillis());
}
@@ -5585,6 +5693,7 @@
/**
* Toggles the power save mode state.
*/
+ @GuardedBy("this")
public void notePowerSaveModeLockedInit(boolean enabled, long elapsedRealtimeMs,
long uptimeMs) {
if (mPowerSaveModeEnabled != enabled) {
@@ -5599,6 +5708,7 @@
}
}
+ @GuardedBy("this")
public void notePowerSaveModeLocked(boolean enabled, long elapsedRealtimeMs, long uptimeMs) {
if (mPowerSaveModeEnabled != enabled) {
int stepState = enabled ? STEP_LEVEL_MODE_POWER_SAVE : 0;
@@ -5624,11 +5734,13 @@
}
}
+ @GuardedBy("this")
public void noteDeviceIdleModeLocked(final int mode, String activeReason, int activeUid) {
noteDeviceIdleModeLocked(mode, activeReason, activeUid,
mClock.elapsedRealtime(), mClock.uptimeMillis());
}
+ @GuardedBy("this")
public void noteDeviceIdleModeLocked(final int mode, String activeReason, int activeUid,
long elapsedRealtimeMs, long uptimeMs) {
boolean nowIdling = mode == DEVICE_IDLE_MODE_DEEP;
@@ -5702,11 +5814,13 @@
}
}
+ @GuardedBy("this")
public void notePackageInstalledLocked(String pkgName, long versionCode) {
notePackageInstalledLocked(pkgName, versionCode,
mClock.elapsedRealtime(), mClock.uptimeMillis());
}
+ @GuardedBy("this")
public void notePackageInstalledLocked(String pkgName, long versionCode,
long elapsedRealtimeMs, long uptimeMs) {
// XXX need to figure out what to do with long version codes.
@@ -5719,10 +5833,12 @@
addPackageChange(pc);
}
+ @GuardedBy("this")
public void notePackageUninstalledLocked(String pkgName) {
notePackageUninstalledLocked(pkgName, mClock.elapsedRealtime(), mClock.uptimeMillis());
}
+ @GuardedBy("this")
public void notePackageUninstalledLocked(String pkgName,
long elapsedRealtimeMs, long uptimeMs) {
addHistoryEventLocked(elapsedRealtimeMs, uptimeMs,
@@ -5740,10 +5856,12 @@
mDailyPackageChanges.add(pc);
}
+ @GuardedBy("this")
void stopAllGpsSignalQualityTimersLocked(int except) {
stopAllGpsSignalQualityTimersLocked(except, mClock.elapsedRealtime());
}
+ @GuardedBy("this")
void stopAllGpsSignalQualityTimersLocked(int except, long elapsedRealtimeMs) {
for (int i = 0; i < mGpsSignalQualityTimer.length; i++) {
if (i == except) {
@@ -5756,10 +5874,12 @@
}
@UnsupportedAppUsage
+ @GuardedBy("this")
public void notePhoneOnLocked() {
notePhoneOnLocked(mClock.elapsedRealtime(), mClock.uptimeMillis());
}
+ @GuardedBy("this")
public void notePhoneOnLocked(long elapsedRealtimeMs, long uptimeMs) {
if (!mPhoneOn) {
mHistoryCur.states2 |= HistoryItem.STATE2_PHONE_IN_CALL_FLAG;
@@ -5772,10 +5892,12 @@
}
@UnsupportedAppUsage
+ @GuardedBy("this")
public void notePhoneOffLocked() {
notePhoneOffLocked(mClock.elapsedRealtime(), mClock.uptimeMillis());
}
+ @GuardedBy("this")
public void notePhoneOffLocked(long elapsedRealtimeMs, long uptimeMs) {
if (mPhoneOn) {
mHistoryCur.states2 &= ~HistoryItem.STATE2_PHONE_IN_CALL_FLAG;
@@ -5787,6 +5909,7 @@
}
}
+ @GuardedBy("this")
private void registerUsbStateReceiver(Context context) {
final IntentFilter usbStateFilter = new IntentFilter();
usbStateFilter.addAction(UsbManager.ACTION_USB_STATE);
@@ -5811,6 +5934,7 @@
}
}
+ @GuardedBy("this")
private void noteUsbConnectionStateLocked(boolean connected, long elapsedRealtimeMs,
long uptimeMs) {
int newState = connected ? USB_DATA_CONNECTED : USB_DATA_DISCONNECTED;
@@ -5825,6 +5949,7 @@
}
}
+ @GuardedBy("this")
void stopAllPhoneSignalStrengthTimersLocked(int except, long elapsedRealtimeMs) {
for (int i = 0; i < CellSignalStrength.getNumSignalStrengthLevels(); i++) {
if (i == except) {
@@ -5849,6 +5974,7 @@
return state;
}
+ @GuardedBy("this")
private void updateAllPhoneStateLocked(int state, int simState, int strengthBin,
long elapsedRealtimeMs, long uptimeMs) {
boolean scanning = false;
@@ -5945,10 +6071,12 @@
* Telephony stack updates the phone state.
* @param state phone state from ServiceState.getState()
*/
+ @GuardedBy("this")
public void notePhoneStateLocked(int state, int simState) {
notePhoneStateLocked(state, simState, mClock.elapsedRealtime(), mClock.uptimeMillis());
}
+ @GuardedBy("this")
public void notePhoneStateLocked(int state, int simState,
long elapsedRealtimeMs, long uptimeMs) {
updateAllPhoneStateLocked(state, simState, mPhoneSignalStrengthBinRaw,
@@ -5956,11 +6084,13 @@
}
@UnsupportedAppUsage
+ @GuardedBy("this")
public void notePhoneSignalStrengthLocked(SignalStrength signalStrength) {
notePhoneSignalStrengthLocked(signalStrength,
mClock.elapsedRealtime(), mClock.uptimeMillis());
}
+ @GuardedBy("this")
public void notePhoneSignalStrengthLocked(SignalStrength signalStrength,
long elapsedRealtimeMs, long uptimeMs) {
// Bin the strength.
@@ -5970,11 +6100,13 @@
}
@UnsupportedAppUsage
+ @GuardedBy("this")
public void notePhoneDataConnectionStateLocked(int dataType, boolean hasData, int serviceType) {
notePhoneDataConnectionStateLocked(dataType, hasData, serviceType,
mClock.elapsedRealtime(), mClock.uptimeMillis());
}
+ @GuardedBy("this")
public void notePhoneDataConnectionStateLocked(int dataType, boolean hasData, int serviceType,
long elapsedRealtimeMs, long uptimeMs) {
// BatteryStats uses 0 to represent no network type.
@@ -6014,10 +6146,12 @@
}
}
+ @GuardedBy("this")
public void noteWifiOnLocked() {
noteWifiOnLocked(mClock.elapsedRealtime(), mClock.uptimeMillis());
}
+ @GuardedBy("this")
public void noteWifiOnLocked(long elapsedRealtimeMs, long uptimeMs) {
if (!mWifiOn) {
mHistoryCur.states2 |= HistoryItem.STATE2_WIFI_ON_FLAG;
@@ -6030,10 +6164,12 @@
}
}
+ @GuardedBy("this")
public void noteWifiOffLocked() {
noteWifiOffLocked(mClock.elapsedRealtime(), mClock.uptimeMillis());
}
+ @GuardedBy("this")
public void noteWifiOffLocked(long elapsedRealtimeMs, long uptimeMs) {
if (mWifiOn) {
mHistoryCur.states2 &= ~HistoryItem.STATE2_WIFI_ON_FLAG;
@@ -6047,10 +6183,12 @@
}
@UnsupportedAppUsage
+ @GuardedBy("this")
public void noteAudioOnLocked(int uid) {
noteAudioOnLocked(uid, mClock.elapsedRealtime(), mClock.uptimeMillis());
}
+ @GuardedBy("this")
public void noteAudioOnLocked(int uid, long elapsedRealtimeMs, long uptimeMs) {
uid = mapUid(uid);
if (mAudioOnNesting == 0) {
@@ -6066,10 +6204,12 @@
}
@UnsupportedAppUsage
+ @GuardedBy("this")
public void noteAudioOffLocked(int uid) {
noteAudioOffLocked(uid, mClock.elapsedRealtime(), mClock.uptimeMillis());
}
+ @GuardedBy("this")
public void noteAudioOffLocked(int uid, long elapsedRealtimeMs, long uptimeMs) {
if (mAudioOnNesting == 0) {
return;
@@ -6087,10 +6227,12 @@
}
@UnsupportedAppUsage
+ @GuardedBy("this")
public void noteVideoOnLocked(int uid) {
noteVideoOnLocked(uid, mClock.elapsedRealtime(), mClock.uptimeMillis());
}
+ @GuardedBy("this")
public void noteVideoOnLocked(int uid, long elapsedRealtimeMs, long uptimeMs) {
uid = mapUid(uid);
if (mVideoOnNesting == 0) {
@@ -6106,10 +6248,12 @@
}
@UnsupportedAppUsage
+ @GuardedBy("this")
public void noteVideoOffLocked(int uid) {
noteVideoOffLocked(uid, mClock.elapsedRealtime(), mClock.uptimeMillis());
}
+ @GuardedBy("this")
public void noteVideoOffLocked(int uid, long elapsedRealtimeMs, long uptimeMs) {
if (mVideoOnNesting == 0) {
return;
@@ -6126,10 +6270,12 @@
.noteVideoTurnedOffLocked(elapsedRealtimeMs);
}
+ @GuardedBy("this")
public void noteResetAudioLocked() {
noteResetAudioLocked(mClock.elapsedRealtime(), mClock.uptimeMillis());
}
+ @GuardedBy("this")
public void noteResetAudioLocked(long elapsedRealtimeMs, long uptimeMs) {
if (mAudioOnNesting > 0) {
mAudioOnNesting = 0;
@@ -6145,10 +6291,12 @@
}
}
+ @GuardedBy("this")
public void noteResetVideoLocked() {
noteResetVideoLocked(mClock.elapsedRealtime(), mClock.uptimeMillis());
}
+ @GuardedBy("this")
public void noteResetVideoLocked(long elapsedRealtimeMs, long uptimeMs) {
if (mVideoOnNesting > 0) {
mVideoOnNesting = 0;
@@ -6164,31 +6312,37 @@
}
}
+ @GuardedBy("this")
public void noteActivityResumedLocked(int uid) {
noteActivityResumedLocked(uid, mClock.elapsedRealtime(), mClock.uptimeMillis());
}
+ @GuardedBy("this")
public void noteActivityResumedLocked(int uid, long elapsedRealtimeMs, long uptimeMs) {
uid = mapUid(uid);
getUidStatsLocked(uid, elapsedRealtimeMs, uptimeMs)
.noteActivityResumedLocked(elapsedRealtimeMs);
}
+ @GuardedBy("this")
public void noteActivityPausedLocked(int uid) {
noteActivityPausedLocked(uid, mClock.elapsedRealtime(), mClock.uptimeMillis());
}
+ @GuardedBy("this")
public void noteActivityPausedLocked(int uid, long elapsedRealtimeMs, long uptimeMs) {
uid = mapUid(uid);
getUidStatsLocked(uid, elapsedRealtimeMs, uptimeMs)
.noteActivityPausedLocked(elapsedRealtimeMs);
}
+ @GuardedBy("this")
public void noteVibratorOnLocked(int uid, long durationMillis) {
noteVibratorOnLocked(uid, durationMillis,
mClock.elapsedRealtime(), mClock.uptimeMillis());
}
+ @GuardedBy("this")
public void noteVibratorOnLocked(int uid, long durationMillis,
long elapsedRealtimeMs, long uptimeMs) {
uid = mapUid(uid);
@@ -6196,20 +6350,24 @@
.noteVibratorOnLocked(durationMillis, elapsedRealtimeMs);
}
+ @GuardedBy("this")
public void noteVibratorOffLocked(int uid) {
noteVibratorOffLocked(uid, mClock.elapsedRealtime(), mClock.uptimeMillis());
}
+ @GuardedBy("this")
public void noteVibratorOffLocked(int uid, long elapsedRealtimeMs, long uptimeMs) {
uid = mapUid(uid);
getUidStatsLocked(uid, elapsedRealtimeMs, uptimeMs)
.noteVibratorOffLocked(elapsedRealtimeMs);
}
+ @GuardedBy("this")
public void noteFlashlightOnLocked(int uid) {
noteFlashlightOnLocked(uid, mClock.elapsedRealtime(), mClock.uptimeMillis());
}
+ @GuardedBy("this")
public void noteFlashlightOnLocked(int uid, long elapsedRealtimeMs, long uptimeMs) {
uid = mapUid(uid);
if (mFlashlightOnNesting++ == 0) {
@@ -6223,10 +6381,12 @@
.noteFlashlightTurnedOnLocked(elapsedRealtimeMs);
}
+ @GuardedBy("this")
public void noteFlashlightOffLocked(int uid) {
noteFlashlightOffLocked(uid, mClock.elapsedRealtime(), mClock.uptimeMillis());
}
+ @GuardedBy("this")
public void noteFlashlightOffLocked(int uid, long elapsedRealtimeMs, long uptimeMs) {
if (mFlashlightOnNesting == 0) {
return;
@@ -6243,10 +6403,12 @@
.noteFlashlightTurnedOffLocked(elapsedRealtimeMs);
}
+ @GuardedBy("this")
public void noteCameraOnLocked(int uid) {
noteCameraOnLocked(uid, mClock.elapsedRealtime(), mClock.uptimeMillis());
}
+ @GuardedBy("this")
public void noteCameraOnLocked(int uid, long elapsedRealtimeMs, long uptimeMs) {
uid = mapUid(uid);
if (mCameraOnNesting++ == 0) {
@@ -6260,10 +6422,12 @@
.noteCameraTurnedOnLocked(elapsedRealtimeMs);
}
+ @GuardedBy("this")
public void noteCameraOffLocked(int uid) {
noteCameraOffLocked(uid, mClock.elapsedRealtime(), mClock.uptimeMillis());
}
+ @GuardedBy("this")
public void noteCameraOffLocked(int uid, long elapsedRealtimeMs, long uptimeMs) {
if (mCameraOnNesting == 0) {
return;
@@ -6280,10 +6444,12 @@
.noteCameraTurnedOffLocked(elapsedRealtimeMs);
}
+ @GuardedBy("this")
public void noteResetCameraLocked() {
noteResetCameraLocked(mClock.elapsedRealtime(), mClock.uptimeMillis());
}
+ @GuardedBy("this")
public void noteResetCameraLocked(long elapsedRealtimeMs, long uptimeMs) {
if (mCameraOnNesting > 0) {
mCameraOnNesting = 0;
@@ -6299,10 +6465,12 @@
}
}
+ @GuardedBy("this")
public void noteResetFlashlightLocked() {
noteResetFlashlightLocked(mClock.elapsedRealtime(), mClock.uptimeMillis());
}
+ @GuardedBy("this")
public void noteResetFlashlightLocked(long elapsedRealtimeMs, long uptimeMs) {
if (mFlashlightOnNesting > 0) {
mFlashlightOnNesting = 0;
@@ -6318,6 +6486,7 @@
}
}
+ @GuardedBy("this")
private void noteBluetoothScanStartedLocked(WorkChain workChain, int uid,
boolean isUnoptimized, long elapsedRealtimeMs, long uptimeMs) {
uid = getAttributionUid(uid, workChain);
@@ -6333,11 +6502,13 @@
.noteBluetoothScanStartedLocked(elapsedRealtimeMs, isUnoptimized);
}
+ @GuardedBy("this")
public void noteBluetoothScanStartedFromSourceLocked(WorkSource ws, boolean isUnoptimized) {
noteBluetoothScanStartedFromSourceLocked(ws, isUnoptimized,
mClock.elapsedRealtime(), mClock.uptimeMillis());
}
+ @GuardedBy("this")
public void noteBluetoothScanStartedFromSourceLocked(WorkSource ws, boolean isUnoptimized,
long elapsedRealtimeMs, long uptimeMs) {
final int N = ws.size();
@@ -6355,6 +6526,7 @@
}
}
+ @GuardedBy("this")
private void noteBluetoothScanStoppedLocked(WorkChain workChain, int uid,
boolean isUnoptimized, long elapsedRealtimeMs, long uptimeMs) {
uid = getAttributionUid(uid, workChain);
@@ -6378,11 +6550,13 @@
return mapUid(uid);
}
+ @GuardedBy("this")
public void noteBluetoothScanStoppedFromSourceLocked(WorkSource ws, boolean isUnoptimized) {
noteBluetoothScanStoppedFromSourceLocked(ws, isUnoptimized,
mClock.elapsedRealtime(), mClock.uptimeMillis());
}
+ @GuardedBy("this")
public void noteBluetoothScanStoppedFromSourceLocked(WorkSource ws, boolean isUnoptimized,
long elapsedRealtimeMs, long uptimeMs) {
final int N = ws.size();
@@ -6400,10 +6574,12 @@
}
}
+ @GuardedBy("this")
public void noteResetBluetoothScanLocked() {
noteResetBluetoothScanLocked(mClock.elapsedRealtime(), mClock.uptimeMillis());
}
+ @GuardedBy("this")
public void noteResetBluetoothScanLocked(long elapsedRealtimeMs, long uptimeMs) {
if (mBluetoothScanNesting > 0) {
mBluetoothScanNesting = 0;
@@ -6419,11 +6595,13 @@
}
}
+ @GuardedBy("this")
public void noteBluetoothScanResultsFromSourceLocked(WorkSource ws, int numNewResults) {
noteBluetoothScanResultsFromSourceLocked(ws, numNewResults,
mClock.elapsedRealtime(), mClock.uptimeMillis());
}
+ @GuardedBy("this")
public void noteBluetoothScanResultsFromSourceLocked(WorkSource ws, int numNewResults,
long elapsedRealtimeMs, long uptimeMs) {
final int N = ws.size();
@@ -6444,6 +6622,7 @@
}
}
+ @GuardedBy("this")
private void noteWifiRadioApWakeupLocked(final long elapsedRealtimeMillis,
final long uptimeMillis, int uid) {
uid = mapUid(uid);
@@ -6452,11 +6631,13 @@
getUidStatsLocked(uid, elapsedRealtimeMillis, uptimeMillis).noteWifiRadioApWakeupLocked();
}
+ @GuardedBy("this")
public void noteWifiRadioPowerState(int powerState, long timestampNs, int uid) {
noteWifiRadioPowerState(powerState, timestampNs, uid,
mClock.elapsedRealtime(), mClock.uptimeMillis());
}
+ @GuardedBy("this")
public void noteWifiRadioPowerState(int powerState, long timestampNs, int uid,
long elapsedRealtimeMs, long uptimeMs) {
if (mWifiRadioPowerState != powerState) {
@@ -6480,10 +6661,12 @@
}
}
+ @GuardedBy("this")
public void noteWifiRunningLocked(WorkSource ws) {
noteWifiRunningLocked(ws, mClock.elapsedRealtime(), mClock.uptimeMillis());
}
+ @GuardedBy("this")
public void noteWifiRunningLocked(WorkSource ws, long elapsedRealtimeMs, long uptimeMs) {
if (!mGlobalWifiRunning) {
mHistoryCur.states2 |= HistoryItem.STATE2_WIFI_RUNNING_FLAG;
@@ -6514,11 +6697,13 @@
}
}
+ @GuardedBy("this")
public void noteWifiRunningChangedLocked(WorkSource oldWs, WorkSource newWs) {
noteWifiRunningChangedLocked(oldWs, newWs,
mClock.elapsedRealtime(), mClock.uptimeMillis());
}
+ @GuardedBy("this")
public void noteWifiRunningChangedLocked(WorkSource oldWs, WorkSource newWs,
long elapsedRealtimeMs, long uptimeMs) {
if (mGlobalWifiRunning) {
@@ -6558,10 +6743,12 @@
}
}
+ @GuardedBy("this")
public void noteWifiStoppedLocked(WorkSource ws) {
noteWifiStoppedLocked(ws, mClock.elapsedRealtime(), mClock.uptimeMillis());
}
+ @GuardedBy("this")
public void noteWifiStoppedLocked(WorkSource ws, long elapsedRealtimeMs, long uptimeMs) {
if (mGlobalWifiRunning) {
mHistoryCur.states2 &= ~HistoryItem.STATE2_WIFI_RUNNING_FLAG;
@@ -6592,10 +6779,12 @@
}
}
+ @GuardedBy("this")
public void noteWifiStateLocked(int wifiState, String accessPoint) {
noteWifiStateLocked(wifiState, accessPoint, mClock.elapsedRealtime());
}
+ @GuardedBy("this")
public void noteWifiStateLocked(int wifiState, String accessPoint, long elapsedRealtimeMs) {
if (DEBUG) Log.i(TAG, "WiFi state -> " + wifiState);
if (mWifiState != wifiState) {
@@ -6608,11 +6797,13 @@
}
}
+ @GuardedBy("this")
public void noteWifiSupplicantStateChangedLocked(int supplState, boolean failedAuth) {
noteWifiSupplicantStateChangedLocked(supplState, failedAuth,
mClock.elapsedRealtime(), mClock.uptimeMillis());
}
+ @GuardedBy("this")
public void noteWifiSupplicantStateChangedLocked(int supplState, boolean failedAuth,
long elapsedRealtimeMs, long uptimeMs) {
if (DEBUG) Log.i(TAG, "WiFi suppl state -> " + supplState);
@@ -6631,6 +6822,7 @@
}
}
+ @GuardedBy("this")
void stopAllWifiSignalStrengthTimersLocked(int except, long elapsedRealtimeMs) {
for (int i = 0; i < NUM_WIFI_SIGNAL_STRENGTH_BINS; i++) {
if (i == except) {
@@ -6642,10 +6834,12 @@
}
}
+ @GuardedBy("this")
public void noteWifiRssiChangedLocked(int newRssi) {
noteWifiRssiChangedLocked(newRssi, mClock.elapsedRealtime(), mClock.uptimeMillis());
}
+ @GuardedBy("this")
public void noteWifiRssiChangedLocked(int newRssi, long elapsedRealtimeMs, long uptimeMs) {
int strengthBin = WifiManager.calculateSignalLevel(newRssi, NUM_WIFI_SIGNAL_STRENGTH_BINS);
if (DEBUG) Log.i(TAG, "WiFi rssi -> " + newRssi + " bin=" + strengthBin);
@@ -6674,10 +6868,12 @@
int mWifiFullLockNesting = 0;
@UnsupportedAppUsage
+ @GuardedBy("this")
public void noteFullWifiLockAcquiredLocked(int uid) {
noteFullWifiLockAcquiredLocked(uid, mClock.elapsedRealtime(), mClock.uptimeMillis());
}
+ @GuardedBy("this")
public void noteFullWifiLockAcquiredLocked(int uid, long elapsedRealtimeMs, long uptimeMs) {
if (mWifiFullLockNesting == 0) {
mHistoryCur.states |= HistoryItem.STATE_WIFI_FULL_LOCK_FLAG;
@@ -6691,10 +6887,12 @@
}
@UnsupportedAppUsage
+ @GuardedBy("this")
public void noteFullWifiLockReleasedLocked(int uid) {
noteFullWifiLockReleasedLocked(uid, mClock.elapsedRealtime(), mClock.uptimeMillis());
}
+ @GuardedBy("this")
public void noteFullWifiLockReleasedLocked(int uid, long elapsedRealtimeMs, long uptimeMs) {
mWifiFullLockNesting--;
if (mWifiFullLockNesting == 0) {
@@ -6709,10 +6907,12 @@
int mWifiScanNesting = 0;
+ @GuardedBy("this")
public void noteWifiScanStartedLocked(int uid) {
noteWifiScanStartedLocked(uid, mClock.elapsedRealtime(), mClock.uptimeMillis());
}
+ @GuardedBy("this")
public void noteWifiScanStartedLocked(int uid, long elapsedRealtimeMs, long uptimeMs) {
if (mWifiScanNesting == 0) {
mHistoryCur.states |= HistoryItem.STATE_WIFI_SCAN_FLAG;
@@ -6725,10 +6925,12 @@
.noteWifiScanStartedLocked(elapsedRealtimeMs);
}
+ @GuardedBy("this")
public void noteWifiScanStoppedLocked(int uid) {
noteWifiScanStoppedLocked(uid, mClock.elapsedRealtime(), mClock.uptimeMillis());
}
+ @GuardedBy("this")
public void noteWifiScanStoppedLocked(int uid, long elapsedRealtimeMs, long uptimeMs) {
mWifiScanNesting--;
if (mWifiScanNesting == 0) {
@@ -6765,11 +6967,13 @@
int mWifiMulticastNesting = 0;
+ @GuardedBy("this")
@UnsupportedAppUsage
public void noteWifiMulticastEnabledLocked(int uid) {
noteWifiMulticastEnabledLocked(uid, mClock.elapsedRealtime(), mClock.uptimeMillis());
}
+ @GuardedBy("this")
public void noteWifiMulticastEnabledLocked(int uid, long elapsedRealtimeMs, long uptimeMs) {
uid = mapUid(uid);
if (mWifiMulticastNesting == 0) {
@@ -6790,10 +6994,12 @@
}
@UnsupportedAppUsage
+ @GuardedBy("this")
public void noteWifiMulticastDisabledLocked(int uid) {
noteWifiMulticastDisabledLocked(uid, mClock.elapsedRealtime(), mClock.uptimeMillis());
}
+ @GuardedBy("this")
public void noteWifiMulticastDisabledLocked(int uid, long elapsedRealtimeMs, long uptimeMs) {
uid = mapUid(uid);
mWifiMulticastNesting--;
@@ -6813,11 +7019,13 @@
.noteWifiMulticastDisabledLocked(elapsedRealtimeMs);
}
+ @GuardedBy("this")
public void noteFullWifiLockAcquiredFromSourceLocked(WorkSource ws) {
noteFullWifiLockAcquiredFromSourceLocked(ws,
mClock.elapsedRealtime(), mClock.uptimeMillis());
}
+ @GuardedBy("this")
public void noteFullWifiLockAcquiredFromSourceLocked(WorkSource ws,
long elapsedRealtimeMs, long uptimeMs) {
int N = ws.size();
@@ -6836,11 +7044,13 @@
}
}
+ @GuardedBy("this")
public void noteFullWifiLockReleasedFromSourceLocked(WorkSource ws) {
noteFullWifiLockReleasedFromSourceLocked(ws,
mClock.elapsedRealtime(), mClock.uptimeMillis());
}
+ @GuardedBy("this")
public void noteFullWifiLockReleasedFromSourceLocked(WorkSource ws,
long elapsedRealtimeMs, long uptimeMs) {
int N = ws.size();
@@ -6859,10 +7069,12 @@
}
}
+ @GuardedBy("this")
public void noteWifiScanStartedFromSourceLocked(WorkSource ws) {
noteWifiScanStartedFromSourceLocked(ws, mClock.elapsedRealtime(), mClock.uptimeMillis());
}
+ @GuardedBy("this")
public void noteWifiScanStartedFromSourceLocked(WorkSource ws,
long elapsedRealtimeMs, long uptimeMs) {
int N = ws.size();
@@ -6881,10 +7093,12 @@
}
}
+ @GuardedBy("this")
public void noteWifiScanStoppedFromSourceLocked(WorkSource ws) {
noteWifiScanStoppedFromSourceLocked(ws, mClock.elapsedRealtime(), mClock.uptimeMillis());
}
+ @GuardedBy("this")
public void noteWifiScanStoppedFromSourceLocked(WorkSource ws,
long elapsedRealtimeMs, long uptimeMs) {
int N = ws.size();
@@ -6903,11 +7117,13 @@
}
}
+ @GuardedBy("this")
public void noteWifiBatchedScanStartedFromSourceLocked(WorkSource ws, int csph) {
noteWifiBatchedScanStartedFromSourceLocked(ws, csph,
mClock.elapsedRealtime(), mClock.uptimeMillis());
}
+ @GuardedBy("this")
public void noteWifiBatchedScanStartedFromSourceLocked(WorkSource ws, int csph,
long elapsedRealtimeMs, long uptimeMs) {
int N = ws.size();
@@ -6924,10 +7140,13 @@
}
}
+ @GuardedBy("this")
public void noteWifiBatchedScanStoppedFromSourceLocked(WorkSource ws) {
noteWifiBatchedScanStoppedFromSourceLocked(ws,
mClock.elapsedRealtime(), mClock.uptimeMillis());
}
+
+ @GuardedBy("this")
public void noteWifiBatchedScanStoppedFromSourceLocked(WorkSource ws,
long elapsedRealtimeMs, long uptimeMs) {
int N = ws.size();
@@ -7454,36 +7673,43 @@
}
}
+ @GuardedBy("this")
@Override
public long getBluetoothMeasuredBatteryConsumptionUC() {
return getPowerBucketConsumptionUC(MeasuredEnergyStats.POWER_BUCKET_BLUETOOTH);
}
+ @GuardedBy("this")
@Override
public long getCpuMeasuredBatteryConsumptionUC() {
return getPowerBucketConsumptionUC(MeasuredEnergyStats.POWER_BUCKET_CPU);
}
+ @GuardedBy("this")
@Override
public long getGnssMeasuredBatteryConsumptionUC() {
return getPowerBucketConsumptionUC(MeasuredEnergyStats.POWER_BUCKET_GNSS);
}
+ @GuardedBy("this")
@Override
public long getMobileRadioMeasuredBatteryConsumptionUC() {
return getPowerBucketConsumptionUC(MeasuredEnergyStats.POWER_BUCKET_MOBILE_RADIO);
}
+ @GuardedBy("this")
@Override
public long getScreenOnMeasuredBatteryConsumptionUC() {
return getPowerBucketConsumptionUC(MeasuredEnergyStats.POWER_BUCKET_SCREEN_ON);
}
+ @GuardedBy("this")
@Override
public long getScreenDozeMeasuredBatteryConsumptionUC() {
return getPowerBucketConsumptionUC(MeasuredEnergyStats.POWER_BUCKET_SCREEN_DOZE);
}
+ @GuardedBy("this")
@Override
public long getWifiMeasuredBatteryConsumptionUC() {
return getPowerBucketConsumptionUC(MeasuredEnergyStats.POWER_BUCKET_WIFI);
@@ -7496,6 +7722,7 @@
* @param bucket standard power bucket of interest
* @return charge (in microcoulombs) used for this power bucket
*/
+ @GuardedBy("this")
private long getPowerBucketConsumptionUC(@StandardPowerBucket int bucket) {
if (mGlobalMeasuredEnergyStats == null) {
return POWER_DATA_UNAVAILABLE;
@@ -7503,6 +7730,7 @@
return mGlobalMeasuredEnergyStats.getAccumulatedStandardBucketCharge(bucket);
}
+ @GuardedBy("this")
@Override
public @Nullable long[] getCustomConsumerMeasuredBatteryConsumptionUC() {
if (mGlobalMeasuredEnergyStats == null) {
@@ -7514,12 +7742,13 @@
/**
* Returns the names of custom power components.
*/
+ @GuardedBy("this")
@Override
public @NonNull String[] getCustomEnergyConsumerNames() {
- if (mGlobalMeasuredEnergyStats == null) {
+ if (mMeasuredEnergyStatsConfig == null) {
return new String[0];
}
- final String[] names = mGlobalMeasuredEnergyStats.getCustomBucketNames();
+ final String[] names = mMeasuredEnergyStatsConfig.getCustomBucketNames();
for (int i = 0; i < names.length; i++) {
if (TextUtils.isEmpty(names[i])) {
names[i] = "CUSTOM_" + BatteryConsumer.FIRST_CUSTOM_POWER_COMPONENT_ID + i;
@@ -7528,6 +7757,7 @@
return names;
}
+ @GuardedBy("this")
@Override public long getStartClockTime() {
final long currentTimeMs = mClock.currentTimeMillis();
if ((currentTimeMs > MILLISECONDS_IN_YEAR
@@ -7954,11 +8184,18 @@
mJobsFreshnessBuckets = new Counter[JOB_FRESHNESS_BUCKETS.length];
}
+ @GuardedBy("mBsi")
@VisibleForTesting
public void setProcessStateForTest(int procState, long elapsedTimeMs) {
mProcessState = procState;
getProcStateTimeCounter().setState(procState, elapsedTimeMs);
getProcStateScreenOffTimeCounter().setState(procState, elapsedTimeMs);
+ final MeasuredEnergyStats energyStats =
+ getOrCreateMeasuredEnergyStatsIfSupportedLocked();
+ if (energyStats != null) {
+ energyStats.setState(mapUidProcessStateToBatteryConsumerProcessState(procState),
+ elapsedTimeMs);
+ }
}
@Override
@@ -7981,6 +8218,7 @@
return nullIfAllZeros(mCpuClusterTimesMs, STATS_SINCE_CHARGED);
}
+ @GuardedBy("mBsi")
@Override
public long[] getCpuFreqTimes(int which, int procState) {
if (procState < 0 || procState >= NUM_PROCESS_STATE) {
@@ -7997,6 +8235,7 @@
return mProcStateTimeMs.getCountsLocked(which, procState);
}
+ @GuardedBy("mBsi")
@Override
public long[] getScreenOffCpuFreqTimes(int which, int procState) {
if (procState < 0 || procState >= NUM_PROCESS_STATE) {
@@ -8026,6 +8265,7 @@
return mProportionalSystemServiceUsage;
}
+ @GuardedBy("mBsi")
public void addIsolatedUid(int isolatedUid) {
if (mChildUids == null) {
mChildUids = new SparseArray<>();
@@ -8312,23 +8552,37 @@
return mModemControllerActivity;
}
+ @GuardedBy("mBsi")
private MeasuredEnergyStats getOrCreateMeasuredEnergyStatsLocked() {
if (mUidMeasuredEnergyStats == null) {
- mUidMeasuredEnergyStats =
- MeasuredEnergyStats.createFromTemplate(mBsi.mGlobalMeasuredEnergyStats);
+ mUidMeasuredEnergyStats = new MeasuredEnergyStats(mBsi.mMeasuredEnergyStatsConfig);
+ }
+ return mUidMeasuredEnergyStats;
+ }
+
+ @GuardedBy("mBsi")
+ private MeasuredEnergyStats getOrCreateMeasuredEnergyStatsIfSupportedLocked() {
+ if (mUidMeasuredEnergyStats == null && mBsi.mMeasuredEnergyStatsConfig != null) {
+ mUidMeasuredEnergyStats = new MeasuredEnergyStats(mBsi.mMeasuredEnergyStatsConfig);
}
return mUidMeasuredEnergyStats;
}
/** Adds the given charge to the given standard power bucket for this uid. */
+ @GuardedBy("mBsi")
private void addChargeToStandardBucketLocked(long chargeDeltaUC,
@StandardPowerBucket int powerBucket) {
- getOrCreateMeasuredEnergyStatsLocked().updateStandardBucket(powerBucket, chargeDeltaUC);
+ final MeasuredEnergyStats measuredEnergyStats =
+ getOrCreateMeasuredEnergyStatsLocked();
+ measuredEnergyStats.updateStandardBucket(powerBucket, chargeDeltaUC,
+ mBsi.mClock.elapsedRealtime());
}
/** Adds the given charge to the given custom power bucket for this uid. */
+ @GuardedBy("mBsi")
private void addChargeToCustomBucketLocked(long chargeDeltaUC, int powerBucket) {
- getOrCreateMeasuredEnergyStatsLocked().updateCustomBucket(powerBucket, chargeDeltaUC);
+ getOrCreateMeasuredEnergyStatsLocked().updateCustomBucket(powerBucket, chargeDeltaUC,
+ mBsi.mClock.elapsedRealtime());
}
/**
@@ -8337,6 +8591,7 @@
* @param bucket standard power bucket of interest
* @return consumption (in microcolombs) used by this uid for this power bucket
*/
+ @GuardedBy("mBsi")
public long getMeasuredBatteryConsumptionUC(@StandardPowerBucket int bucket) {
if (mBsi.mGlobalMeasuredEnergyStats == null
|| !mBsi.mGlobalMeasuredEnergyStats.isStandardBucketSupported(bucket)) {
@@ -8348,6 +8603,24 @@
return mUidMeasuredEnergyStats.getAccumulatedStandardBucketCharge(bucket);
}
+ /**
+ * Returns the battery consumption (in microcoulombs) of this uid for a standard power
+ * bucket and a process state, such as Uid.PROCESS_STATE_TOP.
+ */
+ @GuardedBy("mBsi")
+ public long getMeasuredBatteryConsumptionUC(@StandardPowerBucket int bucket,
+ int processState) {
+ if (mBsi.mGlobalMeasuredEnergyStats == null
+ || !mBsi.mGlobalMeasuredEnergyStats.isStandardBucketSupported(bucket)) {
+ return POWER_DATA_UNAVAILABLE;
+ }
+ if (mUidMeasuredEnergyStats == null) {
+ return 0L; // It is supported, but was never filled, so it must be 0
+ }
+ return mUidMeasuredEnergyStats.getAccumulatedStandardBucketCharge(bucket, processState);
+ }
+
+ @GuardedBy("mBsi")
@Override
public long[] getCustomConsumerMeasuredBatteryConsumptionUC() {
if (mBsi.mGlobalMeasuredEnergyStats == null) {
@@ -8360,31 +8633,44 @@
return mUidMeasuredEnergyStats.getAccumulatedCustomBucketCharges();
}
+ @GuardedBy("mBsi")
@Override
public long getBluetoothMeasuredBatteryConsumptionUC() {
return getMeasuredBatteryConsumptionUC(MeasuredEnergyStats.POWER_BUCKET_BLUETOOTH);
}
+ @GuardedBy("mBsi")
@Override
public long getCpuMeasuredBatteryConsumptionUC() {
return getMeasuredBatteryConsumptionUC(MeasuredEnergyStats.POWER_BUCKET_CPU);
}
+ @GuardedBy("mBsi")
+ @Override
+ public long getCpuMeasuredBatteryConsumptionUC(
+ @BatteryConsumer.ProcessState int processState) {
+ return getMeasuredBatteryConsumptionUC(MeasuredEnergyStats.POWER_BUCKET_CPU,
+ processState);
+ }
+
@Override
public long getGnssMeasuredBatteryConsumptionUC() {
return getMeasuredBatteryConsumptionUC(MeasuredEnergyStats.POWER_BUCKET_GNSS);
}
+ @GuardedBy("mBsi")
@Override
public long getMobileRadioMeasuredBatteryConsumptionUC() {
return getMeasuredBatteryConsumptionUC(MeasuredEnergyStats.POWER_BUCKET_MOBILE_RADIO);
}
+ @GuardedBy("mBsi")
@Override
public long getScreenOnMeasuredBatteryConsumptionUC() {
return getMeasuredBatteryConsumptionUC(MeasuredEnergyStats.POWER_BUCKET_SCREEN_ON);
}
+ @GuardedBy("mBsi")
@Override
public long getWifiMeasuredBatteryConsumptionUC() {
return getMeasuredBatteryConsumptionUC(MeasuredEnergyStats.POWER_BUCKET_WIFI);
@@ -9678,6 +9964,7 @@
}
}
+ @GuardedBy("mBsi")
void readFromParcelLocked(TimeBase timeBase, TimeBase screenOffTimeBase, Parcel in) {
mOnBatteryBackgroundTimeBase.readFromParcel(in);
mOnBatteryScreenOffBackgroundTimeBase.readFromParcel(in);
@@ -9917,7 +10204,8 @@
}
if (in.readInt() != 0) {
- mUidMeasuredEnergyStats = new MeasuredEnergyStats(in);
+ mUidMeasuredEnergyStats = new MeasuredEnergyStats(mBsi.mMeasuredEnergyStatsConfig,
+ in);
}
mUserCpuTime = new LongSamplingCounter(mBsi.mOnBatteryTimeBase, in);
@@ -10801,6 +11089,7 @@
mBsi.mClock.elapsedRealtime(), mBsi.mClock.uptimeMillis());
}
+ @GuardedBy("mBsi")
public void updateUidProcessStateLocked(int procState,
long elapsedRealtimeMs, long uptimeMs) {
int uidRunningState;
@@ -10845,6 +11134,14 @@
updateOnBatteryBgTimeBase(uptimeMs * 1000, elapsedRealtimeMs * 1000);
updateOnBatteryScreenOffBgTimeBase(uptimeMs * 1000, elapsedRealtimeMs * 1000);
+
+ final MeasuredEnergyStats energyStats =
+ getOrCreateMeasuredEnergyStatsIfSupportedLocked();
+ if (energyStats != null) {
+ energyStats.setState(
+ mapUidProcessStateToBatteryConsumerProcessState(mProcessState),
+ elapsedRealtimeMs);
+ }
}
if (userAwareService != mInForegroundService) {
@@ -11485,6 +11782,7 @@
}
}
+ @GuardedBy("this")
public void readDailyStatsLocked() {
Slog.d(TAG, "Reading daily items from " + mDailyFile.getBaseFile());
mDailyItems.clear();
@@ -11659,6 +11957,7 @@
return mNextMaxDailyDeadlineMs;
}
+ @GuardedBy("this")
public int getHistoryTotalSize() {
return mConstants.MAX_HISTORY_BUFFER * mConstants.MAX_HISTORY_FILES;
}
@@ -11779,6 +12078,7 @@
mBatteryResetListener = batteryResetListener;
}
+ @GuardedBy("this")
public void resetAllStatsCmdLocked() {
final long mSecUptime = mClock.uptimeMillis();
long uptimeUs = mSecUptime * 1000;
@@ -11813,6 +12113,7 @@
initActiveHistoryEventsLocked(mSecRealtime, mSecUptime);
}
+ @GuardedBy("this")
private void resetAllStatsLocked(long uptimeMillis, long elapsedRealtimeMillis,
int resetReason) {
if (mBatteryResetListener != null) {
@@ -11971,6 +12272,7 @@
mHandler.sendEmptyMessage(MSG_REPORT_RESET_STATS);
}
+ @GuardedBy("this")
private void initActiveHistoryEventsLocked(long elapsedRealtimeMs, long uptimeMs) {
for (int i=0; i<HistoryItem.EVENT_COUNT; i++) {
if (!mRecordAllHistory && i == HistoryItem.EVENT_PROC) {
@@ -11991,11 +12293,13 @@
}
}
+ @GuardedBy("this")
void updateDischargeScreenLevelsLocked(int oldState, int newState) {
updateOldDischargeScreenLevelLocked(oldState);
updateNewDischargeScreenLevelLocked(newState);
}
+ @GuardedBy("this")
private void updateOldDischargeScreenLevelLocked(int state) {
if (Display.isOnState(state)) {
int diff = mDischargeScreenOnUnplugLevel - mDischargeCurrentLevel;
@@ -12018,6 +12322,7 @@
}
}
+ @GuardedBy("this")
private void updateNewDischargeScreenLevelLocked(int state) {
if (Display.isOnState(state)) {
mDischargeScreenOnUnplugLevel = mDischargeCurrentLevel;
@@ -12034,6 +12339,7 @@
}
}
+ @GuardedBy("this")
public void pullPendingStateUpdatesLocked() {
if (mOnBatteryInternal) {
updateDischargeScreenLevelsLocked(mScreenState, mScreenState);
@@ -12080,10 +12386,13 @@
* Distribute WiFi energy info and network traffic to apps.
* @param info The energy information from the WiFi controller.
*/
+ @GuardedBy("this")
public void updateWifiState(@Nullable final WifiActivityEnergyInfo info,
final long consumedChargeUC, long elapsedRealtimeMs, long uptimeMs) {
if (DEBUG_ENERGY) {
- Slog.d(TAG, "Updating wifi stats: " + Arrays.toString(mWifiIfaces));
+ synchronized (mWifiNetworkLock) {
+ Slog.d(TAG, "Updating wifi stats: " + Arrays.toString(mWifiIfaces));
+ }
}
// Grab a separate lock to acquire the network stats, which may do I/O.
@@ -12714,7 +13023,7 @@
rxTimeMs = info.getControllerRxTimeMillis();
txTimeMs = info.getControllerTxTimeMillis();
energy = info.getControllerEnergyUsed();
- if (info.getUidTraffic() != null) {
+ if (!info.getUidTraffic().isEmpty()) {
for (UidTraffic traffic : info.getUidTraffic()) {
uidRxBytes.put(traffic.getUid(), traffic.getRxBytes());
uidTxBytes.put(traffic.getUid(), traffic.getTxBytes());
@@ -12740,6 +13049,7 @@
*
* @param info The accumulated energy information from the bluetooth controller.
*/
+ @GuardedBy("this")
public void updateBluetoothStateLocked(@Nullable final BluetoothActivityEnergyInfo info,
final long consumedChargeUC, long elapsedRealtimeMs, long uptimeMs) {
if (DEBUG_ENERGY) {
@@ -12865,10 +13175,10 @@
long totalTxBytes = 0;
long totalRxBytes = 0;
- final UidTraffic[] uidTraffic = info.getUidTraffic();
- final int numUids = uidTraffic != null ? uidTraffic.length : 0;
+ final List<UidTraffic> uidTraffic = info.getUidTraffic();
+ final int numUids = uidTraffic.size();
for (int i = 0; i < numUids; i++) {
- final UidTraffic traffic = uidTraffic[i];
+ final UidTraffic traffic = uidTraffic.get(i);
final long rxBytes = traffic.getRxBytes() - mLastBluetoothActivityInfo.uidRxBytes.get(
traffic.getUid());
final long txBytes = traffic.getTxBytes() - mLastBluetoothActivityInfo.uidTxBytes.get(
@@ -12891,7 +13201,7 @@
if ((totalTxBytes != 0 || totalRxBytes != 0) && (leftOverRxTimeMs != 0
|| leftOverTxTimeMs != 0)) {
for (int i = 0; i < numUids; i++) {
- final UidTraffic traffic = uidTraffic[i];
+ final UidTraffic traffic = uidTraffic.get(i);
final int uid = traffic.getUid();
final long rxBytes =
traffic.getRxBytes() - mLastBluetoothActivityInfo.uidRxBytes.get(uid);
@@ -13039,6 +13349,7 @@
* clusterChargeUC against.
*/
@GuardedBy("this")
+ @SuppressWarnings("GuardedBy") // errorprone false positive on u.addChargeToStandardBucketLocked
private void updateCpuMeasuredEnergyStatsLocked(@NonNull long[] clusterChargeUC,
@NonNull CpuDeltaPowerAccumulator accumulator) {
if (DEBUG_ENERGY) {
@@ -13057,7 +13368,7 @@
if (totalCpuChargeUC <= 0) return;
mGlobalMeasuredEnergyStats.updateStandardBucket(MeasuredEnergyStats.POWER_BUCKET_CPU,
- totalCpuChargeUC);
+ totalCpuChargeUC, mClock.elapsedRealtime());
// Calculate the measured microcoulombs/calculated milliamp-hour charge ratio for each
// cluster to normalize each uid's estimated power usage against actual power usage for
@@ -13261,6 +13572,8 @@
* Data inside uidCharges will not be modified (treated immutable).
* Uids not already known to BatteryStats will be ignored.
*/
+ @GuardedBy("this")
+ @SuppressWarnings("GuardedBy") // errorprone false positive on u.addChargeToCustomBucketLocked
public void updateCustomMeasuredEnergyStatsLocked(int customPowerBucket,
long totalChargeUC, @Nullable SparseLongArray uidCharges) {
if (DEBUG_ENERGY) {
@@ -13272,7 +13585,8 @@
if (mGlobalMeasuredEnergyStats == null) return;
if (!mOnBatteryInternal || mIgnoreNextExternalStats || totalChargeUC <= 0) return;
- mGlobalMeasuredEnergyStats.updateCustomBucket(customPowerBucket, totalChargeUC);
+ mGlobalMeasuredEnergyStats.updateCustomBucket(customPowerBucket, totalChargeUC,
+ mClock.elapsedRealtime());
if (uidCharges == null) return;
final int numUids = uidCharges.size();
@@ -13280,6 +13594,7 @@
final int uidInt = mapUid(uidCharges.keyAt(i));
final long uidChargeUC = uidCharges.valueAt(i);
if (uidChargeUC == 0) continue;
+
final Uid uidObj = getAvailableUidStatsLocked(uidInt);
if (uidObj != null) {
uidObj.addChargeToCustomBucketLocked(uidChargeUC, customPowerBucket);
@@ -13314,6 +13629,8 @@
*
* <p>All uids in ratioNumerators must exist in mUidStats already.
*/
+ @GuardedBy("this")
+ @SuppressWarnings("GuardedBy") // errorprone false positive on u.addChargeToStandardBucketLocked
private void distributeEnergyToUidsLocked(@StandardPowerBucket int bucket,
long totalConsumedChargeUC, SparseDoubleArray ratioNumerators,
double minRatioDenominator) {
@@ -14256,6 +14573,7 @@
}
}
+ @GuardedBy("this")
private void startRecordingHistory(final long elapsedRealtimeMs, final long uptimeMs,
boolean reset) {
mRecordingHistory = true;
@@ -14269,6 +14587,7 @@
}
}
+ @GuardedBy("this")
private void recordCurrentTimeChangeLocked(final long currentTimeMs,
final long elapsedRealtimeMs, final long uptimeMs) {
if (mRecordingHistory) {
@@ -14278,6 +14597,7 @@
}
}
+ @GuardedBy("this")
private void recordShutdownLocked(final long currentTimeMs, final long elapsedRealtimeMs) {
if (mRecordingHistory) {
mHistoryCur.currentTime = currentTimeMs;
@@ -14304,6 +14624,7 @@
mClock.elapsedRealtime(), mClock.uptimeMillis(), mClock.currentTimeMillis());
}
+ @GuardedBy("this")
public void setBatteryStateLocked(final int status, final int health, final int plugType,
final int level, /* not final */ int temp, final int voltageMv, final int chargeUah,
final int chargeFullUah, final long chargeTimeToFullSeconds,
@@ -14987,6 +15308,7 @@
return u;
}
+ @GuardedBy("this")
public void onCleanupUserLocked(int userId, long elapsedRealtimeMs) {
final int firstUidForUser = UserHandle.getUid(userId, 0);
final int lastUidForUser = UserHandle.getUid(userId, UserHandle.PER_USER_RANGE - 1);
@@ -14994,6 +15316,7 @@
new UidToRemove(firstUidForUser, lastUidForUser, elapsedRealtimeMs));
}
+ @GuardedBy("this")
public void onUserRemovedLocked(int userId) {
if (mExternalSync != null) {
// Clear out the removed user's UIDs after a short delay. The delay is needed
@@ -15006,6 +15329,7 @@
/**
* Removes battery stats for UIDs corresponding to a removed user.
*/
+ @GuardedBy("this")
public void clearRemovedUserUidsLocked(int userId) {
final int firstUidForUser = UserHandle.getUid(userId, 0);
final int lastUidForUser = UserHandle.getUid(userId, UserHandle.PER_USER_RANGE - 1);
@@ -15027,6 +15351,7 @@
* Remove the statistics object for a particular uid.
*/
@UnsupportedAppUsage
+ @GuardedBy("this")
public void removeUidStatsLocked(int uid) {
removeUidStatsLocked(uid, mClock.elapsedRealtime());
}
@@ -15034,6 +15359,7 @@
/**
* @see #removeUidStatsLocked(int)
*/
+ @GuardedBy("this")
public void removeUidStatsLocked(int uid, long elapsedRealtimeMs) {
final Uid u = mUidStats.get(uid);
if (u != null) {
@@ -15131,21 +15457,25 @@
return u.getServiceStatsLocked(pkg, name);
}
+ @GuardedBy("this")
public void shutdownLocked() {
recordShutdownLocked(mClock.currentTimeMillis(), mClock.elapsedRealtime());
writeSyncLocked();
mShuttingDown = true;
}
+ @GuardedBy("this")
@Override
public boolean isProcessStateDataAvailable() {
return trackPerProcStateCpuTimes();
}
+ @GuardedBy("this")
public boolean trackPerProcStateCpuTimes() {
return mConstants.TRACK_CPU_TIMES_BY_PROC_STATE && mPerProcStateCpuTimesAvailable;
}
+ @GuardedBy("this")
public void systemServicesReady(Context context) {
mConstants.startObserving(context.getContentResolver());
registerUsbStateReceiver(context);
@@ -15162,28 +15492,28 @@
@GuardedBy("this")
public void initMeasuredEnergyStatsLocked(@Nullable boolean[] supportedStandardBuckets,
String[] customBucketNames) {
- boolean supportedBucketMismatch = false;
-
final int numDisplays = mPerDisplayBatteryStats.length;
for (int i = 0; i < numDisplays; i++) {
final int screenState = mPerDisplayBatteryStats[i].screenState;
mPerDisplayBatteryStats[i].screenStateAtLastEnergyMeasurement = screenState;
}
- if (supportedStandardBuckets == null) {
- if (mGlobalMeasuredEnergyStats != null) {
- // Measured energy no longer supported, wipe out the existing data.
- supportedBucketMismatch = true;
- }
- } else {
- if (mGlobalMeasuredEnergyStats == null) {
- mGlobalMeasuredEnergyStats =
- new MeasuredEnergyStats(supportedStandardBuckets, customBucketNames);
+ final boolean compatibleConfig;
+ if (supportedStandardBuckets != null) {
+ final MeasuredEnergyStats.Config config = new MeasuredEnergyStats.Config(
+ supportedStandardBuckets, customBucketNames,
+ SUPPORTED_PER_PROCESS_STATE_STANDARD_ENERGY_BUCKETS,
+ getBatteryConsumerProcessStateNames());
+
+ if (mMeasuredEnergyStatsConfig == null) {
+ compatibleConfig = true;
} else {
- supportedBucketMismatch = !mGlobalMeasuredEnergyStats.isSupportEqualTo(
- supportedStandardBuckets, customBucketNames);
+ compatibleConfig = mMeasuredEnergyStatsConfig.isCompatible(config);
}
+ mMeasuredEnergyStatsConfig = config;
+ mGlobalMeasuredEnergyStats = new MeasuredEnergyStats(config);
+
if (supportedStandardBuckets[MeasuredEnergyStats.POWER_BUCKET_BLUETOOTH]) {
mBluetoothPowerCalculator = new BluetoothPowerCalculator(mPowerProfile);
}
@@ -15196,11 +15526,14 @@
if (supportedStandardBuckets[MeasuredEnergyStats.POWER_BUCKET_WIFI]) {
mWifiPowerCalculator = new WifiPowerCalculator(mPowerProfile);
}
+ } else {
+ compatibleConfig = (mMeasuredEnergyStatsConfig == null);
+ // Measured energy no longer supported, wipe out the existing data.
+ mMeasuredEnergyStatsConfig = null;
+ mGlobalMeasuredEnergyStats = null;
}
- if (supportedBucketMismatch) {
- mGlobalMeasuredEnergyStats = supportedStandardBuckets == null
- ? null : new MeasuredEnergyStats(supportedStandardBuckets, customBucketNames);
+ if (!compatibleConfig) {
// Supported power buckets changed since last boot.
// Existing data is no longer reliable.
resetAllStatsLocked(SystemClock.uptimeMillis(), SystemClock.elapsedRealtime(),
@@ -15208,6 +15541,16 @@
}
}
+ @NonNull
+ private static String[] getBatteryConsumerProcessStateNames() {
+ String[] procStateNames = new String[BatteryConsumer.PROCESS_STATE_COUNT];
+ for (int procState = 0; procState < BatteryConsumer.PROCESS_STATE_COUNT; procState++) {
+ procStateNames[procState] = BatteryConsumer.processStateToString(procState);
+ }
+ procStateNames[BatteryConsumer.PROCESS_STATE_ANY] = "untracked";
+ return procStateNames;
+ }
+
/** Get the last known Battery voltage (in millivolts), returns -1 if unknown */
@GuardedBy("this")
public int getBatteryVoltageMvLocked() {
@@ -15373,6 +15716,7 @@
}
}
+ @GuardedBy("BatteryStatsImpl.this")
private void updateProcStateCpuTimesReadDelayMs(long oldDelayMillis, long newDelayMillis) {
PROC_STATE_CPU_TIMES_READ_DELAY_MS = newDelayMillis;
if (oldDelayMillis != newDelayMillis) {
@@ -15393,6 +15737,7 @@
}
}
+ @GuardedBy("BatteryStatsImpl.this")
private void updateUidRemoveDelay(long newTimeMs) {
UID_REMOVE_DELAY_MS = newTimeMs;
clearPendingRemovedUidsLocked();
@@ -15530,16 +15875,19 @@
final ReentrantLock mWriteLock = new ReentrantLock();
+ @GuardedBy("this")
public void writeAsyncLocked() {
writeStatsLocked(false);
writeHistoryLocked(false);
}
+ @GuardedBy("this")
public void writeSyncLocked() {
writeStatsLocked(true);
writeHistoryLocked(true);
}
+ @GuardedBy("this")
void writeStatsLocked(boolean sync) {
if (mStatsFile == null) {
Slog.w(TAG,
@@ -15621,6 +15969,7 @@
}
@UnsupportedAppUsage
+ @GuardedBy("this")
public void readLocked() {
if (mDailyFile != null) {
readDailyStatsLocked();
@@ -15705,6 +16054,7 @@
return 0;
}
+ @GuardedBy("this")
void readHistoryBuffer(Parcel in) throws ParcelFormatException {
final int version = in.readInt();
if (version != VERSION) {
@@ -15784,6 +16134,7 @@
out.appendFrom(mHistoryBuffer, 0, mHistoryBuffer.dataSize());
}
+ @GuardedBy("this")
public void readSummaryFromParcel(Parcel in) throws ParcelFormatException {
final int version = in.readInt();
if (version != VERSION) {
@@ -15870,11 +16221,14 @@
mNextMaxDailyDeadlineMs = in.readLong();
mBatteryTimeToFullSeconds = in.readLong();
+ mMeasuredEnergyStatsConfig = MeasuredEnergyStats.Config.createFromParcel(in);
+
/**
* WARNING: Supported buckets may have changed across boots. Bucket mismatch is handled
* later when {@link #initMeasuredEnergyStatsLocked} is called.
*/
- mGlobalMeasuredEnergyStats = MeasuredEnergyStats.createAndReadSummaryFromParcel(in);
+ mGlobalMeasuredEnergyStats = MeasuredEnergyStats.createAndReadSummaryFromParcel(
+ mMeasuredEnergyStatsConfig, in);
mStartCount++;
@@ -16191,8 +16545,8 @@
u.mWifiRadioApWakeupCount = null;
}
- u.mUidMeasuredEnergyStats = MeasuredEnergyStats.createAndReadSummaryFromParcel(in,
- /* template */ mGlobalMeasuredEnergyStats);
+ u.mUidMeasuredEnergyStats = MeasuredEnergyStats.createAndReadSummaryFromParcel(
+ mMeasuredEnergyStatsConfig, in);
int NW = in.readInt();
if (NW > (MAX_WAKELOCKS_PER_UID+1)) {
@@ -16304,6 +16658,7 @@
*
* @param out the Parcel to be written to.
*/
+ @GuardedBy("this")
public void writeSummaryToParcel(Parcel out, boolean inclHistory) {
pullPendingStateUpdatesLocked();
@@ -16377,7 +16732,8 @@
out.writeLong(mNextMaxDailyDeadlineMs);
out.writeLong(mBatteryTimeToFullSeconds);
- MeasuredEnergyStats.writeSummaryToParcel(mGlobalMeasuredEnergyStats, out, false, false);
+ MeasuredEnergyStats.Config.writeToParcel(mMeasuredEnergyStatsConfig, out);
+ MeasuredEnergyStats.writeSummaryToParcel(mGlobalMeasuredEnergyStats, out);
mScreenOnTimer.writeSummaryFromParcelLocked(out, nowRealtime);
mScreenDozeTimer.writeSummaryFromParcelLocked(out, nowRealtime);
@@ -16700,7 +17056,7 @@
out.writeInt(0);
}
- MeasuredEnergyStats.writeSummaryToParcel(u.mUidMeasuredEnergyStats, out, true, true);
+ MeasuredEnergyStats.writeSummaryToParcel(u.mUidMeasuredEnergyStats, out);
final ArrayMap<String, Uid.Wakelock> wakeStats = u.mWakelockStats.getMap();
int NW = wakeStats.size();
@@ -16822,10 +17178,13 @@
LongSamplingCounterArray.writeSummaryToParcelLocked(out, mBinderThreadCpuTimesUs);
}
+ @GuardedBy("this")
public void readFromParcel(Parcel in) {
readFromParcelLocked(in);
}
+ @GuardedBy("this")
+ @SuppressWarnings("GuardedBy") // errorprone false positive on u.readFromParcelLocked
void readFromParcelLocked(Parcel in) {
int magic = in.readInt();
if (magic != MAGIC) {
@@ -16966,9 +17325,9 @@
mLastWriteTimeMs = in.readLong();
mBatteryTimeToFullSeconds = in.readLong();
- if (in.readInt() != 0) {
- mGlobalMeasuredEnergyStats = new MeasuredEnergyStats(in);
- }
+ mMeasuredEnergyStatsConfig = MeasuredEnergyStats.Config.createFromParcel(in);
+ mGlobalMeasuredEnergyStats =
+ MeasuredEnergyStats.createFromParcel(mMeasuredEnergyStatsConfig, in);
mRpmStats.clear();
int NRPMS = in.readInt();
@@ -17039,22 +17398,26 @@
for (int i = 0; i < numUids; i++) {
int uid = in.readInt();
Uid u = new Uid(this, uid, elapsedRealtimeMs, uptimeMs);
- u.readFromParcelLocked(mOnBatteryTimeBase, mOnBatteryScreenOffTimeBase, in);
+ u.readFromParcelLocked(mOnBatteryTimeBase, mOnBatteryScreenOffTimeBase,
+ in);
mUidStats.append(uid, u);
}
mBinderThreadCpuTimesUs = LongSamplingCounterArray.readFromParcel(in, mOnBatteryTimeBase);
}
+ @GuardedBy("this")
public void writeToParcel(Parcel out, int flags) {
writeToParcelLocked(out, true, flags);
}
+ @GuardedBy("this")
public void writeToParcelWithoutUids(Parcel out, int flags) {
writeToParcelLocked(out, false, flags);
}
@SuppressWarnings("unused")
+ @GuardedBy("this")
void writeToParcelLocked(Parcel out, boolean inclUids, int flags) {
// Need to update with current kernel wake lock counts.
pullPendingStateUpdatesLocked();
@@ -17170,6 +17533,8 @@
out.writeLong(mLastWriteTimeMs);
out.writeLong(mBatteryTimeToFullSeconds);
+ MeasuredEnergyStats.Config.writeToParcel(mMeasuredEnergyStatsConfig, out);
+
if (mGlobalMeasuredEnergyStats != null) {
out.writeInt(1);
mGlobalMeasuredEnergyStats.writeToParcel(out);
@@ -17332,6 +17697,7 @@
}
};
+ @GuardedBy("this")
public void prepareForDumpLocked() {
// Need to retrieve current kernel wake lock stats before printing.
pullPendingStateUpdatesLocked();
@@ -17343,6 +17709,7 @@
updateSystemServiceCallStats();
}
+ @GuardedBy("this")
public void dumpLocked(Context context, PrintWriter pw, int flags, int reqUid, long histStart) {
if (DEBUG) {
pw.println("mOnBatteryTimeBase:");
diff --git a/core/java/com/android/internal/os/ClassLoaderFactory.java b/core/java/com/android/internal/os/ClassLoaderFactory.java
index d347f2e..8b0411d 100644
--- a/core/java/com/android/internal/os/ClassLoaderFactory.java
+++ b/core/java/com/android/internal/os/ClassLoaderFactory.java
@@ -80,15 +80,20 @@
*/
public static ClassLoader createClassLoader(String dexPath,
String librarySearchPath, ClassLoader parent, String classloaderName,
- List<ClassLoader> sharedLibraries) {
+ List<ClassLoader> sharedLibraries, List<ClassLoader> sharedLibrariesLoadedAfter) {
ClassLoader[] arrayOfSharedLibraries = (sharedLibraries == null)
? null
: sharedLibraries.toArray(new ClassLoader[sharedLibraries.size()]);
+ ClassLoader[] arrayOfSharedLibrariesLoadedAfterApp = (sharedLibrariesLoadedAfter == null)
+ ? null
+ : sharedLibrariesLoadedAfter.toArray(
+ new ClassLoader[sharedLibrariesLoadedAfter.size()]);
if (isPathClassLoaderName(classloaderName)) {
- return new PathClassLoader(dexPath, librarySearchPath, parent, arrayOfSharedLibraries);
+ return new PathClassLoader(dexPath, librarySearchPath, parent, arrayOfSharedLibraries,
+ arrayOfSharedLibrariesLoadedAfterApp);
} else if (isDelegateLastClassLoaderName(classloaderName)) {
return new DelegateLastClassLoader(dexPath, librarySearchPath, parent,
- arrayOfSharedLibraries);
+ arrayOfSharedLibraries, arrayOfSharedLibrariesLoadedAfterApp);
}
throw new AssertionError("Invalid classLoaderName: " + classloaderName);
@@ -102,20 +107,20 @@
String librarySearchPath, String libraryPermittedPath, ClassLoader parent,
int targetSdkVersion, boolean isNamespaceShared, String classLoaderName) {
return createClassLoader(dexPath, librarySearchPath, libraryPermittedPath,
- parent, targetSdkVersion, isNamespaceShared, classLoaderName, null, null);
+ parent, targetSdkVersion, isNamespaceShared, classLoaderName, null, null, null);
}
-
/**
* Create a ClassLoader and initialize a linker-namespace for it.
*/
public static ClassLoader createClassLoader(String dexPath,
String librarySearchPath, String libraryPermittedPath, ClassLoader parent,
int targetSdkVersion, boolean isNamespaceShared, String classLoaderName,
- List<ClassLoader> sharedLibraries, List<String> nativeSharedLibraries) {
+ List<ClassLoader> sharedLibraries, List<String> nativeSharedLibraries,
+ List<ClassLoader> sharedLibrariesAfter) {
final ClassLoader classLoader = createClassLoader(dexPath, librarySearchPath, parent,
- classLoaderName, sharedLibraries);
+ classLoaderName, sharedLibraries, sharedLibrariesAfter);
String sonameList = "";
if (nativeSharedLibraries != null) {
diff --git a/core/java/com/android/internal/os/CpuPowerCalculator.java b/core/java/com/android/internal/os/CpuPowerCalculator.java
index e693d9d..4599231 100644
--- a/core/java/com/android/internal/os/CpuPowerCalculator.java
+++ b/core/java/com/android/internal/os/CpuPowerCalculator.java
@@ -25,11 +25,13 @@
import android.util.Log;
import android.util.SparseArray;
+import java.util.Arrays;
import java.util.List;
public class CpuPowerCalculator extends PowerCalculator {
private static final String TAG = "CpuPowerCalculator";
private static final boolean DEBUG = BatteryStatsHelper.DEBUG;
+ private static final BatteryConsumer.Key[] UNINITIALIZED_KEYS = new BatteryConsumer.Key[0];
private final int mNumCpuClusters;
// Time-in-state based CPU power estimation model computes the estimated power
@@ -44,13 +46,16 @@
private final UsageBasedPowerEstimator[] mPerClusterPowerEstimators;
// Multiple estimators per cluster: one per available scaling frequency. Note that different
// clusters have different sets of frequencies and corresponding power consumption averages.
- private final UsageBasedPowerEstimator[][] mPerCpuFreqPowerEstimators;
+ private final UsageBasedPowerEstimator[][] mPerCpuFreqPowerEstimatorsByCluster;
+ // Flattened array of estimators across clusters
+ private final UsageBasedPowerEstimator[] mPerCpuFreqPowerEstimators;
private static class Result {
public long durationMs;
public double powerMah;
public long durationFgMs;
public String packageWithHighestDrain;
+ public double[] perProcStatePowerMah;
}
public CpuPowerCalculator(PowerProfile profile) {
@@ -65,14 +70,23 @@
profile.getAveragePowerForCpuCluster(cluster));
}
- mPerCpuFreqPowerEstimators = new UsageBasedPowerEstimator[mNumCpuClusters][];
+ int freqCount = 0;
+ for (int cluster = 0; cluster < mNumCpuClusters; cluster++) {
+ freqCount += profile.getNumSpeedStepsInCpuCluster(cluster);
+ }
+
+ mPerCpuFreqPowerEstimatorsByCluster = new UsageBasedPowerEstimator[mNumCpuClusters][];
+ mPerCpuFreqPowerEstimators = new UsageBasedPowerEstimator[freqCount];
+ int index = 0;
for (int cluster = 0; cluster < mNumCpuClusters; cluster++) {
final int speedsForCluster = profile.getNumSpeedStepsInCpuCluster(cluster);
- mPerCpuFreqPowerEstimators[cluster] = new UsageBasedPowerEstimator[speedsForCluster];
+ mPerCpuFreqPowerEstimatorsByCluster[cluster] =
+ new UsageBasedPowerEstimator[speedsForCluster];
for (int speed = 0; speed < speedsForCluster; speed++) {
- mPerCpuFreqPowerEstimators[cluster][speed] =
- new UsageBasedPowerEstimator(
- profile.getAveragePowerForCpuCore(cluster, speed));
+ final UsageBasedPowerEstimator estimator = new UsageBasedPowerEstimator(
+ profile.getAveragePowerForCpuCore(cluster, speed));
+ mPerCpuFreqPowerEstimatorsByCluster[cluster][speed] = estimator;
+ mPerCpuFreqPowerEstimators[index++] = estimator;
}
}
}
@@ -82,12 +96,20 @@
long rawRealtimeUs, long rawUptimeUs, BatteryUsageStatsQuery query) {
double totalPowerMah = 0;
+ BatteryConsumer.Key[] keys = UNINITIALIZED_KEYS;
Result result = new Result();
final SparseArray<UidBatteryConsumer.Builder> uidBatteryConsumerBuilders =
builder.getUidBatteryConsumerBuilders();
for (int i = uidBatteryConsumerBuilders.size() - 1; i >= 0; i--) {
final UidBatteryConsumer.Builder app = uidBatteryConsumerBuilders.valueAt(i);
- calculateApp(app, app.getBatteryStatsUid(), query, result);
+ if (keys == UNINITIALIZED_KEYS) {
+ if (query.isProcessStateDataNeeded()) {
+ keys = app.getKeys(BatteryConsumer.POWER_COMPONENT_CPU);
+ } else {
+ keys = null;
+ }
+ }
+ calculateApp(app, app.getBatteryStatsUid(), query, result, keys);
totalPowerMah += result.powerMah;
}
@@ -105,7 +127,7 @@
}
private void calculateApp(UidBatteryConsumer.Builder app, BatteryStats.Uid u,
- BatteryUsageStatsQuery query, Result result) {
+ BatteryUsageStatsQuery query, Result result, BatteryConsumer.Key[] keys) {
final long consumptionUC = u.getCpuMeasuredBatteryConsumptionUC();
final int powerModel = getPowerModel(consumptionUC, query);
calculatePowerAndDuration(u, powerModel, consumptionUC, BatteryStats.STATS_SINCE_CHARGED,
@@ -114,6 +136,75 @@
app.setConsumedPower(BatteryConsumer.POWER_COMPONENT_CPU, result.powerMah, powerModel)
.setUsageDurationMillis(BatteryConsumer.POWER_COMPONENT_CPU, result.durationMs)
.setPackageWithHighestDrain(result.packageWithHighestDrain);
+
+ if (query.isProcessStateDataNeeded() && keys != null) {
+ switch (powerModel) {
+ case BatteryConsumer.POWER_MODEL_MEASURED_ENERGY:
+ calculateMeasuredPowerPerProcessState(app, u, keys);
+ break;
+ case BatteryConsumer.POWER_MODEL_POWER_PROFILE:
+ calculateModeledPowerPerProcessState(app, u, keys, result);
+ break;
+ }
+ }
+ }
+
+ private void calculateMeasuredPowerPerProcessState(UidBatteryConsumer.Builder app,
+ BatteryStats.Uid u, BatteryConsumer.Key[] keys) {
+ for (BatteryConsumer.Key key : keys) {
+ // The key for "PROCESS_STATE_ANY" has already been populated with the
+ // full energy across all states. We don't want to override it with
+ // the energy for "other" states, which excludes the tracked states like
+ // foreground, background etc.
+ if (key.processState == BatteryConsumer.PROCESS_STATE_ANY) {
+ continue;
+ }
+
+ final long consumptionUC = u.getCpuMeasuredBatteryConsumptionUC(key.processState);
+ if (consumptionUC != 0) {
+ app.setConsumedPower(key, uCtoMah(consumptionUC),
+ BatteryConsumer.POWER_MODEL_MEASURED_ENERGY);
+ }
+ }
+ }
+
+ private void calculateModeledPowerPerProcessState(UidBatteryConsumer.Builder app,
+ BatteryStats.Uid u, BatteryConsumer.Key[] keys, Result result) {
+ if (result.perProcStatePowerMah == null) {
+ result.perProcStatePowerMah = new double[BatteryConsumer.PROCESS_STATE_COUNT];
+ } else {
+ Arrays.fill(result.perProcStatePowerMah, 0);
+ }
+
+ for (int uidProcState = 0; uidProcState < BatteryStats.Uid.NUM_PROCESS_STATE;
+ uidProcState++) {
+ @BatteryConsumer.ProcessState int procState =
+ BatteryStats.mapUidProcessStateToBatteryConsumerProcessState(uidProcState);
+ if (procState == BatteryConsumer.PROCESS_STATE_ANY) {
+ continue;
+ }
+
+ // TODO(b/191921016): use per-state CPU active time
+ final long cpuActiveTime = 0;
+ // TODO(b/191921016): use per-state CPU cluster times
+ final long[] cpuClusterTimes = null;
+
+ final long[] cpuFreqTimes = u.getCpuFreqTimes(BatteryStats.STATS_SINCE_CHARGED,
+ uidProcState);
+ if (cpuActiveTime != 0 || cpuClusterTimes != null || cpuFreqTimes != null) {
+ result.perProcStatePowerMah[procState] += calculateUidModeledPowerMah(u,
+ cpuActiveTime, cpuClusterTimes, cpuFreqTimes);
+ }
+ }
+
+ for (BatteryConsumer.Key key : keys) {
+ if (key.processState == BatteryConsumer.PROCESS_STATE_ANY) {
+ continue;
+ }
+
+ app.setConsumedPower(key, result.perProcStatePowerMah[key.processState],
+ BatteryConsumer.POWER_MODEL_POWER_PROFILE);
+ }
}
@Override
@@ -145,7 +236,7 @@
long durationMs = (u.getUserCpuTimeUs(statsType) + u.getSystemCpuTimeUs(statsType)) / 1000;
final double powerMah;
- switch(powerModel) {
+ switch (powerModel) {
case BatteryConsumer.POWER_MODEL_MEASURED_ENERGY:
powerMah = uCtoMah(consumptionUC);
break;
@@ -205,16 +296,21 @@
* Calculates CPU power consumed by the specified app, using the PowerProfile model.
*/
public double calculateUidModeledPowerMah(BatteryStats.Uid u, int statsType) {
+ return calculateUidModeledPowerMah(u, u.getCpuActiveTime(), u.getCpuClusterTimes(),
+ u.getCpuFreqTimes(statsType));
+ }
+
+ private double calculateUidModeledPowerMah(BatteryStats.Uid u, long cpuActiveTime,
+ long[] cpuClusterTimes, long[] cpuFreqTimes) {
// Constant battery drain when CPU is active
- double powerMah = calculateActiveCpuPowerMah(u.getCpuActiveTime());
+ double powerMah = calculateActiveCpuPowerMah(cpuActiveTime);
// Additional per-cluster battery drain
- long[] cpuClusterTimes = u.getCpuClusterTimes();
if (cpuClusterTimes != null) {
if (cpuClusterTimes.length == mNumCpuClusters) {
for (int cluster = 0; cluster < mNumCpuClusters; cluster++) {
- double power = calculatePerCpuClusterPowerMah(cluster,
- cpuClusterTimes[cluster]);
+ final double power = mPerClusterPowerEstimators[cluster]
+ .calculatePower(cpuClusterTimes[cluster]);
powerMah += power;
if (DEBUG) {
Log.d(TAG, "UID " + u.getUid() + ": CPU cluster #" + cluster
@@ -228,21 +324,17 @@
}
}
- // Additional per-frequency battery drain
- for (int cluster = 0; cluster < mNumCpuClusters; cluster++) {
- final int speedsForCluster = mPerCpuFreqPowerEstimators[cluster].length;
- for (int speed = 0; speed < speedsForCluster; speed++) {
- final long timeUs = u.getTimeAtCpuSpeed(cluster, speed, statsType);
- final double power = calculatePerCpuFreqPowerMah(cluster, speed,
- timeUs / 1000);
- if (DEBUG) {
- Log.d(TAG, "UID " + u.getUid() + ": CPU cluster #" + cluster + " step #"
- + speed + " timeUs=" + timeUs + " power="
- + formatCharge(power));
+ if (cpuFreqTimes != null) {
+ if (cpuFreqTimes.length == mPerCpuFreqPowerEstimators.length) {
+ for (int i = 0; i < cpuFreqTimes.length; i++) {
+ powerMah += mPerCpuFreqPowerEstimators[i].calculatePower(cpuFreqTimes[i]);
}
- powerMah += power;
+ } else {
+ Log.w(TAG, "UID " + u.getUid() + " CPU freq # mismatch: Power Profile # "
+ + mPerCpuFreqPowerEstimators.length + " actual # " + cpuFreqTimes.length);
}
}
+
return powerMah;
}
@@ -259,7 +351,7 @@
/**
* Calculates CPU cluster power consumption.
*
- * @param cluster CPU cluster used.
+ * @param cluster CPU cluster used.
* @param clusterDurationMs duration of CPU cluster usage.
* @return a double in milliamp-hours of estimated CPU cluster power consumption.
*/
@@ -270,14 +362,14 @@
/**
* Calculates CPU cluster power consumption at a specific speedstep.
*
- * @param cluster CPU cluster used.
- * @param speedStep which speedstep used.
+ * @param cluster CPU cluster used.
+ * @param speedStep which speedstep used.
* @param clusterSpeedDurationsMs duration of CPU cluster usage at the specified speed step.
* @return a double in milliamp-hours of estimated CPU cluster-speed power consumption.
*/
public double calculatePerCpuFreqPowerMah(int cluster, int speedStep,
long clusterSpeedDurationsMs) {
- return mPerCpuFreqPowerEstimators[cluster][speedStep].calculatePower(
+ return mPerCpuFreqPowerEstimatorsByCluster[cluster][speedStep].calculatePower(
clusterSpeedDurationsMs);
}
}
diff --git a/core/java/com/android/internal/os/SomeArgs.java b/core/java/com/android/internal/os/SomeArgs.java
index 5ec882c..d1b483b 100644
--- a/core/java/com/android/internal/os/SomeArgs.java
+++ b/core/java/com/android/internal/os/SomeArgs.java
@@ -54,7 +54,6 @@
public Object arg6;
public Object arg7;
public Object arg8;
- public Object arg9;
public int argi1;
@UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
public int argi2;
@@ -63,6 +62,8 @@
public int argi4;
public int argi5;
public int argi6;
+ public long argl1;
+ public long argl2;
private SomeArgs() {
/* do nothing - reduce visibility */
@@ -122,12 +123,13 @@
arg6 = null;
arg7 = null;
arg8 = null;
- arg9 = null;
argi1 = 0;
argi2 = 0;
argi3 = 0;
argi4 = 0;
argi5 = 0;
argi6 = 0;
+ argl1 = 0;
+ argl2 = 0;
}
}
diff --git a/core/java/com/android/internal/policy/SystemBarUtils.java b/core/java/com/android/internal/policy/SystemBarUtils.java
new file mode 100644
index 0000000..6bf1333
--- /dev/null
+++ b/core/java/com/android/internal/policy/SystemBarUtils.java
@@ -0,0 +1,94 @@
+/*
+ * Copyright (C) 2021 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.internal.policy;
+
+import android.content.Context;
+import android.content.res.Resources;
+import android.graphics.Insets;
+import android.util.RotationUtils;
+import android.view.DisplayCutout;
+import android.view.Surface;
+
+import com.android.internal.R;
+
+/**
+ * Utility functions for system bars used by both window manager and System UI.
+ *
+ * @hide
+ */
+public final class SystemBarUtils {
+
+ /**
+ * Gets the status bar height.
+ */
+ public static int getStatusBarHeight(Context context) {
+ return getStatusBarHeight(context.getResources(), context.getDisplay().getCutout());
+ }
+
+ /**
+ * Gets the status bar height with a specific display cutout.
+ */
+ public static int getStatusBarHeight(Resources res, DisplayCutout cutout) {
+ final int defaultSize = res.getDimensionPixelSize(R.dimen.status_bar_height);
+ final int safeInsetTop = cutout == null ? 0 : cutout.getSafeInsetTop();
+ final int waterfallInsetTop = cutout == null ? 0 : cutout.getWaterfallInsets().top;
+ // The status bar height should be:
+ // Max(top cutout size, (status bar default height + waterfall top size))
+ return Math.max(safeInsetTop, defaultSize + waterfallInsetTop);
+ }
+
+ /**
+ * Gets the status bar height for a specific rotation.
+ */
+ public static int getStatusBarHeightForRotation(
+ Context context, @Surface.Rotation int targetRot) {
+ final int rotation = context.getDisplay().getRotation();
+ final DisplayCutout cutout = context.getDisplay().getCutout();
+
+ Insets insets = cutout == null ? Insets.NONE : Insets.of(cutout.getSafeInsets());
+ Insets waterfallInsets = cutout == null ? Insets.NONE : cutout.getWaterfallInsets();
+ // rotate insets to target rotation if needed.
+ if (rotation != targetRot) {
+ if (!insets.equals(Insets.NONE)) {
+ insets = RotationUtils.rotateInsets(
+ insets, RotationUtils.deltaRotation(rotation, targetRot));
+ }
+ if (!waterfallInsets.equals(Insets.NONE)) {
+ waterfallInsets = RotationUtils.rotateInsets(
+ waterfallInsets, RotationUtils.deltaRotation(rotation, targetRot));
+ }
+ }
+ final int defaultSize =
+ context.getResources().getDimensionPixelSize(R.dimen.status_bar_height);
+ // The status bar height should be:
+ // Max(top cutout size, (status bar default height + waterfall top size))
+ return Math.max(insets.top, defaultSize + waterfallInsets.top);
+ }
+
+ /**
+ * Gets the height of area above QQS where battery/time go in notification panel. The height
+ * equals to status bar height if status bar height is bigger than the
+ * {@link R.dimen#quick_qs_offset_height}.
+ */
+ public static int getQuickQsOffsetHeight(Context context) {
+ final int defaultSize = context.getResources().getDimensionPixelSize(
+ R.dimen.quick_qs_offset_height);
+ final int statusBarHeight = getStatusBarHeight(context);
+ // Equals to status bar height if status bar height is bigger.
+ return Math.max(defaultSize, statusBarHeight);
+ }
+}
diff --git a/core/java/com/android/internal/power/MeasuredEnergyStats.java b/core/java/com/android/internal/power/MeasuredEnergyStats.java
index 72b57ab..0723766 100644
--- a/core/java/com/android/internal/power/MeasuredEnergyStats.java
+++ b/core/java/com/android/internal/power/MeasuredEnergyStats.java
@@ -29,6 +29,7 @@
import android.view.Display;
import com.android.internal.annotations.VisibleForTesting;
+import com.android.internal.os.LongMultiStateCounter;
import java.io.PrintWriter;
import java.lang.annotation.Retention;
@@ -75,6 +76,147 @@
public @interface StandardPowerBucket {
}
+ private static final int INVALID_STATE = -1;
+
+ /**
+ * Configuration of measured energy stats: which power rails (buckets) are supported on
+ * this device, what custom power drains are supported etc.
+ */
+ public static class Config {
+ private final boolean[] mSupportedStandardBuckets;
+ @NonNull
+ private final String[] mCustomBucketNames;
+ private final boolean[] mSupportedMultiStateBuckets;
+ @NonNull
+ private final String[] mStateNames;
+
+ public Config(@NonNull boolean[] supportedStandardBuckets,
+ @Nullable String[] customBucketNames,
+ @NonNull int[] supportedMultiStateBuckets,
+ @Nullable String[] stateNames) {
+ mSupportedStandardBuckets = supportedStandardBuckets;
+ mCustomBucketNames = customBucketNames != null ? customBucketNames : new String[0];
+ mSupportedMultiStateBuckets =
+ new boolean[supportedStandardBuckets.length + mCustomBucketNames.length];
+ for (int bucket : supportedMultiStateBuckets) {
+ if (mSupportedStandardBuckets[bucket]) {
+ mSupportedMultiStateBuckets[bucket] = true;
+ }
+ }
+ mStateNames = stateNames != null ? stateNames : new String[] {""};
+ }
+
+ /**
+ * Returns true if the supplied Config is compatible with this one and therefore
+ * data collected with one of them will work with the other.
+ */
+ public boolean isCompatible(Config other) {
+ return Arrays.equals(mSupportedStandardBuckets, other.mSupportedStandardBuckets)
+ && Arrays.equals(mCustomBucketNames, other.mCustomBucketNames)
+ && Arrays.equals(mSupportedMultiStateBuckets,
+ other.mSupportedMultiStateBuckets)
+ && Arrays.equals(mStateNames, other.mStateNames);
+ }
+
+ /**
+ * Writes the Config object into the supplied Parcel.
+ */
+ public static void writeToParcel(@Nullable Config config, Parcel out) {
+ if (config == null) {
+ out.writeBoolean(false);
+ return;
+ }
+
+ out.writeBoolean(true);
+ out.writeInt(config.mSupportedStandardBuckets.length);
+ out.writeBooleanArray(config.mSupportedStandardBuckets);
+ out.writeStringArray(config.mCustomBucketNames);
+ int multiStateBucketCount = 0;
+ for (boolean supported : config.mSupportedMultiStateBuckets) {
+ if (supported) {
+ multiStateBucketCount++;
+ }
+ }
+ final int[] supportedMultiStateBuckets = new int[multiStateBucketCount];
+ int index = 0;
+ for (int bucket = 0; bucket < config.mSupportedMultiStateBuckets.length; bucket++) {
+ if (config.mSupportedMultiStateBuckets[bucket]) {
+ supportedMultiStateBuckets[index++] = bucket;
+ }
+ }
+ out.writeInt(multiStateBucketCount);
+ out.writeIntArray(supportedMultiStateBuckets);
+ out.writeStringArray(config.mStateNames);
+ }
+
+ /**
+ * Reads a Config object from the supplied Parcel.
+ */
+ @Nullable
+ public static Config createFromParcel(Parcel in) {
+ if (!in.readBoolean()) {
+ return null;
+ }
+
+ final int supportedStandardBucketCount = in.readInt();
+ final boolean[] supportedStandardBuckets = new boolean[supportedStandardBucketCount];
+ in.readBooleanArray(supportedStandardBuckets);
+ final String[] customBucketNames = in.readStringArray();
+ final int supportedMultiStateBucketCount = in.readInt();
+ final int[] supportedMultiStateBuckets = new int[supportedMultiStateBucketCount];
+ in.readIntArray(supportedMultiStateBuckets);
+ final String[] stateNames = in.readStringArray();
+ return new Config(supportedStandardBuckets, customBucketNames,
+ supportedMultiStateBuckets, stateNames);
+ }
+
+ /** Get number of possible buckets, including both standard and custom ones. */
+ private int getNumberOfBuckets() {
+ return mSupportedStandardBuckets.length + mCustomBucketNames.length;
+ }
+
+ /**
+ * Returns true if the specified charge bucket is tracked.
+ */
+ public boolean isSupportedBucket(int index) {
+ return mSupportedStandardBuckets[index];
+ }
+
+ @NonNull
+ public String[] getCustomBucketNames() {
+ return mCustomBucketNames;
+ }
+
+ /**
+ * Returns true if the specified charge bucket is tracked on a per-state basis.
+ */
+ public boolean isSupportedMultiStateBucket(int index) {
+ return mSupportedMultiStateBuckets[index];
+ }
+
+ public String[] getStateNames() {
+ return mStateNames;
+ }
+
+ /**
+ * If the index is a standard bucket, returns its name; otherwise returns its prefixed
+ * custom bucket number.
+ */
+ private String getBucketName(int index) {
+ if (isValidStandardBucket(index)) {
+ return DebugUtils.valueToString(MeasuredEnergyStats.class, "POWER_BUCKET_", index);
+ }
+ final int customBucket = indexToCustomBucket(index);
+ StringBuilder name = new StringBuilder().append("CUSTOM_").append(customBucket);
+ if (!TextUtils.isEmpty(mCustomBucketNames[customBucket])) {
+ name.append('(').append(mCustomBucketNames[customBucket]).append(')');
+ }
+ return name.toString();
+ }
+ }
+
+ private final Config mConfig;
+
/**
* Total charge (in microcoulombs) that a power bucket (including both
* {@link StandardPowerBucket} and custom buckets) has accumulated since the last reset.
@@ -90,74 +232,76 @@
*/
private final long[] mAccumulatedChargeMicroCoulomb;
- private final String[] mCustomBucketNames;
+ private LongMultiStateCounter[] mAccumulatedMultiStateChargeMicroCoulomb;
+ private int mState = INVALID_STATE;
+ private long mStateChangeTimestampMs;
/**
* Creates a MeasuredEnergyStats set to support the provided power buckets.
* supportedStandardBuckets must be of size {@link #NUMBER_STANDARD_POWER_BUCKETS}.
* numCustomBuckets >= 0 is the number of (non-standard) custom power buckets on the device.
*/
- public MeasuredEnergyStats(@NonNull boolean[] supportedStandardBuckets,
- @Nullable String[] customBucketNames) {
- mCustomBucketNames = customBucketNames == null ? new String[0] : customBucketNames;
- final int numTotalBuckets = NUMBER_STANDARD_POWER_BUCKETS + mCustomBucketNames.length;
+ public MeasuredEnergyStats(MeasuredEnergyStats.Config config) {
+ mConfig = config;
+ final int numTotalBuckets = config.getNumberOfBuckets();
mAccumulatedChargeMicroCoulomb = new long[numTotalBuckets];
// Initialize to all zeros where supported, otherwise POWER_DATA_UNAVAILABLE.
// All custom buckets are, by definition, supported, so their values stay at 0.
for (int stdBucket = 0; stdBucket < NUMBER_STANDARD_POWER_BUCKETS; stdBucket++) {
- if (!supportedStandardBuckets[stdBucket]) {
+ if (!mConfig.mSupportedStandardBuckets[stdBucket]) {
mAccumulatedChargeMicroCoulomb[stdBucket] = POWER_DATA_UNAVAILABLE;
}
}
}
/**
- * Creates a new zero'd MeasuredEnergyStats, using the template to determine which buckets are
- * supported. This certainly does NOT produce an exact clone of the template.
+ * Reads a MeasuredEnergyStats from the supplied Parcel.
*/
- private MeasuredEnergyStats(MeasuredEnergyStats template) {
- final int numIndices = template.getNumberOfIndices();
- mAccumulatedChargeMicroCoulomb = new long[numIndices];
- // Initialize to all zeros where supported, otherwise POWER_DATA_UNAVAILABLE.
- // All custom buckets are, by definition, supported, so their values stay at 0.
- for (int stdBucket = 0; stdBucket < NUMBER_STANDARD_POWER_BUCKETS; stdBucket++) {
- if (!template.isIndexSupported(stdBucket)) {
- mAccumulatedChargeMicroCoulomb[stdBucket] = POWER_DATA_UNAVAILABLE;
- }
+ @Nullable
+ public static MeasuredEnergyStats createFromParcel(Config config, Parcel in) {
+ if (!in.readBoolean()) {
+ return null;
}
- mCustomBucketNames = template.getCustomBucketNames();
- }
-
- /**
- * Creates a new zero'd MeasuredEnergyStats, using the template to determine which buckets are
- * supported.
- */
- public static MeasuredEnergyStats createFromTemplate(MeasuredEnergyStats template) {
- return new MeasuredEnergyStats(template);
- }
-
- /**
- * Constructor for creating a temp MeasuredEnergyStats.
- * See {@link #createAndReadSummaryFromParcel(Parcel, MeasuredEnergyStats)}.
- */
- private MeasuredEnergyStats(int numIndices) {
- mAccumulatedChargeMicroCoulomb = new long[numIndices];
- mCustomBucketNames = new String[numIndices - NUMBER_STANDARD_POWER_BUCKETS];
+ return new MeasuredEnergyStats(config, in);
}
/** Construct from parcel. */
- public MeasuredEnergyStats(Parcel in) {
+ public MeasuredEnergyStats(MeasuredEnergyStats.Config config, Parcel in) {
+ mConfig = config;
+
final int size = in.readInt();
mAccumulatedChargeMicroCoulomb = new long[size];
in.readLongArray(mAccumulatedChargeMicroCoulomb);
- mCustomBucketNames = in.readStringArray();
+ if (in.readBoolean()) {
+ mAccumulatedMultiStateChargeMicroCoulomb = new LongMultiStateCounter[size];
+ for (int i = 0; i < size; i++) {
+ if (in.readBoolean()) {
+ mAccumulatedMultiStateChargeMicroCoulomb[i] =
+ LongMultiStateCounter.CREATOR.createFromParcel(in);
+ }
+ }
+ } else {
+ mAccumulatedMultiStateChargeMicroCoulomb = null;
+ }
}
/** Write to parcel */
public void writeToParcel(Parcel out) {
out.writeInt(mAccumulatedChargeMicroCoulomb.length);
out.writeLongArray(mAccumulatedChargeMicroCoulomb);
- out.writeStringArray(mCustomBucketNames);
+ if (mAccumulatedMultiStateChargeMicroCoulomb != null) {
+ out.writeBoolean(true);
+ for (LongMultiStateCounter counter : mAccumulatedMultiStateChargeMicroCoulomb) {
+ if (counter != null) {
+ out.writeBoolean(true);
+ counter.writeToParcel(out, 0);
+ } else {
+ out.writeBoolean(false);
+ }
+ }
+ } else {
+ out.writeBoolean(false);
+ }
}
/**
@@ -167,17 +311,27 @@
* Note: {@link com.android.internal.os.BatteryStatsImpl#VERSION} must be updated if summary
* parceling changes.
*
- * Corresponding write performed by {@link #writeSummaryToParcel(Parcel, boolean)}.
+ * Corresponding write performed by {@link #writeSummaryToParcel(Parcel)}.
*/
- private void readSummaryFromParcel(Parcel in, boolean overwriteAvailability) {
+ private void readSummaryFromParcel(Parcel in) {
final int numWrittenEntries = in.readInt();
for (int entry = 0; entry < numWrittenEntries; entry++) {
final int index = in.readInt();
final long chargeUC = in.readLong();
- if (overwriteAvailability) {
- mAccumulatedChargeMicroCoulomb[index] = chargeUC;
- } else {
+ LongMultiStateCounter multiStateCounter = null;
+ if (in.readBoolean()) {
+ multiStateCounter = LongMultiStateCounter.CREATOR.createFromParcel(in);
+ }
+
+ if (index < mAccumulatedChargeMicroCoulomb.length) {
setValueIfSupported(index, chargeUC);
+ if (multiStateCounter != null) {
+ if (mAccumulatedMultiStateChargeMicroCoulomb == null) {
+ mAccumulatedMultiStateChargeMicroCoulomb =
+ new LongMultiStateCounter[numWrittenEntries];
+ }
+ mAccumulatedMultiStateChargeMicroCoulomb[index] = multiStateCounter;
+ }
}
}
}
@@ -186,20 +340,26 @@
* Write to summary parcel.
* Note: Measured subsystem availability may be different when the summary parcel is read.
*
- * Corresponding read performed by {@link #readSummaryFromParcel(Parcel, boolean)}.
+ * Corresponding read performed by {@link #readSummaryFromParcel(Parcel)}.
*/
- private void writeSummaryToParcel(Parcel out, boolean skipZero) {
+ private void writeSummaryToParcel(Parcel out) {
final int posOfNumWrittenEntries = out.dataPosition();
out.writeInt(0);
int numWrittenEntries = 0;
// Write only the supported buckets (with non-zero charge, if applicable).
for (int index = 0; index < mAccumulatedChargeMicroCoulomb.length; index++) {
final long charge = mAccumulatedChargeMicroCoulomb[index];
- if (charge < 0) continue;
- if (charge == 0 && skipZero) continue;
+ if (charge <= 0) continue;
out.writeInt(index);
out.writeLong(charge);
+ if (mAccumulatedMultiStateChargeMicroCoulomb != null
+ && mAccumulatedMultiStateChargeMicroCoulomb[index] != null) {
+ out.writeBoolean(true);
+ mAccumulatedMultiStateChargeMicroCoulomb[index].writeToParcel(out, 0);
+ } else {
+ out.writeBoolean(false);
+ }
numWrittenEntries++;
}
final int currPos = out.dataPosition();
@@ -208,40 +368,87 @@
out.setDataPosition(currPos);
}
- /** Get number of possible buckets, including both standard and custom ones. */
- private int getNumberOfIndices() {
- return mAccumulatedChargeMicroCoulomb.length;
- }
-
-
/** Updates the given standard power bucket with the given charge if accumulate is true. */
public void updateStandardBucket(@StandardPowerBucket int bucket, long chargeDeltaUC) {
+ updateStandardBucket(bucket, chargeDeltaUC, 0);
+ }
+
+ /**
+ * Updates the given standard power bucket with the given charge if supported.
+ * @param timestampMs elapsed realtime in milliseconds
+ */
+ public void updateStandardBucket(@StandardPowerBucket int bucket, long chargeDeltaUC,
+ long timestampMs) {
checkValidStandardBucket(bucket);
- updateEntry(bucket, chargeDeltaUC);
+ updateEntry(bucket, chargeDeltaUC, timestampMs);
}
/** Updates the given custom power bucket with the given charge if accumulate is true. */
public void updateCustomBucket(int customBucket, long chargeDeltaUC) {
+ updateCustomBucket(customBucket, chargeDeltaUC, 0);
+ }
+
+ /**
+ * Updates the given custom power bucket with the given charge if supported.
+ * @param timestampMs elapsed realtime in milliseconds
+ */
+ public void updateCustomBucket(int customBucket, long chargeDeltaUC, long timestampMs) {
if (!isValidCustomBucket(customBucket)) {
Slog.e(TAG, "Attempted to update invalid custom bucket " + customBucket);
return;
}
final int index = customBucketToIndex(customBucket);
- updateEntry(index, chargeDeltaUC);
+ updateEntry(index, chargeDeltaUC, timestampMs);
}
- /** Updates the given index with the given charge if accumulate is true. */
- private void updateEntry(int index, long chargeDeltaUC) {
+ /** Updates the given bucket with the given charge delta. */
+ private void updateEntry(int index, long chargeDeltaUC, long timestampMs) {
if (mAccumulatedChargeMicroCoulomb[index] >= 0L) {
mAccumulatedChargeMicroCoulomb[index] += chargeDeltaUC;
+ if (mState != INVALID_STATE && mConfig.isSupportedMultiStateBucket(index)) {
+ if (mAccumulatedMultiStateChargeMicroCoulomb == null) {
+ mAccumulatedMultiStateChargeMicroCoulomb =
+ new LongMultiStateCounter[mAccumulatedChargeMicroCoulomb.length];
+ }
+ LongMultiStateCounter counter =
+ mAccumulatedMultiStateChargeMicroCoulomb[index];
+ if (counter == null) {
+ counter = new LongMultiStateCounter(mConfig.mStateNames.length);
+ mAccumulatedMultiStateChargeMicroCoulomb[index] = counter;
+ counter.setState(mState, mStateChangeTimestampMs);
+ counter.updateValue(0, mStateChangeTimestampMs);
+ }
+ counter.updateValue(mAccumulatedChargeMicroCoulomb[index], timestampMs);
+ }
} else {
Slog.wtf(TAG, "Attempting to add " + chargeDeltaUC + " to unavailable bucket "
- + getBucketName(index) + " whose value was "
+ + mConfig.getBucketName(index) + " whose value was "
+ mAccumulatedChargeMicroCoulomb[index]);
}
}
/**
+ * Updates the "state" on all multi-state counters used by this MeasuredEnergyStats. Further
+ * accumulated charge updates will assign the deltas to this state, until the state changes.
+ *
+ * If setState is never called on a MeasuredEnergyStats object, then it does not track
+ * per-state usage.
+ */
+ public void setState(int state, long timestampMs) {
+ mState = state;
+ mStateChangeTimestampMs = timestampMs;
+ if (mAccumulatedMultiStateChargeMicroCoulomb == null) {
+ return;
+ }
+ for (int i = 0; i < mAccumulatedMultiStateChargeMicroCoulomb.length; i++) {
+ LongMultiStateCounter counter = mAccumulatedMultiStateChargeMicroCoulomb[i];
+ if (counter != null) {
+ counter.setState(state, timestampMs);
+ }
+ }
+ }
+
+ /**
* Return accumulated charge (in microcouloumb) for a standard power bucket since last reset.
* Returns {@link android.os.BatteryStats#POWER_DATA_UNAVAILABLE} if this data is unavailable.
* @throws IllegalArgumentException if no such {@link StandardPowerBucket}.
@@ -252,6 +459,26 @@
}
/**
+ * Returns the accumulated charge (in microcouloumb) for the standard power bucket and
+ * the specified state since last reset.
+ *
+ * Returns {@link android.os.BatteryStats#POWER_DATA_UNAVAILABLE} if this data is unavailable.
+ */
+ public long getAccumulatedStandardBucketCharge(@StandardPowerBucket int bucket, int state) {
+ if (!mConfig.isSupportedMultiStateBucket(bucket)) {
+ return POWER_DATA_UNAVAILABLE;
+ }
+ if (mAccumulatedMultiStateChargeMicroCoulomb == null) {
+ return 0;
+ }
+ final LongMultiStateCounter counter = mAccumulatedMultiStateChargeMicroCoulomb[bucket];
+ if (counter == null) {
+ return 0;
+ }
+ return counter.getCount(state);
+ }
+
+ /**
* Return accumulated charge (in microcoulomb) for the a custom power bucket since last
* reset.
* Returns {@link android.os.BatteryStats#POWER_DATA_UNAVAILABLE} if this data is unavailable.
@@ -289,32 +516,6 @@
}
/**
- * Create a MeasuredEnergyStats object from a summary parcel.
- *
- * Corresponding write performed by
- * {@link #writeSummaryToParcel(MeasuredEnergyStats, Parcel, boolean, boolean)}.
- *
- * @return a new MeasuredEnergyStats object as described.
- * Returns null if the parcel indicates there is no data to populate.
- */
- public static @Nullable MeasuredEnergyStats createAndReadSummaryFromParcel(Parcel in) {
- final int arraySize = in.readInt();
- // Check if any MeasuredEnergyStats exists on the parcel
- if (arraySize == 0) return null;
-
- final String[] customBucketNames;
- if (in.readBoolean()) {
- customBucketNames = in.readStringArray();
- } else {
- customBucketNames = new String[0];
- }
- final MeasuredEnergyStats stats = new MeasuredEnergyStats(
- new boolean[NUMBER_STANDARD_POWER_BUCKETS], customBucketNames);
- stats.readSummaryFromParcel(in, true);
- return stats;
- }
-
- /**
* Create a MeasuredEnergyStats using the template to determine which buckets are supported,
* and populate this new object from the given parcel.
*
@@ -322,44 +523,37 @@
* possible (not necessarily supported) standard and custom buckets.
*
* Corresponding write performed by
- * {@link #writeSummaryToParcel(MeasuredEnergyStats, Parcel, boolean, boolean)}.
+ * {@link #writeSummaryToParcel(MeasuredEnergyStats, Parcel)}.
*
* @return a new MeasuredEnergyStats object as described.
* Returns null if the stats contain no non-0 information (such as if template is null
* or if the parcel indicates there is no data to populate).
- *
- * @see #createFromTemplate
*/
- public static @Nullable MeasuredEnergyStats createAndReadSummaryFromParcel(Parcel in,
- @Nullable MeasuredEnergyStats template) {
+ public static @Nullable MeasuredEnergyStats createAndReadSummaryFromParcel(
+ @Nullable Config config, Parcel in) {
final int arraySize = in.readInt();
// Check if any MeasuredEnergyStats exists on the parcel
if (arraySize == 0) return null;
- boolean includesCustomBucketNames = in.readBoolean();
- if (includesCustomBucketNames) {
- // Consume the array of custom bucket names. They are already included in the
- // template.
- in.readStringArray();
- }
- if (template == null) {
+ if (config == null) {
// Nothing supported anymore. Create placeholder object just to consume the parcel data.
- final MeasuredEnergyStats mes = new MeasuredEnergyStats(arraySize);
- mes.readSummaryFromParcel(in, false);
+ final MeasuredEnergyStats mes = new MeasuredEnergyStats(
+ new Config(new boolean[arraySize], null, new int[0], new String[]{""}));
+ mes.readSummaryFromParcel(in);
return null;
}
- if (arraySize != template.getNumberOfIndices()) {
+ if (arraySize != config.getNumberOfBuckets()) {
Slog.wtf(TAG, "Size of MeasuredEnergyStats parcel (" + arraySize
- + ") does not match template (" + template.getNumberOfIndices() + ").");
+ + ") does not match config (" + config.getNumberOfBuckets() + ").");
// Something is horribly wrong. Just consume the parcel and return null.
- final MeasuredEnergyStats mes = new MeasuredEnergyStats(arraySize);
- mes.readSummaryFromParcel(in, false);
+ final MeasuredEnergyStats mes = new MeasuredEnergyStats(config);
+ mes.readSummaryFromParcel(in);
return null;
}
- final MeasuredEnergyStats stats = createFromTemplate(template);
- stats.readSummaryFromParcel(in, false);
+ final MeasuredEnergyStats stats = new MeasuredEnergyStats(config);
+ stats.readSummaryFromParcel(in);
if (stats.containsInterestingData()) {
return stats;
} else {
@@ -379,28 +573,20 @@
/**
* Write a MeasuredEnergyStats to a parcel. If the stats is null, just write a 0.
*
- * Corresponding read performed by {@link #createAndReadSummaryFromParcel(Parcel)}
- * and {@link #createAndReadSummaryFromParcel(Parcel, MeasuredEnergyStats)}.
+ * Corresponding read performed by {@link #createAndReadSummaryFromParcel}.
*/
- public static void writeSummaryToParcel(@Nullable MeasuredEnergyStats stats,
- Parcel dest, boolean skipZero, boolean skipCustomBucketNames) {
+ public static void writeSummaryToParcel(@Nullable MeasuredEnergyStats stats, Parcel dest) {
if (stats == null) {
dest.writeInt(0);
return;
}
- dest.writeInt(stats.getNumberOfIndices());
- if (!skipCustomBucketNames) {
- dest.writeBoolean(true);
- dest.writeStringArray(stats.getCustomBucketNames());
- } else {
- dest.writeBoolean(false);
- }
- stats.writeSummaryToParcel(dest, skipZero);
+ dest.writeInt(stats.mConfig.getNumberOfBuckets());
+ stats.writeSummaryToParcel(dest);
}
/** Reset accumulated charges. */
private void reset() {
- final int numIndices = getNumberOfIndices();
+ final int numIndices = mConfig.getNumberOfBuckets();
for (int index = 0; index < numIndices; index++) {
setValueIfSupported(index, 0L);
}
@@ -431,46 +617,32 @@
return mAccumulatedChargeMicroCoulomb[index] != POWER_DATA_UNAVAILABLE;
}
- /** Check if the supported power buckets are precisely those given. */
- public boolean isSupportEqualTo(
- @NonNull boolean[] queriedStandardBuckets, @Nullable String[] customBucketNames) {
- if (customBucketNames == null) {
- //In practice customBucketNames should never be null, but sanitize it just to be sure.
- customBucketNames = new String[0];
- }
-
- final int numBuckets = getNumberOfIndices();
- final int numCustomBuckets = customBucketNames == null ? 0 : customBucketNames.length;
- if (numBuckets != NUMBER_STANDARD_POWER_BUCKETS + numCustomBuckets) {
- return false;
- }
-
- if (!Arrays.equals(mCustomBucketNames, customBucketNames)) {
- return false;
- }
-
- for (int stdBucket = 0; stdBucket < NUMBER_STANDARD_POWER_BUCKETS; stdBucket++) {
- if (isStandardBucketSupported(stdBucket) != queriedStandardBuckets[stdBucket]) {
- return false;
- }
- }
- return true;
- }
-
- public String[] getCustomBucketNames() {
- return mCustomBucketNames;
- }
-
/** Dump debug data. */
public void dump(PrintWriter pw) {
pw.print(" ");
for (int index = 0; index < mAccumulatedChargeMicroCoulomb.length; index++) {
- pw.print(getBucketName(index));
+ pw.print(mConfig.getBucketName(index));
pw.print(" : ");
pw.print(mAccumulatedChargeMicroCoulomb[index]);
if (!isIndexSupported(index)) {
pw.print(" (unsupported)");
}
+ if (mAccumulatedMultiStateChargeMicroCoulomb != null) {
+ final LongMultiStateCounter counter =
+ mAccumulatedMultiStateChargeMicroCoulomb[index];
+ if (counter != null) {
+ pw.print(" [");
+ for (int i = 0; i < mConfig.mStateNames.length; i++) {
+ if (i != 0) {
+ pw.print(" ");
+ }
+ pw.print(mConfig.mStateNames[i]);
+ pw.print(": ");
+ pw.print(counter.getCount(i));
+ }
+ pw.print("]");
+ }
+ }
if (index != mAccumulatedChargeMicroCoulomb.length - 1) {
pw.print(", ");
}
@@ -478,22 +650,6 @@
pw.println();
}
- /**
- * If the index is a standard bucket, returns its name; otherwise returns its prefixed custom
- * bucket number.
- */
- private String getBucketName(int index) {
- if (isValidStandardBucket(index)) {
- return DebugUtils.valueToString(MeasuredEnergyStats.class, "POWER_BUCKET_", index);
- }
- final int customBucket = indexToCustomBucket(index);
- StringBuilder name = new StringBuilder().append("CUSTOM_").append(customBucket);
- if (mCustomBucketNames != null && !TextUtils.isEmpty(mCustomBucketNames[customBucket])) {
- name.append('(').append(mCustomBucketNames[customBucket]).append(')');
- }
- return name.toString();
- }
-
/** Get the number of custom power buckets on this device. */
public int getNumberCustomPowerBuckets() {
return mAccumulatedChargeMicroCoulomb.length - NUMBER_STANDARD_POWER_BUCKETS;
diff --git a/core/java/com/android/internal/statusbar/IStatusBar.aidl b/core/java/com/android/internal/statusbar/IStatusBar.aidl
index 0f245e6..4e758e6 100644
--- a/core/java/com/android/internal/statusbar/IStatusBar.aidl
+++ b/core/java/com/android/internal/statusbar/IStatusBar.aidl
@@ -290,4 +290,5 @@
void runGcForTest();
void requestAddTile(in ComponentName componentName, in CharSequence appName, in CharSequence label, in Icon icon, in IAddTileResultCallback callback);
+ void cancelRequestAddTile(in String packageName);
}
diff --git a/core/java/com/android/internal/statusbar/IStatusBarService.aidl b/core/java/com/android/internal/statusbar/IStatusBarService.aidl
index 49c32be..40a3951 100644
--- a/core/java/com/android/internal/statusbar/IStatusBarService.aidl
+++ b/core/java/com/android/internal/statusbar/IStatusBarService.aidl
@@ -161,4 +161,5 @@
void suppressAmbientDisplay(boolean suppress);
void requestAddTile(in ComponentName componentName, in CharSequence label, in Icon icon, int userId, in IAddTileResultCallback callback);
+ void cancelRequestAddTile(in String packageName);
}
diff --git a/core/jni/Android.bp b/core/jni/Android.bp
index 1a1a8ba..2bd385c 100644
--- a/core/jni/Android.bp
+++ b/core/jni/Android.bp
@@ -404,6 +404,7 @@
name: "libandroid_runtime_vm_headers",
host_supported: true,
vendor_available: true,
+ recovery_available: true,
// TODO(b/153609531): remove when libbinder is not native_bridge_supported
native_bridge_supported: true,
// Allow only modules from the following list to create threads that can be
diff --git a/core/jni/android_os_Parcel.cpp b/core/jni/android_os_Parcel.cpp
index be9aaaf..0d530f6 100644
--- a/core/jni/android_os_Parcel.cpp
+++ b/core/jni/android_os_Parcel.cpp
@@ -604,6 +604,25 @@
return thisParcel->compareData(*otherParcel);
}
+static jboolean android_os_Parcel_compareDataInRange(JNIEnv* env, jclass clazz, jlong thisNativePtr,
+ jint thisOffset, jlong otherNativePtr,
+ jint otherOffset, jint length) {
+ Parcel* thisParcel = reinterpret_cast<Parcel*>(thisNativePtr);
+ LOG_ALWAYS_FATAL_IF(thisParcel == nullptr, "Should not be null");
+
+ Parcel* otherParcel = reinterpret_cast<Parcel*>(otherNativePtr);
+ LOG_ALWAYS_FATAL_IF(otherParcel == nullptr, "Should not be null");
+
+ int result;
+ status_t err =
+ thisParcel->compareDataInRange(thisOffset, *otherParcel, otherOffset, length, &result);
+ if (err != NO_ERROR) {
+ signalExceptionForError(env, clazz, err);
+ return JNI_FALSE;
+ }
+ return (result == 0) ? JNI_TRUE : JNI_FALSE;
+}
+
static void android_os_Parcel_appendFrom(JNIEnv* env, jclass clazz, jlong thisNativePtr,
jlong otherNativePtr, jint offset, jint length)
{
@@ -841,6 +860,7 @@
{"nativeMarshall", "(J)[B", (void*)android_os_Parcel_marshall},
{"nativeUnmarshall", "(J[BII)V", (void*)android_os_Parcel_unmarshall},
{"nativeCompareData", "(JJ)I", (void*)android_os_Parcel_compareData},
+ {"nativeCompareDataInRange", "(JIJII)Z", (void*)android_os_Parcel_compareDataInRange},
{"nativeAppendFrom", "(JJII)V", (void*)android_os_Parcel_appendFrom},
// @CriticalNative
{"nativeHasFileDescriptors", "(J)Z", (void*)android_os_Parcel_hasFileDescriptors},
diff --git a/core/jni/android_util_Binder.cpp b/core/jni/android_util_Binder.cpp
index 793b4eb..61b91dd 100644
--- a/core/jni/android_util_Binder.cpp
+++ b/core/jni/android_util_Binder.cpp
@@ -959,8 +959,7 @@
return IPCThreadState::self()->getCallingUid();
}
-static jboolean android_os_Binder_isHandlingTransaction()
-{
+static jboolean android_os_Binder_isDirectlyHandlingTransaction() {
return getCurrentServingCall() == BinderCallType::BINDER;
}
@@ -1056,6 +1055,7 @@
// ----------------------------------------------------------------------------
+// clang-format off
static const JNINativeMethod gBinderMethods[] = {
/* name, signature, funcPtr */
// @CriticalNative
@@ -1063,7 +1063,7 @@
// @CriticalNative
{ "getCallingUid", "()I", (void*)android_os_Binder_getCallingUid },
// @CriticalNative
- { "isHandlingTransaction", "()Z", (void*)android_os_Binder_isHandlingTransaction },
+ { "isDirectlyHandlingTransaction", "()Z", (void*)android_os_Binder_isDirectlyHandlingTransaction },
// @CriticalNative
{ "clearCallingIdentity", "()J", (void*)android_os_Binder_clearCallingIdentity },
// @CriticalNative
@@ -1088,6 +1088,7 @@
{ "getExtension", "()Landroid/os/IBinder;", (void*)android_os_Binder_getExtension },
{ "setExtension", "(Landroid/os/IBinder;)V", (void*)android_os_Binder_setExtension },
};
+// clang-format on
const char* const kBinderPathName = "android/os/Binder";
diff --git a/core/jni/fd_utils.cpp b/core/jni/fd_utils.cpp
index 6f5cc53..40f6e4f 100644
--- a/core/jni/fd_utils.cpp
+++ b/core/jni/fd_utils.cpp
@@ -138,6 +138,14 @@
return true;
}
+ // Allow Runtime Resource Overlays inside APEXes.
+ static const char* kOverlayPathSuffix = "/overlay";
+ if (android::base::StartsWith(path, kApexPrefix) &&
+ android::base::EndsWith(android::base::Dirname(path), kOverlayPathSuffix) &&
+ android::base::EndsWith(path, kApkSuffix) && path.find("/../") == std::string::npos) {
+ return true;
+ }
+
static const char* kOverlayIdmapPrefix = "/data/resource-cache/";
static const char* kOverlayIdmapSuffix = ".apk@idmap";
if (android::base::StartsWith(path, kOverlayIdmapPrefix) &&
diff --git a/core/proto/android/server/windowmanagerservice.proto b/core/proto/android/server/windowmanagerservice.proto
index 40e3f60..3248cf5 100644
--- a/core/proto/android/server/windowmanagerservice.proto
+++ b/core/proto/android/server/windowmanagerservice.proto
@@ -202,7 +202,6 @@
optional .com.android.server.wm.IdentifierProto resumed_activity = 24;
repeated TaskProto tasks = 25 [deprecated=true];
optional bool display_ready = 26;
-
optional WindowStateProto input_method_target = 27;
optional WindowStateProto input_method_input_target = 28;
optional WindowStateProto input_method_control_target = 29;
@@ -214,6 +213,9 @@
optional int32 ime_policy = 34;
repeated InsetsSourceProviderProto insets_source_providers = 35;
+ optional bool is_sleeping = 36;
+ repeated string sleep_tokens = 37;
+
}
/* represents DisplayArea object */
@@ -527,7 +529,7 @@
message WindowFramesProto {
option (.android.msg_privacy).dest = DEST_AUTOMATIC;
- optional .android.graphics.RectProto containing_frame = 1;
+ optional .android.graphics.RectProto containing_frame = 1 [deprecated=true];
optional .android.graphics.RectProto content_frame = 2 [deprecated=true];
optional .android.graphics.RectProto decor_frame = 3 [deprecated=true];
optional .android.graphics.RectProto display_frame = 4;
diff --git a/core/res/AndroidManifest.xml b/core/res/AndroidManifest.xml
index 329f02a..df69ed0 100644
--- a/core/res/AndroidManifest.xml
+++ b/core/res/AndroidManifest.xml
@@ -5802,6 +5802,12 @@
<permission android:name="android.permission.ACCESS_TV_DESCRAMBLER"
android:protectionLevel="signature|privileged|vendorPrivileged" />
+ <!-- @SystemApi Allows an application to access shared filter of TV tuner HAL
+ <p>Not for use by third-party applications.
+ @hide -->
+ <permission android:name="android.permission.ACCESS_TV_SHARED_FILTER"
+ android:protectionLevel="signature|privileged|vendorPrivileged" />
+
<!-- Allows an application to create trusted displays. @hide -->
<permission android:name="android.permission.ADD_TRUSTED_DISPLAY"
android:protectionLevel="signature" />
@@ -5911,6 +5917,11 @@
<permission android:name="android.permission.READ_GLOBAL_APP_SEARCH_DATA"
android:protectionLevel="internal|role" />
+ <!-- @SystemApi Allows an application to create virtual devices in VirtualDeviceManager.
+ @hide -->
+ <permission android:name="android.permission.CREATE_VIRTUAL_DEVICE"
+ android:protectionLevel="internal|role" />
+
<!-- Attribution for Geofencing service. -->
<attribution android:tag="GeofencingService" android:label="@string/geofencing_service"/>
<!-- Attribution for Country Detector. -->
diff --git a/core/res/res/values-as/strings.xml b/core/res/res/values-as/strings.xml
index 7dbeabf..f023d88 100644
--- a/core/res/res/values-as/strings.xml
+++ b/core/res/res/values-as/strings.xml
@@ -236,7 +236,7 @@
<string name="shutdown_confirm" product="default" msgid="136816458966692315">"আপোনাৰ ফ\'নটো বন্ধ হ\'ব।"</string>
<string name="shutdown_confirm_question" msgid="796151167261608447">"আপুনি ফ\'নটোৰ পাৱাৰ অফ কৰিব বিচাৰেনে?"</string>
<string name="reboot_safemode_title" msgid="5853949122655346734">"সুৰক্ষিত ম\'ডলৈ ৰিবুট কৰক"</string>
- <string name="reboot_safemode_confirm" msgid="1658357874737219624">"আপুনি সুৰক্ষিত ম\'ডলৈ ৰিবুট কৰিব বিচাৰেনে? এই কার্যই আপুনি ইনষ্টল কৰা তৃতীয় পক্ষৰ সকলো এপ্লিকেশ্বন অক্ষম কৰিব। আপুনি পুনৰ ৰিবুট কৰিলে সেইবোৰ পুনঃস্থাপন কৰা হ\'ব।"</string>
+ <string name="reboot_safemode_confirm" msgid="1658357874737219624">"আপুনি সুৰক্ষিত ম\'ডলৈ ৰিবুট কৰিব বিচাৰেনে? এই কার্যই আপুনি ইনষ্টল কৰা তৃতীয় পক্ষৰ আটাইবোৰ এপ্লিকেশ্বন অক্ষম কৰিব। আপুনি পুনৰ ৰিবুট কৰিলে সেইবোৰ পুনঃস্থাপন কৰা হ\'ব।"</string>
<string name="recent_tasks_title" msgid="8183172372995396653">"শেহতীয়া"</string>
<string name="no_recent_tasks" msgid="9063946524312275906">"কোনো শেহতীয়া এপ্ নাই।"</string>
<string name="global_actions" product="tablet" msgid="4412132498517933867">"টে\'বলেটৰ বিকল্পসমূহ"</string>
@@ -255,7 +255,7 @@
<string name="bugreport_option_interactive_title" msgid="7968287837902871289">"ইণ্টাৰেক্টিভ অভিযোগ"</string>
<string name="bugreport_option_interactive_summary" msgid="8493795476325339542">"বেছিভাগ পৰিস্থিতিত এয়া ব্যৱহাৰ কৰক। ই আপোনাক অভিযোগৰ অগ্ৰগতি ট্ৰেক কৰিবলৈ, সমস্যাটোৰ সম্পর্কে অধিক বিৱৰণ দিবলৈ আৰু স্ক্ৰীণশ্বট ল\'বলৈ অনুমতি দিয়ে। ই কম ব্যৱহাৰ হোৱা সেই শাখাসমূহক অন্তৰ্ভুক্ত নকৰিব পাৰে যিবোৰক অভিযোগ কৰিবলৈ দীৰ্ঘ সময়ৰ প্ৰয়োজন হয়।"</string>
<string name="bugreport_option_full_title" msgid="7681035745950045690">"সম্পূৰ্ণ অভিযোগ"</string>
- <string name="bugreport_option_full_summary" msgid="1975130009258435885">"যেতিয়া আপোনাৰ ডিভাইচটোৱে সঁহাৰি নিদিয়া হয় বা ই অতি লেহেমীয়া হৈ পৰে বা যেতিয়া আপোনাক সকলো অভিযোগৰ শাখাৰ প্ৰয়োজন হয় তেতিয়া ছিষ্টেমত কম হস্তক্ষেপৰ বাবে এই বিকল্প ব্যৱহাৰ কৰক। আপোনাক অধিক বিৱৰণ দিবলৈ বা অতিৰিক্ত স্ক্ৰীণশ্বট ল’বলৈ নিদিয়ে।"</string>
+ <string name="bugreport_option_full_summary" msgid="1975130009258435885">"যেতিয়া আপোনাৰ ডিভাইচটোৱে সঁহাৰি নিদিয়া হয় বা ই অতি লেহেমীয়া হৈ পৰে বা যেতিয়া আপোনাক আটাইবোৰ অভিযোগৰ শাখাৰ প্ৰয়োজন হয় তেতিয়া ছিষ্টেমত কম হস্তক্ষেপৰ বাবে এই বিকল্প ব্যৱহাৰ কৰক। আপোনাক অধিক বিৱৰণ দিবলৈ বা অতিৰিক্ত স্ক্ৰীণশ্বট ল’বলৈ নিদিয়ে।"</string>
<plurals name="bugreport_countdown" formatted="false" msgid="3906120379260059206">
<item quantity="one">ত্ৰুটি সম্পর্কীয় অভিযোগৰ বাবে <xliff:g id="NUMBER_1">%d</xliff:g>ছেকেণ্ডৰ ভিতৰত স্ক্ৰীণশ্বট লোৱা হ\'ব।</item>
<item quantity="other">ত্ৰুটি সম্পর্কীয় অভিযোগৰ বাবে <xliff:g id="NUMBER_1">%d</xliff:g>ছেকেণ্ডৰ ভিতৰত স্ক্ৰীণশ্বট লোৱা হ\'ব।</item>
@@ -373,9 +373,9 @@
<string name="permlab_sendSms" msgid="7757368721742014252">"এছএমএছ ৰ বার্তাবোৰ প্ৰেৰণ কৰিব আৰু চাব পাৰে"</string>
<string name="permdesc_sendSms" msgid="6757089798435130769">"এপটোক এছএমএছ বাৰ্তা পঠিয়াবলৈ অনুমতি দিয়ে৷ ইয়াৰ ফলত অপ্ৰত্যাশিত মাচুল ভৰিবলগা হ\'ব পাৰে৷ ক্ষতিকাৰক এপসমূহে আপোনাৰ অনুমতি নোলোৱাকৈয়ে বাৰ্তা পঠিয়াই আপোনাৰ পৰা মাচুল কাটিব পাৰে৷"</string>
<string name="permlab_readSms" msgid="5164176626258800297">"আপোনাৰ পাঠ বার্তাবোৰ পঢ়ক (এছএমএছ বা এমএমএছ)"</string>
- <string name="permdesc_readSms" product="tablet" msgid="7912990447198112829">"এই এপটোৱে আপোনাৰ টেবলেটটোত সংৰক্ষিত সকলো এছএমএছ (পাঠ) বাৰ্তা পঢ়িব পাৰে।"</string>
- <string name="permdesc_readSms" product="tv" msgid="3054753345758011986">"এই এপ্টোৱে আপোনাৰ Android TV ডিভাইচত ষ্ট’ৰ কৰি ৰখা সকলো এছএমএছ (পাঠ) বাৰ্তা পঢ়িব পাৰে।"</string>
- <string name="permdesc_readSms" product="default" msgid="774753371111699782">"এই এপটোৱে আপোনাৰ ফ\'নত সংৰক্ষিত সকলো এছএমএছ (পাঠ) বাৰ্তা পঢ়িব পাৰে।"</string>
+ <string name="permdesc_readSms" product="tablet" msgid="7912990447198112829">"এই এপ্টোৱে আপোনাৰ টেবলেটটোত সংৰক্ষিত আটাইবোৰ এছএমএছ (পাঠ) বাৰ্তা পঢ়িব পাৰে।"</string>
+ <string name="permdesc_readSms" product="tv" msgid="3054753345758011986">"এই এপ্টোৱে আপোনাৰ Android TV ডিভাইচত ষ্ট’ৰ কৰি ৰখা আটাইবোৰ এছএমএছ (পাঠ) বাৰ্তা পঢ়িব পাৰে।"</string>
+ <string name="permdesc_readSms" product="default" msgid="774753371111699782">"এই এপ্টোৱে আপোনাৰ ফ\'নত সংৰক্ষিত আটাইবোৰ এছএমএছ (পাঠ) বাৰ্তা পঢ়িব পাৰে।"</string>
<string name="permlab_receiveWapPush" msgid="4223747702856929056">"পাঠ বার্তা (WAP) বোৰ লাভ কৰক"</string>
<string name="permdesc_receiveWapPush" msgid="1638677888301778457">"এপটোক WAP বাৰ্তাবোৰ পাবলৈ আৰু প্ৰক্ৰিয়া সম্পন্ন কৰিবলৈ অনুমতি দিয়ে৷ এই অনুমতিত আপোনালৈ পঠিওৱা বাৰ্তাবোৰ আপোনাক নেদেখুৱাকৈয়ে নিৰীক্ষণ বা মচাৰ সক্ষমতা অন্তৰ্ভুক্ত থাকে৷"</string>
<string name="permlab_getTasks" msgid="7460048811831750262">"চলি থকা এপসমূহ বিচাৰি উলিয়াওক"</string>
@@ -429,9 +429,9 @@
<string name="permlab_bodySensors" msgid="3411035315357380862">"শৰীৰৰ ছেন্সৰসমূহ (যেনে হৃদপিণ্ডৰ গতিৰ হাৰ নিৰীক্ষক) ব্যৱহাৰ কৰিব পাৰে"</string>
<string name="permdesc_bodySensors" product="default" msgid="2365357960407973997">"আপোনাৰ হৃদস্পন্দনৰ দৰে শাৰীৰিক অৱস্থাক নিৰীক্ষণ কৰা ছেন্সৰৰ পৰা ডেটা লাভ কৰিবলৈ এপক অনুমতি দিয়ে।"</string>
<string name="permlab_readCalendar" msgid="6408654259475396200">"কেলেণ্ডাৰৰ কাৰ্যক্ৰম আৰু সবিশেষ পঢ়িব পাৰে"</string>
- <string name="permdesc_readCalendar" product="tablet" msgid="515452384059803326">"এই এপটোৱে আপোনাৰ টেবলেটটোত সংৰক্ষিত সকলো কেলেণ্ডাৰ কাৰ্যক্ৰম পঢ়িব পাৰে আৰু আপোনাৰ কেলেণ্ডাৰৰ ডেটা শ্বেয়াৰ বা ছেভ কৰিব পাৰে।"</string>
- <string name="permdesc_readCalendar" product="tv" msgid="5811726712981647628">"এই এপ্টোৱে আপোনাৰ Android TV ডিভাইচটোত ষ্ট’ৰ কৰি ৰখা সকলো কেলেণ্ডাৰৰ অনুষ্ঠান পঢ়িব পাৰে আৰু আপোনাৰ কেলেণ্ডাৰৰ ডেটা শ্বেয়াৰ অথবা ছেভ কৰিব পাৰে।"</string>
- <string name="permdesc_readCalendar" product="default" msgid="9118823807655829957">"এই এপটোৱে আপোনাৰ ফ\'নটোত সংৰক্ষিত সকলো কেলেণ্ডাৰ কাৰ্যক্ৰম পঢ়িব পাৰে আৰু আপোনাৰ কেলেণ্ডাৰৰ ডেটা শ্বেয়াৰ বা ছেভ কৰিব পাৰে।"</string>
+ <string name="permdesc_readCalendar" product="tablet" msgid="515452384059803326">"এই এপ্টোৱে আপোনাৰ টেবলেটটোত সংৰক্ষিত আটাইবোৰ কেলেণ্ডাৰ কাৰ্যক্ৰম পঢ়িব পাৰে আৰু আপোনাৰ কেলেণ্ডাৰৰ ডেটা শ্বেয়াৰ বা ছেভ কৰিব পাৰে।"</string>
+ <string name="permdesc_readCalendar" product="tv" msgid="5811726712981647628">"এই এপ্টোৱে আপোনাৰ Android TV ডিভাইচটোত ষ্ট’ৰ কৰি ৰখা আটাইবোৰ কেলেণ্ডাৰৰ অনুষ্ঠান পঢ়িব পাৰে আৰু আপোনাৰ কেলেণ্ডাৰৰ ডেটা শ্বেয়াৰ অথবা ছেভ কৰিব পাৰে।"</string>
+ <string name="permdesc_readCalendar" product="default" msgid="9118823807655829957">"এই এপ্টোৱে আপোনাৰ ফ\'নটোত সংৰক্ষিত আটাইবোৰ কেলেণ্ডাৰ কাৰ্যক্ৰম পঢ়িব পাৰে আৰু আপোনাৰ কেলেণ্ডাৰৰ ডেটা শ্বেয়াৰ বা ছেভ কৰিব পাৰে।"</string>
<string name="permlab_writeCalendar" msgid="6422137308329578076">"গৰাকীয়ে নজনাকৈয়ে কেলেণ্ডাৰৰ কাৰ্যক্ৰম সংশোধন কৰি অতিথিসকললৈ ইমেইল প্ৰেৰণ কৰক"</string>
<string name="permdesc_writeCalendar" product="tablet" msgid="8722230940717092850">"এই এপটোৱে আপোনাৰ টেবলেটত কেলেণ্ডাৰ কাৰ্যক্ৰম যোগ কৰিব, আঁতৰাব বা সলনি কৰিব পাৰে। ই এনে বাৰ্তা পঠিয়াব পাৰে যিবোৰ কেলেণ্ডাৰৰ গৰাকীৰ পৰা অহা যেন লাগিব বা ই গৰাকীক নজনোৱাকৈ কাৰ্যক্ৰম সলনি কৰিব পাৰে৷"</string>
<string name="permdesc_writeCalendar" product="tv" msgid="951246749004952706">"এই এপ্টোৱে আপোনাৰ Android TV ডিভাইচত কেলেণ্ডাৰ অনুষ্ঠানবোৰ যোগ দিব, আঁতৰাব অথবা সলনি কৰিব পাৰে। এই এপ্টোৱে এনে বাৰ্তা পঠিয়াব পাৰে যিবোৰ কেলেণ্ডাৰৰ গৰাকীৰ পৰা অহা বুলি প্ৰদর্শিত হ’ব পাৰে অথবা এইটোৱে গৰাকীসকলক নজনোৱাকৈ অনুষ্ঠানবোৰ সলনি কৰিব পাৰে।"</string>
@@ -518,9 +518,9 @@
<string name="permlab_changeWifiState" msgid="7947824109713181554">"ৱাই-ফাই সংযোগ কৰক আৰু ইয়াৰ সংযোগ বিচ্ছিন্ন কৰক"</string>
<string name="permdesc_changeWifiState" msgid="7170350070554505384">"এপটোক ৱাই-ফাই এক্সেছ পইণ্টলৈ সংযোগ কৰিবলৈ আৰু তাৰ সংযোগ বিচ্ছিন্ন কৰিবলৈ আৰু ৱাই-ফাই নেটৱৰ্কসমূহৰ বাবে ডিভাইচ কনফিগাৰেশ্বনত সাল-সলনি কৰিবলৈ অনুমতি দিয়ে৷"</string>
<string name="permlab_changeWifiMulticastState" msgid="285626875870754696">"ৱাই-ফাই মাল্টিকাষ্ট প্ৰচাৰৰ অনুমতি দিয়ক"</string>
- <string name="permdesc_changeWifiMulticastState" product="tablet" msgid="191079868596433554">"আপোনাৰ টেবলেটৰ লগতে মাল্টিকাষ্ট ঠিকনাবোৰ ও ব্যৱহাৰ কৰি এপক ৱাই-ফাই নেটৱর্কত থকা সকলো ডিভাইচলৈ পঠোৱা পেকেট প্ৰাপ্ত কৰিবলৈ অনুমতি দিয়ে। এই কার্যই ন\'ন মাল্টিকাষ্ট ম\'ডতকৈ বেটাৰিৰ অধিক চ্চাৰ্জ ব্যৱহাৰ কৰে।"</string>
- <string name="permdesc_changeWifiMulticastState" product="tv" msgid="1336952358450652595">"কেৱল আপোনাৰ Android TV ডিভাইচটোৱেই নহয়, মাল্টিকাষ্ট ঠিকনাবোৰ ব্যৱহাৰ কৰি এটা ৱাই-ফাই নেটৱর্কত থকা সকলো ডিভাইচলৈ পঠোৱা পেকেটবোৰ লাভ কৰিবলৈ এপ্টোক অনুমতি দিয়ে। এই কার্যই ন’ন-মাল্টিকাষ্ট ম’ডতকৈ অধিক পাৱাৰ ব্যৱহাৰ কৰে।"</string>
- <string name="permdesc_changeWifiMulticastState" product="default" msgid="8296627590220222740">"আপোনাৰ ফ\'নৰ লগতে মাল্টিকাষ্ট ঠিকনাবোৰ ও ব্যৱহাৰ কৰি এপক ৱাই-ফাই নেটৱর্কত থকা সকলো ডিভাইচলৈ পঠোৱা পেকেট প্ৰাপ্ত কৰিবলৈ অনুমতি দিয়ে। এই কার্যই ন\'ন মাল্টিকাষ্ট ম\'ডতকৈ বেটাৰিৰ অধিক চ্চাৰ্জ ব্যৱহাৰ কৰে।"</string>
+ <string name="permdesc_changeWifiMulticastState" product="tablet" msgid="191079868596433554">"কেৱল আপোনাৰ টেবলেটটোৱেই নহয়, মাল্টিকাষ্ট ঠিকনা ব্যৱহাৰ কৰি এটা ৱাই-ফাই নেটৱর্কত থকা আটাইবোৰ ডিভাইচলৈ পঠিওৱা পেকেট লাভ কৰিবলৈ এপ্টোক অনুমতি দিয়ে। এই কার্যই নন মাল্টিকাষ্ট ম\'ডতকৈ অধিক বেটাৰী ব্যৱহাৰ কৰে।"</string>
+ <string name="permdesc_changeWifiMulticastState" product="tv" msgid="1336952358450652595">"কেৱল আপোনাৰ Android TV ডিভাইচটোৱেই নহয়, মাল্টিকাষ্ট ঠিকনাবোৰ ব্যৱহাৰ কৰি এটা ৱাই-ফাই নেটৱর্কত থকা আটাইবোৰ ডিভাইচলৈ পঠিওৱা পেকেট লাভ কৰিবলৈ এপ্টোক অনুমতি দিয়ে। এই কার্যই নন-মাল্টিকাষ্ট ম’ডতকৈ অধিক পাৱাৰ ব্যৱহাৰ কৰে।"</string>
+ <string name="permdesc_changeWifiMulticastState" product="default" msgid="8296627590220222740">"আপোনাৰ ফ\'নৰ লগতে ৱাই-ফাই নেটৱর্কত থকা আটাইবোৰ ডিভাইচলৈ মাল্টিকাষ্ট ঠিকনা ব্যৱহাৰ কৰি পঠিওৱা পেকেট লাভ কৰিবলৈ এপক অনুমতি দিয়ে। এই কার্যই নন-মাল্টিকাষ্ট ম\'ডতকৈ বেটাৰীৰ অধিক চাৰ্জ ব্যৱহাৰ কৰে।"</string>
<string name="permlab_bluetoothAdmin" msgid="6490373569441946064">"ব্লুটুথ ছেটিং এক্সেছ কৰক"</string>
<string name="permdesc_bluetoothAdmin" product="tablet" msgid="5370837055438574863">"স্থানীয় ব্লুটুথ টে\'বলেট কনফিগাৰ কৰিবলৈ আৰু দূৰৱৰ্তী ডিভাইচসমূহৰ সৈতে যোৰা লগাবলৈ আৰু বিচাৰি উলিয়াবলৈ এপটোক অনুমতি দিয়ে।"</string>
<string name="permdesc_bluetoothAdmin" product="tv" msgid="1623992984547014588">"এপ্টোক আপোনাৰ Android TV ডিভাইচটোত ব্লুটুথ কনফিগাৰ কৰিবলৈ আৰু ৰিম’ট ডিভাইচসমূহ বিচাৰি উলিয়াবলৈ আৰু পেয়াৰ কৰিবলৈ অনুমতি দিয়ে।"</string>
@@ -745,7 +745,7 @@
<string name="policydesc_resetPassword" msgid="4626419138439341851">"স্ক্ৰীন লক সলনি কৰক।"</string>
<string name="policylab_forceLock" msgid="7360335502968476434">"স্ক্ৰীনখন লক কৰক"</string>
<string name="policydesc_forceLock" msgid="1008844760853899693">"স্ক্ৰীন কেনেকৈ আৰু কেতিয়া লক হয় সেয়া নিয়ন্ত্ৰণ কৰক।"</string>
- <string name="policylab_wipeData" msgid="1359485247727537311">"সকলো ডেটা মচক"</string>
+ <string name="policylab_wipeData" msgid="1359485247727537311">"আটাইবোৰ ডেটা মচক"</string>
<string name="policydesc_wipeData" product="tablet" msgid="7245372676261947507">"সতৰ্কবাণী প্ৰেৰণ নকৰাকৈয়ে ফেক্টৰী ডেটা ৰিছেট কৰি টেবলেটৰ ডেটা মচক।"</string>
<string name="policydesc_wipeData" product="tv" msgid="513862488950801261">"কোনো সতর্কবার্তা নপঠিওৱাকৈ ফেক্টৰী ডেটা ৰিছেট কৰি আপোনাৰ Android TV ডিভাইচৰ ডেটা মচক।"</string>
<string name="policydesc_wipeData" product="default" msgid="8036084184768379022">"সতৰ্কবাণী প্ৰেৰণ নকৰাকৈয়ে ফেক্টৰী ডেটা ৰিছেট কৰি ফ\'নৰ ডেটা মচক।"</string>
@@ -760,7 +760,7 @@
<string name="policylab_encryptedStorage" msgid="9012936958126670110">"সঞ্চয়াগাৰৰ এনক্ৰিপশ্বন ছেট কৰক"</string>
<string name="policydesc_encryptedStorage" msgid="1102516950740375617">"সঞ্চয় কৰি ৰখা ডেটাক এনক্ৰিপ্ট কৰাৰ প্ৰয়োজন।"</string>
<string name="policylab_disableCamera" msgid="5749486347810162018">"কেমেৰাবোৰ অক্ষম কৰক"</string>
- <string name="policydesc_disableCamera" msgid="3204405908799676104">"সকলো ডিভাইচৰ কেমেৰাবোৰ ব্যৱহাৰ কৰাত বাধা দিয়ক।"</string>
+ <string name="policydesc_disableCamera" msgid="3204405908799676104">"আটাইবোৰ ডিভাইচৰ কেমেৰা ব্যৱহাৰ কৰাত বাধা দিয়ক।"</string>
<string name="policylab_disableKeyguardFeatures" msgid="5071855750149949741">"স্ক্ৰীন লকৰ কিছুমান সুবিধা অক্ষম কৰক"</string>
<string name="policydesc_disableKeyguardFeatures" msgid="6641673177041195957">"স্ক্ৰীন লকৰ কিছুমান সুবিধা ব্যৱহাৰ হোৱাত বাধা দিয়ক।"</string>
<string-array name="phoneTypes">
@@ -897,7 +897,7 @@
<string name="lockscreen_pattern_correct" msgid="8050630103651508582">"শুদ্ধ!"</string>
<string name="lockscreen_pattern_wrong" msgid="2940138714468358458">"আকৌ চেষ্টা কৰক"</string>
<string name="lockscreen_password_wrong" msgid="8605355913868947490">"আকৌ চেষ্টা কৰক"</string>
- <string name="lockscreen_storage_locked" msgid="634993789186443380">"সকলো সুবিধা আৰু ডেটাৰ বাবে আনলক কৰক"</string>
+ <string name="lockscreen_storage_locked" msgid="634993789186443380">"আটাইবোৰ সুবিধা আৰু ডেটাৰ বাবে আনলক কৰক"</string>
<string name="faceunlock_multiple_failures" msgid="681991538434031708">"গৰাকীৰ ফেচ আনলক কৰা সৰ্বাধিক সীমা অতিক্ৰম কৰা হ’ল"</string>
<string name="lockscreen_missing_sim_message_short" msgid="1248431165144893792">"কোনো ছিম কাৰ্ড নাই"</string>
<string name="lockscreen_missing_sim_message" product="tablet" msgid="8596805728510570760">"টে\'বলেটত ছিম কার্ড নাই।"</string>
@@ -926,9 +926,9 @@
<string name="lockscreen_failed_attempts_almost_glogin" product="tablet" msgid="3069635524964070596">"আপুনি অশুদ্ধভাৱে আপোনাৰ লক খোলাৰ আৰ্হিটো <xliff:g id="NUMBER_0">%1$d</xliff:g> বাৰ আঁকিলে৷ <xliff:g id="NUMBER_1">%2$d</xliff:g> তকৈ অধিকবাৰ অসফলভাৱে কৰা প্ৰয়াসৰ পিছত, আপোনাৰ ফ\'নটো আনলক কৰিবৰ বাবে Google ছাইন ইনৰ জৰিয়তে কাৰ্যটো কৰিবলৈ কোৱা হ\'ব৷\n\n <xliff:g id="NUMBER_2">%3$d</xliff:g> ছেকেণ্ডৰ পিছত পুনৰ চেষ্টা কৰক৷"</string>
<string name="lockscreen_failed_attempts_almost_glogin" product="tv" msgid="6399092175942158529">"আপুনি নিজৰ আনলক আৰ্হিটো <xliff:g id="NUMBER_0">%1$d</xliff:g>বাৰ ভুলকৈ দিলে। আকৌ <xliff:g id="NUMBER_1">%2$d</xliff:g>বাৰ ভুলকৈ প্ৰয়াস কৰাৰ পাছত আপোনাক নিজৰ Google ছাইন ইন ব্যৱহাৰ কৰি আপোনাৰ Android TV ডিভাইচটো আনলক কৰিবলৈ কোৱা হ’ব।\n\n <xliff:g id="NUMBER_2">%3$d</xliff:g>ছেকেণ্ডৰ পাছত পুনৰ চেষ্টা কৰক।"</string>
<string name="lockscreen_failed_attempts_almost_glogin" product="default" msgid="5691623136957148335">"আপুনি অশুদ্ধভাৱে আপোনাৰ লক খোলাৰ আৰ্হিটো <xliff:g id="NUMBER_0">%1$d</xliff:g> বাৰ আঁকিলে৷ <xliff:g id="NUMBER_1">%2$d</xliff:g> তকৈ অধিকবাৰ অসফলভাৱে কৰা প্ৰয়াসৰ পিছত, আপোনাৰ ফ\'নটো আনলক কৰিবৰ বাবে Google ছাইন ইনৰ জৰিয়তে কাৰ্যটো কৰিবলৈ কোৱা হ\'ব৷\n\n <xliff:g id="NUMBER_2">%3$d</xliff:g> ছেকেণ্ডৰ পিছত পুনৰ চেষ্টা কৰক৷"</string>
- <string name="lockscreen_failed_attempts_almost_at_wipe" product="tablet" msgid="7914445759242151426">"আপুনি টে\'বলেটটো <xliff:g id="NUMBER_0">%1$d</xliff:g> বাৰ ভুলকৈ আনলক কৰিবলৈ প্ৰয়াস কৰিছে। <xliff:g id="NUMBER_1">%2$d</xliff:g> বাৰতকৈ বেছি প্ৰয়াস কৰিলে টে\'বলেটটো ফেক্টৰী ডিফ\'ল্টলৈ ৰিছেট কৰা হ\'ব আৰু সকলো ব্যৱহাৰকাৰী ডেটা হেৰুৱাব।"</string>
+ <string name="lockscreen_failed_attempts_almost_at_wipe" product="tablet" msgid="7914445759242151426">"আপুনি টে\'বলেটটো <xliff:g id="NUMBER_0">%1$d</xliff:g> বাৰ ভুলকৈ আনলক কৰিবলৈ প্ৰয়াস কৰিছে। <xliff:g id="NUMBER_1">%2$d</xliff:g> বাৰতকৈ বেছি প্ৰয়াস কৰিলে টে\'বলেটটো ফেক্টৰী ডিফ\'ল্টলৈ ৰিছেট কৰা হ\'ব আৰু আটাইবোৰ ব্যৱহাৰকাৰী ডেটা হেৰুৱাব।"</string>
<string name="lockscreen_failed_attempts_almost_at_wipe" product="tv" msgid="4275591249631864248">"আপুনি নিজৰ Android TV ডিভাইচটো আনলক কৰিবলৈ <xliff:g id="NUMBER_0">%1$d</xliff:g>বাৰ ভুলকৈ প্ৰয়াস কৰিছে। <xliff:g id="NUMBER_1">%2$d</xliff:g>তকৈ বেছি বাৰ ভুলকৈ প্ৰয়াস কৰাৰ পাছত আপোনাৰ Android TV ডিভাইচটো ফেক্টৰী ডিফ’ল্টলৈ ৰিছেট কৰা হ’ব আৰু ব্যৱহাৰকাৰীৰ সকলো ডেটা হেৰুৱাব।"</string>
- <string name="lockscreen_failed_attempts_almost_at_wipe" product="default" msgid="1166532464798446579">"আপুনি ফ\'নটো <xliff:g id="NUMBER_0">%1$d</xliff:g> বাৰ ভুলকৈ আনলক কৰিবলৈ প্ৰয়াস কৰিছে। <xliff:g id="NUMBER_1">%2$d</xliff:g> বাৰতকৈ বেছি প্ৰয়াস কৰিলে ফ\'নটো ফেক্টৰী ডিফ\'ল্টলৈ ৰিছেট কৰা হ\'ব আৰু সকলো ব্যৱহাৰকাৰী ডেটা হেৰুৱাব।"</string>
+ <string name="lockscreen_failed_attempts_almost_at_wipe" product="default" msgid="1166532464798446579">"আপুনি ফ\'নটো <xliff:g id="NUMBER_0">%1$d</xliff:g> বাৰ ভুলকৈ আনলক কৰিবলৈ প্ৰয়াস কৰিছে। <xliff:g id="NUMBER_1">%2$d</xliff:g> বাৰতকৈ বেছি প্ৰয়াস কৰিলে ফ\'নটো ফেক্টৰী ডিফ\'ল্টলৈ ৰিছেট কৰা হ\'ব আৰু আটাইবোৰ ব্যৱহাৰকাৰী ডেটা হেৰুৱাব।"</string>
<string name="lockscreen_failed_attempts_now_wiping" product="tablet" msgid="8682445539263683414">"আপুনি অশুদ্ধভাৱে টে\'বলেটটো আনলক কৰিবলৈ <xliff:g id="NUMBER">%d</xliff:g> বাৰ চেষ্টা কৰিছিল। টে\'বলেটটো এতিয়া ফেক্টৰী ডিফ\'ল্টলৈ ৰিছেট কৰা হ\'ব।"</string>
<string name="lockscreen_failed_attempts_now_wiping" product="tv" msgid="2205435033340091883">"আপুনি নিজৰ Android TV ডিভাইচটো আনলক কৰিবলৈ <xliff:g id="NUMBER">%d</xliff:g>বাৰ ভুলকৈ প্ৰয়াস কৰিছে। আপোনাৰ Android TV ডিভাইচটো এতিয়া ফেক্টৰী ডিফ’ল্টলৈ ৰিছেট কৰা হ’ব।"</string>
<string name="lockscreen_failed_attempts_now_wiping" product="default" msgid="2203704707679895487">"আপুনি অশুদ্ধভাৱে ফ\'নটো আনলক কৰিবলৈ <xliff:g id="NUMBER">%d</xliff:g> বাৰ চেষ্টা কৰিছিল। ফ\'নটো এতিয়া ফেক্টৰী ডিফ\'ল্টলৈ ৰিছেট কৰা হ\'ব।"</string>
@@ -1014,7 +1014,7 @@
<string name="autofill_area" msgid="8289022370678448983">"ক্ষেত্ৰ"</string>
<string name="autofill_emirate" msgid="2544082046790551168">"এমিৰেট"</string>
<string name="permlab_readHistoryBookmarks" msgid="9102293913842539697">"আপোনাৰ ৱেব বুকমার্কবোৰ আৰু ইতিহাস পঢ়ক"</string>
- <string name="permdesc_readHistoryBookmarks" msgid="2323799501008967852">"ব্ৰাউজাৰৰ বুকমার্ক আৰু ব্ৰাউজাৰে ব্যৱহাৰ কৰা সকলো URLৰ ইতিহাস পঢ়িবলৈ এপক অনুমতি দিয়ে। টোকা: এই অনুমতি তৃতীয় পক্ষৰ ব্ৰাউজাৰবোৰ বা ৱেব ব্ৰাউজিং কৰিব পৰা অন্য এপ্লিকেশ্বনবোৰৰ দ্বাৰা বলৱৎ নহ\'বও পাৰে।"</string>
+ <string name="permdesc_readHistoryBookmarks" msgid="2323799501008967852">"ব্ৰাউজাৰৰ বুকমার্ক আৰু ব্ৰাউজাৰে ব্যৱহাৰ কৰা আটাইবোৰ URLৰ ইতিহাস পঢ়িবলৈ এপক অনুমতি দিয়ে। টোকা: এই অনুমতি তৃতীয় পক্ষৰ ব্ৰাউজাৰবোৰ বা ৱেব ব্ৰাউজিং কৰিব পৰা অন্য এপ্লিকেশ্বনবোৰৰ দ্বাৰা বলৱৎ নহ\'বও পাৰে।"</string>
<string name="permlab_writeHistoryBookmarks" msgid="6090259925187986937">"আপোনাৰ ৱেব বুকমার্কবোৰ আৰু ইতিহাস লিখক"</string>
<string name="permdesc_writeHistoryBookmarks" product="tablet" msgid="573341025292489065">"আপোনাৰ টেবলেটত সঞ্চয় কৰি ৰখা ব্ৰাউজাৰৰ বুকমার্ক আৰু ব্ৰাউজাৰৰ ইতিহাস সংশোধন কৰিবলৈ এপক অনুমতি দিয়ে। টোকা: এই অনুমতি তৃতীয় পক্ষৰ ব্ৰাউজাৰবোৰ বা ৱেব ব্ৰাউজিং কৰিব পৰা অন্য এপ্লিকেশ্বনবোৰৰ দ্বাৰা বলৱৎ নহ\'বও পাৰে।"</string>
<string name="permdesc_writeHistoryBookmarks" product="tv" msgid="88642768580408561">"এপ্টোক আপোনাৰ Android TV ডিভাইচত ষ্ট’ৰ কৰি ৰখা ব্ৰাউজাৰৰ ইতিহাস আৰু বুকমার্কবোৰ সংশোধন কৰিবলৈ অনুমতি দিয়ে। ব্ৰাউজাৰ ডাটা মোহাৰিবলৈ অথবা সংশোধন কৰিবলৈ ই এপ্টোক অনুমতি দিব পাৰে। টোকা: এই অনুমতি তৃতীয় পক্ষৰ ব্ৰাউজাৰবোৰ অথবা ৱেব ব্ৰাউজিঙৰ ক্ষমতা থকা অন্য এপ্লিকেশ্বনবোৰৰ দ্বাৰা বলৱৎ কৰা নহ’বও পাৰে।"</string>
@@ -1157,7 +1157,7 @@
<string name="Midnight" msgid="8176019203622191377">"মাজনিশা"</string>
<string name="elapsed_time_short_format_mm_ss" msgid="8689459651807876423">"<xliff:g id="MINUTES">%1$02d</xliff:g>:<xliff:g id="SECONDS">%2$02d</xliff:g>"</string>
<string name="elapsed_time_short_format_h_mm_ss" msgid="2302144714803345056">"<xliff:g id="HOURS">%1$d</xliff:g>:<xliff:g id="MINUTES">%2$02d</xliff:g>:<xliff:g id="SECONDS">%3$02d</xliff:g>"</string>
- <string name="selectAll" msgid="1532369154488982046">"সকলো বাছনি কৰক"</string>
+ <string name="selectAll" msgid="1532369154488982046">"আটাইবোৰ বাছনি কৰক"</string>
<string name="cut" msgid="2561199725874745819">"কাটক"</string>
<string name="copy" msgid="5472512047143665218">"প্ৰতিলিপি কৰক"</string>
<string name="failed_to_copy_to_clipboard" msgid="725919885138539875">"ক্লিপব\'ৰ্ডত প্ৰতিলিপি কৰিব পৰা নগ\'ল"</string>
@@ -1619,7 +1619,7 @@
<string name="fingerprints" msgid="148690767172613723">"ফিংগাৰপ্ৰিণ্ট:"</string>
<string name="sha256_fingerprint" msgid="7103976380961964600">"SHA-256 ফিংগাৰপ্ৰিণ্ট:"</string>
<string name="sha1_fingerprint" msgid="2339915142825390774">"SHA-1 ফিংগাৰপ্ৰিণ্ট:"</string>
- <string name="activity_chooser_view_see_all" msgid="3917045206812726099">"সকলো চাওক"</string>
+ <string name="activity_chooser_view_see_all" msgid="3917045206812726099">"আটাইবোৰ চাওক"</string>
<string name="activity_chooser_view_dialog_title_default" msgid="8880731437191978314">"কাৰ্যকলাপ বাছনি কৰক"</string>
<string name="share_action_provider_share_with" msgid="1904096863622941880">"ইয়াৰ জৰিয়তে শ্বেয়াৰ কৰক"</string>
<string name="sending" msgid="206925243621664438">"পঠিয়াই থকা হৈছে…"</string>
@@ -1686,9 +1686,9 @@
<string name="kg_too_many_failed_pin_attempts_dialog_message" msgid="23741434207544038">"আপুনি আপোনাৰ পিন <xliff:g id="NUMBER_0">%1$d</xliff:g>বাৰ ভুলকৈ লিখিছে। \n\n<xliff:g id="NUMBER_1">%2$d</xliff:g>ছেকেণ্ডৰ পিছত আকৌ চেষ্টা কৰক।"</string>
<string name="kg_too_many_failed_password_attempts_dialog_message" msgid="3328686432962224215">"আপুনি আপোনাৰ পাছৱৰ্ড <xliff:g id="NUMBER_0">%1$d</xliff:g>বাৰ ভুলকৈ লিখিছে। \n\n<xliff:g id="NUMBER_1">%2$d</xliff:g> ছেকেণ্ডৰ পিছত আকৌ চেষ্টা কৰক।"</string>
<string name="kg_too_many_failed_pattern_attempts_dialog_message" msgid="7357404233979139075">"আপুনি আপোনাৰ ল\'ক খোলাৰ আৰ্হি <xliff:g id="NUMBER_0">%1$d</xliff:g>বাৰ ভুলকৈ আঁকিছে। \n\n<xliff:g id="NUMBER_1">%2$d</xliff:g>ছেকেণ্ডৰ পিছত আকৌ চেষ্টা কৰক।"</string>
- <string name="kg_failed_attempts_almost_at_wipe" product="tablet" msgid="3479940221343361587">"আপুনি <xliff:g id="NUMBER_0">%1$d</xliff:g>বাৰ ভুলকৈ টেবলেটৰ ল\'ক খোলাৰ প্ৰয়াস কৰিছে। <xliff:g id="NUMBER_1">%2$d</xliff:g>তকৈ বেছি বাৰ ভুল প্ৰয়াস কৰিলে টেবলেটটো ফেক্টৰী ডিফ\'ল্টলৈ ৰিছেট কৰা হ\'ব আৰু সকলো ব্যৱহাৰকাৰীৰ ডেটা হেৰুৱাব।"</string>
- <string name="kg_failed_attempts_almost_at_wipe" product="tv" msgid="9064457748587850217">"আপুনি নিজৰ Android TV ডিভাইচটো আনলক কৰিবলৈ <xliff:g id="NUMBER_0">%1$d</xliff:g>বাৰ ভুলকৈ প্ৰয়াস কৰিছে। <xliff:g id="NUMBER_1">%2$d</xliff:g>তকৈ বেছি বাৰ ভুলকৈ প্ৰয়াস কৰাৰ পাছত আপোনাৰ Android TV ডিভাইচটো ফেক্টৰী ডিফ’ল্টলৈ ৰিছেট কৰা হ’ব আৰু ব্যৱহাৰকাৰীৰ সকলো ডেটা হেৰুৱাব।"</string>
- <string name="kg_failed_attempts_almost_at_wipe" product="default" msgid="5955398963754432548">"আপুনি <xliff:g id="NUMBER_0">%1$d</xliff:g>বাৰ ভুলকৈ ফ\'নৰ ল\'ক খোলাৰ প্ৰয়াস কৰিছে। <xliff:g id="NUMBER_1">%2$d</xliff:g>তকৈ বেছি বাৰ ভুল প্ৰয়াস কৰিলে ফ\'নটো ফেক্টৰী ডিফ\'ল্টলৈ ৰিছেট কৰা হ\'ব আৰু সকলো ব্যৱহাৰকাৰীৰ ডেটা হেৰুৱাব।"</string>
+ <string name="kg_failed_attempts_almost_at_wipe" product="tablet" msgid="3479940221343361587">"আপুনি <xliff:g id="NUMBER_0">%1$d</xliff:g>বাৰ ভুলকৈ টেবলেটৰ ল\'ক খোলাৰ প্ৰয়াস কৰিছে। <xliff:g id="NUMBER_1">%2$d</xliff:g>তকৈ বেছি বাৰ ভুল প্ৰয়াস কৰিলে টেবলেটটো ফেক্টৰী ডিফ\'ল্টলৈ ৰিছেট কৰা হ\'ব আৰু আটাইবোৰ ব্যৱহাৰকাৰীৰ ডেটা হেৰুৱাব।"</string>
+ <string name="kg_failed_attempts_almost_at_wipe" product="tv" msgid="9064457748587850217">"আপুনি নিজৰ Android TV ডিভাইচটো আনলক কৰিবলৈ <xliff:g id="NUMBER_0">%1$d</xliff:g>বাৰ ভুলকৈ প্ৰয়াস কৰিছে। <xliff:g id="NUMBER_1">%2$d</xliff:g>তকৈ বেছি বাৰ ভুলকৈ প্ৰয়াস কৰাৰ পাছত আপোনাৰ Android TV ডিভাইচটো ফেক্টৰী ডিফ’ল্টলৈ ৰিছেট কৰা হ’ব আৰু ব্যৱহাৰকাৰীৰ আটাইবোৰ ডেটা হেৰুৱাব।"</string>
+ <string name="kg_failed_attempts_almost_at_wipe" product="default" msgid="5955398963754432548">"আপুনি <xliff:g id="NUMBER_0">%1$d</xliff:g>বাৰ ভুলকৈ ফ\'নৰ ল\'ক খোলাৰ প্ৰয়াস কৰিছে। <xliff:g id="NUMBER_1">%2$d</xliff:g>তকৈ বেছি বাৰ ভুল প্ৰয়াস কৰিলে ফ\'নটো ফেক্টৰী ডিফ\'ল্টলৈ ৰিছেট কৰা হ\'ব আৰু ব্যৱহাৰকাৰীৰ আটাইবোৰ ডেটা হেৰুৱাব।"</string>
<string name="kg_failed_attempts_now_wiping" product="tablet" msgid="2299099385175083308">"আপুনি <xliff:g id="NUMBER">%d</xliff:g>বাৰ ভুলকৈ টেবলেটৰ ল\'ক খোলাৰ প্ৰয়াস কৰিছে। টেবলেটটো এতিয়া ফেক্টৰী ডিফ\'ল্টলৈ ৰিছেট কৰা হ\'ব।"</string>
<string name="kg_failed_attempts_now_wiping" product="tv" msgid="5045460916106267585">"আপুনি নিজৰ Android TV ডিভাইচটো আনলক কৰিবলৈ <xliff:g id="NUMBER">%d</xliff:g>বাৰ ভুলকৈ প্ৰয়াস কৰিছে। আপোনাৰ Android TV ডিভাইচটো এতিয়া ফেক্টৰী ডিফ’ল্টলৈ ৰিছেট কৰা হ’ব।"</string>
<string name="kg_failed_attempts_now_wiping" product="default" msgid="5043730590446071189">"আপুনি <xliff:g id="NUMBER">%d</xliff:g>বাৰ ভুলকৈ ফ\'নৰ ল\'ক খোলাৰ প্ৰয়াস কৰিছে। ফ\'নটো এতিয়া ফেক্টৰী ডিফ\'ল্টলৈ ৰিছেট কৰা হ\'ব।"</string>
@@ -1982,7 +1982,7 @@
<string name="search_language_hint" msgid="7004225294308793583">"ভাষাৰ নাম লিখক"</string>
<string name="language_picker_section_suggested" msgid="6556199184638990447">"প্ৰস্তাৱিত"</string>
<string name="language_picker_section_all" msgid="1985809075777564284">"সকলো ভাষা"</string>
- <string name="region_picker_section_all" msgid="756441309928774155">"সকলো অঞ্চল"</string>
+ <string name="region_picker_section_all" msgid="756441309928774155">"আটাইবোৰ অঞ্চল"</string>
<string name="locale_search_menu" msgid="6258090710176422934">"সন্ধান কৰক"</string>
<string name="app_suspended_title" msgid="888873445010322650">"এপটো নাই"</string>
<string name="app_suspended_default_message" msgid="6451215678552004172">"এই মুহূৰ্তত <xliff:g id="APP_NAME_0">%1$s</xliff:g> উপলব্ধ নহয়। ইয়াক <xliff:g id="APP_NAME_1">%2$s</xliff:g>এ পৰিচালনা কৰে।"</string>
diff --git a/core/res/res/values-az/strings.xml b/core/res/res/values-az/strings.xml
index e949a53..a6098b8 100644
--- a/core/res/res/values-az/strings.xml
+++ b/core/res/res/values-az/strings.xml
@@ -543,10 +543,8 @@
<string name="permdesc_bluetooth_advertise" product="default" msgid="6085174451034210183">"Tətbiqə yaxınlıqdakı Bluetooth cihazlarında reklam etmək imkanı verir"</string>
<string name="permlab_uwb_ranging" msgid="8141915781475770665">"yaxınlıqdakı Ultra Genişzolaqlı cihazları arasında nisbi mövqeyi təyin etmək"</string>
<string name="permdesc_uwb_ranging" msgid="2519723069604307055">"Tətbiqə yaxınlıqdakı Ultra Genişzolaqlı cihazları arasında nisbi mövqeyi təyin etməyə icazə verin"</string>
- <!-- no translation found for permlab_nearby_wifi_devices (392774237063608500) -->
- <skip />
- <!-- no translation found for permdesc_nearby_wifi_devices (3054307728646332906) -->
- <skip />
+ <string name="permlab_nearby_wifi_devices" msgid="392774237063608500">"yaxınlıqdakı Wi-Fi cihazları ilə əlaqə qurmaq"</string>
+ <string name="permdesc_nearby_wifi_devices" msgid="3054307728646332906">"Tətbiqə yaxınlıqdakı Wi-Fi cihazlarında reklam etmək, onlara qoşulmaq və nisbi mövqeyini təyin etmək icazəsi verir"</string>
<string name="permlab_preferredPaymentInfo" msgid="5274423844767445054">"Tərcih edilən NFC ödəniş xidməti məlumatı"</string>
<string name="permdesc_preferredPaymentInfo" msgid="8583552469807294967">"Tətbiqə qeydiyyatdan keçmiş yardım və marşrut təyinatı kimi tərcih edilən nfc ödəniş xidməti məlumatını əldə etmək icazəsi verir."</string>
<string name="permlab_nfc" msgid="1904455246837674977">"Near Field Communication\'ı kontrol et"</string>
diff --git a/core/res/res/values-bn/strings.xml b/core/res/res/values-bn/strings.xml
index 9f29d8e..5e54b61 100644
--- a/core/res/res/values-bn/strings.xml
+++ b/core/res/res/values-bn/strings.xml
@@ -543,10 +543,8 @@
<string name="permdesc_bluetooth_advertise" product="default" msgid="6085174451034210183">"আশেপাশের ব্লুটুথ ডিভাইস বিজ্ঞাপন দেওয়ার জন্য অ্যাপকে অনুমতি দেয়"</string>
<string name="permlab_uwb_ranging" msgid="8141915781475770665">"আশেপাশের Ultra-Wideband ডিভাইসগুলির আপেক্ষিক অবস্থান নির্ণয় করুন"</string>
<string name="permdesc_uwb_ranging" msgid="2519723069604307055">"অ্যাপকে আশেপাশের Ultra-Wideband ডিভাইসগুলির আপেক্ষিক অবস্থান নির্ণয় করার অনুমতি দিন"</string>
- <!-- no translation found for permlab_nearby_wifi_devices (392774237063608500) -->
- <skip />
- <!-- no translation found for permdesc_nearby_wifi_devices (3054307728646332906) -->
- <skip />
+ <string name="permlab_nearby_wifi_devices" msgid="392774237063608500">"আশপাশের ওয়াই-ফাই ডিভাইসের সাথে ইন্টার্যাক্ট করুন"</string>
+ <string name="permdesc_nearby_wifi_devices" msgid="3054307728646332906">"এটির ফলে অ্যাপ আশপাশের ওয়াই-ফাই ডিভাইসের তথ্য দেখাতে, তাদের সাথে কানেক্ট করতে এবং ত দূরত্বে আছে সেটি জানতে পারবে"</string>
<string name="permlab_preferredPaymentInfo" msgid="5274423844767445054">"পছন্দের NFC পেমেন্ট পরিষেবার তথ্য"</string>
<string name="permdesc_preferredPaymentInfo" msgid="8583552469807294967">"অ্যাপের মাধ্যমে পছন্দসই এনএফসি পেমেন্ট পরিষেবার তথ্য, যেমন রেজিস্ট্রার করার সহায়তা এবং রুট ডেস্টিনেশন সম্পর্কিত তথ্য অ্যাক্সেস করার অনুমতি দেয়।"</string>
<string name="permlab_nfc" msgid="1904455246837674977">"নিয়ার ফিল্ড কমিউনিকেশন নিয়ন্ত্রণ করে"</string>
@@ -730,10 +728,8 @@
<string name="permdesc_access_notification_policy" msgid="8538374112403845013">"অ্যাপটিকে \'বিরক্ত করবে না\' কনফিগারেশন পড়া এবং লেখার অনুমতি দেয়।"</string>
<string name="permlab_startViewPermissionUsage" msgid="1504564328641112341">"দেখার অনুমতি কাজে লাগানো শুরু করুন"</string>
<string name="permdesc_startViewPermissionUsage" msgid="2820325605959586538">"কোনও অ্যাপের কোনও নির্দিষ্ট অনুমতির ব্যবহার শুরু করার ক্ষেত্রে হোল্ডারকে সাহায্য করে। সাধারণ অ্যাপের জন্য এটির পরিবর্তন হওয়ার কথা নয়।"</string>
- <!-- no translation found for permlab_startViewAppFeatures (7955084203185903001) -->
- <skip />
- <!-- no translation found for permdesc_startViewAppFeatures (7207240860165206107) -->
- <skip />
+ <string name="permlab_startViewAppFeatures" msgid="7955084203185903001">"অ্যাপের ফিচার দেখা শুরু করুন"</string>
+ <string name="permdesc_startViewAppFeatures" msgid="7207240860165206107">"কোনও অ্যাপের ফিচার সম্পর্কিত তথ্য দেখা শুরু করতে অনুমতি দেয়।"</string>
<string name="permlab_highSamplingRateSensors" msgid="3941068435726317070">"হাই স্যাম্পলিং রেটে সেন্সর ডেটা অ্যাক্সেস করুন"</string>
<string name="permdesc_highSamplingRateSensors" msgid="8430061978931155995">"200 Hz-এর বেশি রেটে অ্যাপকে স্যাম্পল সেন্সর ডেটার জন্য অনুমতি দিন"</string>
<string name="policylab_limitPassword" msgid="4851829918814422199">"পাসওয়ার্ড নিয়মগুলি সেট করে"</string>
diff --git a/core/res/res/values-cs/strings.xml b/core/res/res/values-cs/strings.xml
index c57d844..4f9e7dc 100644
--- a/core/res/res/values-cs/strings.xml
+++ b/core/res/res/values-cs/strings.xml
@@ -734,10 +734,8 @@
<string name="permdesc_access_notification_policy" msgid="8538374112403845013">"Umožňuje aplikaci číst a zapisovat konfiguraci režimu Nerušit."</string>
<string name="permlab_startViewPermissionUsage" msgid="1504564328641112341">"zahájení zobrazení využití oprávnění"</string>
<string name="permdesc_startViewPermissionUsage" msgid="2820325605959586538">"Umožňuje přístup zahájit využití oprávnění jiné aplikace. Běžné aplikace by toto oprávnění neměly nikdy požadovat."</string>
- <!-- no translation found for permlab_startViewAppFeatures (7955084203185903001) -->
- <skip />
- <!-- no translation found for permdesc_startViewAppFeatures (7207240860165206107) -->
- <skip />
+ <string name="permlab_startViewAppFeatures" msgid="7955084203185903001">"zobrazení informací o funkcích aplikace"</string>
+ <string name="permdesc_startViewAppFeatures" msgid="7207240860165206107">"Umožňuje držiteli zobrazit informace o funkcích aplikace."</string>
<string name="permlab_highSamplingRateSensors" msgid="3941068435726317070">"přístup k datům ze senzorů s vyšší vzorkovací frekvencí"</string>
<string name="permdesc_highSamplingRateSensors" msgid="8430061978931155995">"Umožňuje aplikaci vzorkovat data ze senzorů s frekvencí vyšší než 200 Hz"</string>
<string name="policylab_limitPassword" msgid="4851829918814422199">"Nastavit pravidla pro heslo"</string>
diff --git a/core/res/res/values-es/strings.xml b/core/res/res/values-es/strings.xml
index 4afc20c..5eca42f 100644
--- a/core/res/res/values-es/strings.xml
+++ b/core/res/res/values-es/strings.xml
@@ -728,10 +728,8 @@
<string name="permdesc_access_notification_policy" msgid="8538374112403845013">"Permite que la aplicación lea y modifique la configuración de No molestar."</string>
<string name="permlab_startViewPermissionUsage" msgid="1504564328641112341">"iniciar uso de permiso de visualización"</string>
<string name="permdesc_startViewPermissionUsage" msgid="2820325605959586538">"Permite que el titular inicie el uso de permisos de una aplicación. Las aplicaciones normales no deberían necesitar nunca este permiso."</string>
- <!-- no translation found for permlab_startViewAppFeatures (7955084203185903001) -->
- <skip />
- <!-- no translation found for permdesc_startViewAppFeatures (7207240860165206107) -->
- <skip />
+ <string name="permlab_startViewAppFeatures" msgid="7955084203185903001">"ver funciones de una aplicación"</string>
+ <string name="permdesc_startViewAppFeatures" msgid="7207240860165206107">"Permite que el titular vea la información de las funciones de una aplicación."</string>
<string name="permlab_highSamplingRateSensors" msgid="3941068435726317070">"acceder a datos de sensores a una frecuencia de muestreo alta"</string>
<string name="permdesc_highSamplingRateSensors" msgid="8430061978931155995">"Permite que la aplicación consulte datos de sensores a una frecuencia superior a 200 Hz"</string>
<string name="policylab_limitPassword" msgid="4851829918814422199">"Establecimiento de reglas de contraseña"</string>
diff --git a/core/res/res/values-fr-rCA/strings.xml b/core/res/res/values-fr-rCA/strings.xml
index 56ab0af..e0a5363 100644
--- a/core/res/res/values-fr-rCA/strings.xml
+++ b/core/res/res/values-fr-rCA/strings.xml
@@ -728,10 +728,8 @@
<string name="permdesc_access_notification_policy" msgid="8538374112403845013">"Permet à l\'application de consulter et de modifier la configuration du mode Ne pas déranger."</string>
<string name="permlab_startViewPermissionUsage" msgid="1504564328641112341">"démarrer l\'affichage de l\'usage des autorisations"</string>
<string name="permdesc_startViewPermissionUsage" msgid="2820325605959586538">"Permet au détenteur de démarrer l\'usage des autorisations pour une application. Cette fonctionnalité ne devrait pas être nécessaire pour les applications standards."</string>
- <!-- no translation found for permlab_startViewAppFeatures (7955084203185903001) -->
- <skip />
- <!-- no translation found for permdesc_startViewAppFeatures (7207240860165206107) -->
- <skip />
+ <string name="permlab_startViewAppFeatures" msgid="7955084203185903001">"démarrer l\'affichage des fonctionnalités de l\'application"</string>
+ <string name="permdesc_startViewAppFeatures" msgid="7207240860165206107">"Permet au détenteur de commencer à afficher les renseignements sur les fonctionnalités d\'une application."</string>
<string name="permlab_highSamplingRateSensors" msgid="3941068435726317070">"accéder aux données des capteurs à un taux d’échantillonnage élevé"</string>
<string name="permdesc_highSamplingRateSensors" msgid="8430061978931155995">"Permet à l’application d’échantillonner les données des capteurs à une fréquence supérieure à 200 Hz"</string>
<string name="policylab_limitPassword" msgid="4851829918814422199">"Définir les règles du mot de passe"</string>
diff --git a/core/res/res/values-gl/strings.xml b/core/res/res/values-gl/strings.xml
index 987464a..daa95d1 100644
--- a/core/res/res/values-gl/strings.xml
+++ b/core/res/res/values-gl/strings.xml
@@ -543,10 +543,8 @@
<string name="permdesc_bluetooth_advertise" product="default" msgid="6085174451034210183">"Permite que a aplicación envíe anuncios a dispositivos Bluetooth próximos"</string>
<string name="permlab_uwb_ranging" msgid="8141915781475770665">"determinar posición entre dispositivos próximos"</string>
<string name="permdesc_uwb_ranging" msgid="2519723069604307055">"Permite que a aplicación determine a posición relativa entre os dispositivos próximos que usen banda ultralarga"</string>
- <!-- no translation found for permlab_nearby_wifi_devices (392774237063608500) -->
- <skip />
- <!-- no translation found for permdesc_nearby_wifi_devices (3054307728646332906) -->
- <skip />
+ <string name="permlab_nearby_wifi_devices" msgid="392774237063608500">"interactuar con dispositivos wifi próximos"</string>
+ <string name="permdesc_nearby_wifi_devices" msgid="3054307728646332906">"Permítelle á aplicación enviar anuncios e conectarse a dispositivos wifi próximos, e determinar a súa posición relativa"</string>
<string name="permlab_preferredPaymentInfo" msgid="5274423844767445054">"Información do servizo de pago de NFC preferido"</string>
<string name="permdesc_preferredPaymentInfo" msgid="8583552469807294967">"Permite que a aplicación obteña información do servizo de pago de NFC preferido, como as axudas rexistradas e o destino da ruta."</string>
<string name="permlab_nfc" msgid="1904455246837674977">"controlar Near Field Communication"</string>
diff --git a/core/res/res/values-gu/strings.xml b/core/res/res/values-gu/strings.xml
index 0a2649d..3be53ab 100644
--- a/core/res/res/values-gu/strings.xml
+++ b/core/res/res/values-gu/strings.xml
@@ -728,10 +728,8 @@
<string name="permdesc_access_notification_policy" msgid="8538374112403845013">"એપ્લિકેશનને ખલેલ પાડશો નહીં ગોઠવણી વાંચવા અને લખવાની મંજૂરી આપે છે."</string>
<string name="permlab_startViewPermissionUsage" msgid="1504564328641112341">"પરવાનગી વપરાશ જુઓને શરૂ કરો"</string>
<string name="permdesc_startViewPermissionUsage" msgid="2820325605959586538">"કોઈ ઍપ માટે પરવાનગી વપરાશ શરૂ કરવાની ધારકને મંજૂરી આપે છે. સામાન્ય ઍપ માટે ક્યારેય જરૂર પડી ન શકે."</string>
- <!-- no translation found for permlab_startViewAppFeatures (7955084203185903001) -->
- <skip />
- <!-- no translation found for permdesc_startViewAppFeatures (7207240860165206107) -->
- <skip />
+ <string name="permlab_startViewAppFeatures" msgid="7955084203185903001">"ઍપની સુવિધાઓ જોવા માટેની પરવાનગી ચાલુ કરો"</string>
+ <string name="permdesc_startViewAppFeatures" msgid="7207240860165206107">"ધારકને ઍપ માટેની સુવિધાઓની માહિતી જોવાનું શરૂ કરવાની મંજૂરી આપે છે."</string>
<string name="permlab_highSamplingRateSensors" msgid="3941068435726317070">"ઉચ્ચ સેમ્પ્લિંગ રેટ પર સેન્સરનો ડેટા ઍક્સેસ કરો"</string>
<string name="permdesc_highSamplingRateSensors" msgid="8430061978931155995">"ઍપને 200 Hzથી વધુના દરે સેન્સરના ડેટાના નમૂનાની મંજૂરી આપે છે"</string>
<string name="policylab_limitPassword" msgid="4851829918814422199">"પાસવર્ડ નિયમો સેટ કરો"</string>
diff --git a/core/res/res/values-hr/strings.xml b/core/res/res/values-hr/strings.xml
index 5f276c3..3dfbd06 100644
--- a/core/res/res/values-hr/strings.xml
+++ b/core/res/res/values-hr/strings.xml
@@ -731,10 +731,8 @@
<string name="permdesc_access_notification_policy" msgid="8538374112403845013">"Omogućuje aplikaciji čitanje i pisanje konfiguracije opcije Ne uznemiravaj."</string>
<string name="permlab_startViewPermissionUsage" msgid="1504564328641112341">"pokrenuti upotrebu dopuštenja za pregled"</string>
<string name="permdesc_startViewPermissionUsage" msgid="2820325605959586538">"Dopušta nositelju pokretanje upotrebe dopuštenja za aplikaciju. Ne bi smjelo biti potrebno za uobičajene aplikacije."</string>
- <!-- no translation found for permlab_startViewAppFeatures (7955084203185903001) -->
- <skip />
- <!-- no translation found for permdesc_startViewAppFeatures (7207240860165206107) -->
- <skip />
+ <string name="permlab_startViewAppFeatures" msgid="7955084203185903001">"pokretanje prikaza značajki aplikacije"</string>
+ <string name="permdesc_startViewAppFeatures" msgid="7207240860165206107">"Dopušta nositelju pokretanje prikaza informacija o značajkama aplikacije."</string>
<string name="permlab_highSamplingRateSensors" msgid="3941068435726317070">"pristup podacima senzora pri višoj brzini uzorkovanja"</string>
<string name="permdesc_highSamplingRateSensors" msgid="8430061978931155995">"Aplikaciji omogućuje uzorkovanje podataka senzora pri brzini većoj od 200 Hz"</string>
<string name="policylab_limitPassword" msgid="4851829918814422199">"Postavi pravila zaporke"</string>
diff --git a/core/res/res/values-hu/strings.xml b/core/res/res/values-hu/strings.xml
index a0f8eac..22de5eb 100644
--- a/core/res/res/values-hu/strings.xml
+++ b/core/res/res/values-hu/strings.xml
@@ -728,10 +728,8 @@
<string name="permdesc_access_notification_policy" msgid="8538374112403845013">"Az alkalmazás olvashatja és szerkesztheti a „Ne zavarjanak” funkció beállításait."</string>
<string name="permlab_startViewPermissionUsage" msgid="1504564328641112341">"engedélyhasználat megtekintésének elindítása"</string>
<string name="permdesc_startViewPermissionUsage" msgid="2820325605959586538">"Lehetővé teszi a felhasználó számára, hogy elindítsa az alkalmazás engedélyhasználatát. A normál alkalmazásoknak erre soha nincs szükségük."</string>
- <!-- no translation found for permlab_startViewAppFeatures (7955084203185903001) -->
- <skip />
- <!-- no translation found for permdesc_startViewAppFeatures (7207240860165206107) -->
- <skip />
+ <string name="permlab_startViewAppFeatures" msgid="7955084203185903001">"alkalmazásfunkciók megtekintésének megkezdése"</string>
+ <string name="permdesc_startViewAppFeatures" msgid="7207240860165206107">"Engedélyezi az alkalmazás számára, hogy megkezdje az alkalmazások funkcióira vonatkozó adatok megtekintését."</string>
<string name="permlab_highSamplingRateSensors" msgid="3941068435726317070">"hozzáférés a szenzoradatokhoz nagy mintavételezési gyakorisággal"</string>
<string name="permdesc_highSamplingRateSensors" msgid="8430061978931155995">"Lehetővé teszi az alkalmazás számára, hogy 200 Hz-nél magasabb gyakorisággal vegyen mintát a szenzoradatokból"</string>
<string name="policylab_limitPassword" msgid="4851829918814422199">"Jelszavakkal kapcsolatos szabályok beállítása"</string>
diff --git a/core/res/res/values-kk/strings.xml b/core/res/res/values-kk/strings.xml
index 05da5fd..48bc9cb 100644
--- a/core/res/res/values-kk/strings.xml
+++ b/core/res/res/values-kk/strings.xml
@@ -543,10 +543,8 @@
<string name="permdesc_bluetooth_advertise" product="default" msgid="6085174451034210183">"Қолданба жарнаманы маңайдағы Bluetooth құрылғыларына бере алады."</string>
<string name="permlab_uwb_ranging" msgid="8141915781475770665">"маңайдағы кең жолақты құрылғылардың бір-біріне қатысты орнын анықтау"</string>
<string name="permdesc_uwb_ranging" msgid="2519723069604307055">"Қолданбаға маңайдағы кең жолақты құрылғылардың бір-біріне қатысты орнын анықтауға мүмкіндік береді."</string>
- <!-- no translation found for permlab_nearby_wifi_devices (392774237063608500) -->
- <skip />
- <!-- no translation found for permdesc_nearby_wifi_devices (3054307728646332906) -->
- <skip />
+ <string name="permlab_nearby_wifi_devices" msgid="392774237063608500">"маңайдағы Wi-Fi құрылғыларымен байланысу"</string>
+ <string name="permdesc_nearby_wifi_devices" msgid="3054307728646332906">"Қолданба маңайдағы Wi‑Fi құрылғыларына жарнама беріп, оларға қосылып, шамамен орналасқан жерін анықтай алады."</string>
<string name="permlab_preferredPaymentInfo" msgid="5274423844767445054">"Таңдаулы NFC төлеу қызметі туралы ақпарат"</string>
<string name="permdesc_preferredPaymentInfo" msgid="8583552469807294967">"Қолданба тіркелген көмектер және баратын жер маршруты сияқты таңдаулы NFC төлеу қызметі туралы ақпаратты ала алатын болады."</string>
<string name="permlab_nfc" msgid="1904455246837674977">"NFC функциясын басқару"</string>
diff --git a/core/res/res/values-kn/strings.xml b/core/res/res/values-kn/strings.xml
index 89a5043..180d7fc 100644
--- a/core/res/res/values-kn/strings.xml
+++ b/core/res/res/values-kn/strings.xml
@@ -728,10 +728,8 @@
<string name="permdesc_access_notification_policy" msgid="8538374112403845013">"ಅಡಚಣೆ ಮಾಡಬೇಡಿ ಕಾನ್ಫಿಗರೇಶನ್ ಅನ್ನು ಓದಲು ಮತ್ತು ಬರೆಯಲು ಅಪ್ಲಿಕೇಶನ್ಗೆ ಅನುಮತಿಸುತ್ತದೆ."</string>
<string name="permlab_startViewPermissionUsage" msgid="1504564328641112341">"ವೀಕ್ಷಣಾ ಅನುಮತಿಯ ಬಳಕೆಯನ್ನು ಪ್ರಾರಂಭಿಸಿ"</string>
<string name="permdesc_startViewPermissionUsage" msgid="2820325605959586538">"ಆ್ಯಪ್ಗಾಗಿ ಅನುಮತಿ ಬಳಕೆಯನ್ನು ಪ್ರಾರಂಭಿಸಲು ಹೊಂದಿರುವವರಿಗೆ ಅನುಮತಿಸುತ್ತದೆ. ಸಾಮಾನ್ಯ ಆ್ಯಪ್ಗಳಿಗೆ ಎಂದಿಗೂ ಅಗತ್ಯವಿರುವುದಿಲ್ಲ."</string>
- <!-- no translation found for permlab_startViewAppFeatures (7955084203185903001) -->
- <skip />
- <!-- no translation found for permdesc_startViewAppFeatures (7207240860165206107) -->
- <skip />
+ <string name="permlab_startViewAppFeatures" msgid="7955084203185903001">"ಆ್ಯಪ್ ವೈಶಿಷ್ಟ್ಯಗಳನ್ನು ವೀಕ್ಷಿಸಲು ಪ್ರಾರಂಭಿಸಿ"</string>
+ <string name="permdesc_startViewAppFeatures" msgid="7207240860165206107">"ಆ್ಯಪ್ನ ವೈಶಿಷ್ಟ್ಯಗಳ ಮಾಹಿತಿಯನ್ನು ವೀಕ್ಷಿಸಲು ಬಳಕೆದಾರರನ್ನು ಅನುಮತಿಸುತ್ತದೆ."</string>
<string name="permlab_highSamplingRateSensors" msgid="3941068435726317070">"ಹೆಚ್ಚಿನ ನಮೂನೆ ದರದಲ್ಲಿ ಸೆನ್ಸಾರ್ ಡೇಟಾ ಪ್ರವೇಶಿಸಿ"</string>
<string name="permdesc_highSamplingRateSensors" msgid="8430061978931155995">"200 Hz ಗಿಂತಲೂ ಹೆಚ್ಚಿನ ವೇಗದಲ್ಲಿ ಸೆನ್ಸಾರ್ ಡೇಟಾದ ಮಾದರಿ ಪರೀಕ್ಷಿಸಲು ಆ್ಯಪ್ಗೆ ಅನುಮತಿಸಿ"</string>
<string name="policylab_limitPassword" msgid="4851829918814422199">"ಪಾಸ್ವರ್ಡ್ ನಿಮಯಗಳನ್ನು ಹೊಂದಿಸಿ"</string>
diff --git a/core/res/res/values-ko/strings.xml b/core/res/res/values-ko/strings.xml
index 5c4c93c..9c5ded9 100644
--- a/core/res/res/values-ko/strings.xml
+++ b/core/res/res/values-ko/strings.xml
@@ -989,7 +989,7 @@
<string name="js_dialog_title" msgid="7464775045615023241">"\'<xliff:g id="TITLE">%s</xliff:g>\' 페이지 내용:"</string>
<string name="js_dialog_title_default" msgid="3769524569903332476">"자바스크립트"</string>
<string name="js_dialog_before_unload_title" msgid="7012587995876771246">"탐색 확인"</string>
- <string name="js_dialog_before_unload_positive_button" msgid="4274257182303565509">"이 페이지 닫기"</string>
+ <string name="js_dialog_before_unload_positive_button" msgid="4274257182303565509">"이 페이지 나가기"</string>
<string name="js_dialog_before_unload_negative_button" msgid="3873765747622415310">"이 페이지에 머무르기"</string>
<string name="js_dialog_before_unload" msgid="7213364985774778744">"<xliff:g id="MESSAGE">%s</xliff:g>\n\n다른 페이지로 이동하시겠습니까?"</string>
<string name="save_password_label" msgid="9161712335355510035">"확인"</string>
diff --git a/core/res/res/values-land/dimens.xml b/core/res/res/values-land/dimens.xml
index ca549ae..f1e5888 100644
--- a/core/res/res/values-land/dimens.xml
+++ b/core/res/res/values-land/dimens.xml
@@ -27,8 +27,6 @@
<dimen name="password_keyboard_spacebar_vertical_correction">2dip</dimen>
<dimen name="preference_widget_width">72dp</dimen>
- <!-- Height of the status bar -->
- <dimen name="status_bar_height">@dimen/status_bar_height_landscape</dimen>
<!-- Height of area above QQS where battery/time go -->
<dimen name="quick_qs_offset_height">48dp</dimen>
<!-- Default height of an action bar. -->
diff --git a/core/res/res/values-ml/strings.xml b/core/res/res/values-ml/strings.xml
index 95f3fa1..7768d2f 100644
--- a/core/res/res/values-ml/strings.xml
+++ b/core/res/res/values-ml/strings.xml
@@ -728,10 +728,8 @@
<string name="permdesc_access_notification_policy" msgid="8538374112403845013">"\'ശല്യപ്പെടുത്തരുത്\' കോൺഫിഗറേഷൻ വായിക്കുന്നതിനും എഴുതുന്നതിനും ആപ്പിനെ അനുവദിക്കുന്നു."</string>
<string name="permlab_startViewPermissionUsage" msgid="1504564328641112341">"അനുമതി ഉപയോഗം കാണാൻ ആരംഭിക്കുക"</string>
<string name="permdesc_startViewPermissionUsage" msgid="2820325605959586538">"ഒരു ആപ്പിനുള്ള അനുമതി ഉപയോഗം ആരംഭിക്കാൻ ഹോൾഡറിനെ അനുവദിക്കുന്നു. സാധാരണ ആപ്പുകൾക്ക് ഒരിക്കലും ആവശ്യമില്ല."</string>
- <!-- no translation found for permlab_startViewAppFeatures (7955084203185903001) -->
- <skip />
- <!-- no translation found for permdesc_startViewAppFeatures (7207240860165206107) -->
- <skip />
+ <string name="permlab_startViewAppFeatures" msgid="7955084203185903001">"ആപ്പ് ഫീച്ചറുകൾ കാണാൻ ആരംഭിക്കുക"</string>
+ <string name="permdesc_startViewAppFeatures" msgid="7207240860165206107">"ആപ്പിനുള്ള ഫീച്ചറുകളുടെ വിവരങ്ങൾ കാണാൻ ആരംഭിക്കാൻ ഹോൾഡറിനെ അനുവദിക്കുന്നു."</string>
<string name="permlab_highSamplingRateSensors" msgid="3941068435726317070">"ഉയർന്ന സാംപ്ലിംഗ് റേറ്റിൽ സെൻസർ ഡാറ്റ ആക്സസ് ചെയ്യുക"</string>
<string name="permdesc_highSamplingRateSensors" msgid="8430061978931155995">"200 Hz-നേക്കാൾ ഉയർന്ന റേറ്റിൽ സെൻസർ ഡാറ്റ സാമ്പിൾ ചെയ്യാൻ ആപ്പിനെ അനുവദിക്കുന്നു"</string>
<string name="policylab_limitPassword" msgid="4851829918814422199">"പാസ്വേഡ് നിയമങ്ങൾ സജ്ജീകരിക്കുക"</string>
diff --git a/core/res/res/values-mr/strings.xml b/core/res/res/values-mr/strings.xml
index a57f60d..07cb06d 100644
--- a/core/res/res/values-mr/strings.xml
+++ b/core/res/res/values-mr/strings.xml
@@ -728,10 +728,8 @@
<string name="permdesc_access_notification_policy" msgid="8538374112403845013">"व्यत्यय आणू नका कॉंफिगरेशन वाचण्यासाठी आणि लिहिण्यासाठी ॲपला अनुमती देते."</string>
<string name="permlab_startViewPermissionUsage" msgid="1504564328641112341">"व्ह्यू परवानगी वापर सुरू करा"</string>
<string name="permdesc_startViewPermissionUsage" msgid="2820325605959586538">"धारकास अॅपसाठी परवानगी वापरणे सुरू करण्याची अनुमती देते. सामान्य अॅप्ससाठी कधीही आवश्यकता नसते."</string>
- <!-- no translation found for permlab_startViewAppFeatures (7955084203185903001) -->
- <skip />
- <!-- no translation found for permdesc_startViewAppFeatures (7207240860165206107) -->
- <skip />
+ <string name="permlab_startViewAppFeatures" msgid="7955084203185903001">"ॲप वैशिष्ट्ये पाहणे सुरू करा"</string>
+ <string name="permdesc_startViewAppFeatures" msgid="7207240860165206107">"होल्डरला ॲपसाठी वैशिष्ट्यांची माहिती पाहण्यास सुरू करण्याची अनुमती देते."</string>
<string name="permlab_highSamplingRateSensors" msgid="3941068435726317070">"उच्च नमुना दराने सेन्सर डेटा अॅक्सेस करते"</string>
<string name="permdesc_highSamplingRateSensors" msgid="8430061978931155995">"ॲपला २०० Hz पेक्षा जास्त दराने सेन्सर डेटाचा नमुना तयार करण्याची अनुमती देते"</string>
<string name="policylab_limitPassword" msgid="4851829918814422199">"पासवर्ड नियम सेट करा"</string>
diff --git a/core/res/res/values-my/strings.xml b/core/res/res/values-my/strings.xml
index 6874414..8d2c0d5 100644
--- a/core/res/res/values-my/strings.xml
+++ b/core/res/res/values-my/strings.xml
@@ -48,7 +48,7 @@
<string name="invalidPin" msgid="7542498253319440408">"နံပါတ်(၄)ခုမှ(၈)ခုအထိပါရှိသော ပင်နံပါတ်အားထည့်ပါ"</string>
<string name="invalidPuk" msgid="8831151490931907083">"နံပါတ်(၈)ခုသို့မဟုတ် ထိုထက်ရှည်သောသော PUKအားထည့်သွင်းပါ"</string>
<string name="needPuk" msgid="7321876090152422918">"ဆင်းမ်ကတ် ရဲ့ ပင်နံပါတ် ပြန်ဖွင့်သည့် ကုဒ် သော့ကျနေပါသည်။ ဖွင့်ရန် ကုဒ်အားထည့်သွင်းပါ။"</string>
- <string name="needPuk2" msgid="7032612093451537186">"ဆင်းမ်ကဒ်အားမပိတ်ရန် PUK2အားထည့်သွင်းပါ"</string>
+ <string name="needPuk2" msgid="7032612093451537186">"ဆင်းမ်ကတ်အားမပိတ်ရန် PUK2 အားထည့်သွင်းပါ"</string>
<string name="enablePin" msgid="2543771964137091212">"မအောင်မြင်ပါ, SIM/RUIM သော့ကို အရင် သုံးခွင့်ပြုရန်"</string>
<plurals name="pinpuk_attempts" formatted="false" msgid="1619867269012213584">
<item quantity="other">ဆင်းမ်ကတ် သော့မချခင် သင့်တွင် <xliff:g id="NUMBER_1">%d</xliff:g> ခါ ကြိုးစားခွင့်များကျန်ပါသေးသည်။</item>
@@ -333,7 +333,7 @@
<string name="capability_title_canRequestTouchExploration" msgid="327598364696316213">"တို့ထိခြင်းဖြင့် ရှာဖွေမှုကို ဖွင့်ရန်"</string>
<string name="capability_desc_canRequestTouchExploration" msgid="4394677060796752976">"တို့လိုက်သည့်အရာများကို အသံထွက်ဖတ်ပေးပါလိမ့်မည်။ လက်ဟန်အမူအရာများကို အသုံးပြု၍ မျက်နှာပြင်ကို လေ့လာနိုင်ပါသည်။"</string>
<string name="capability_title_canRequestFilterKeyEvents" msgid="2772371671541753254">"ရိုက်သောစာများကို စောင့်ကြည့်ရန်"</string>
- <string name="capability_desc_canRequestFilterKeyEvents" msgid="2381315802405773092">"ကိုယ်ရေးအချက်အလက်များဖြစ်သော ခရက်ဒစ်ကဒ်နံပါတ်နှင့် စကားဝှက်များ ပါဝင်သည်။"</string>
+ <string name="capability_desc_canRequestFilterKeyEvents" msgid="2381315802405773092">"ကိုယ်ရေးအချက်အလက်များဖြစ်သော ခရက်ဒစ်ကတ်နံပါတ်နှင့် စကားဝှက်များ ပါဝင်သည်။"</string>
<string name="capability_title_canControlMagnification" msgid="7701572187333415795">"မျက်နှာပြင် ချဲ့ခြင်းကို ထိန်းချုပ်ရန်"</string>
<string name="capability_desc_canControlMagnification" msgid="2206586716709254805">"မျက်နှာပြင် ဇူးမ်အရွယ်နှင့် နေရာချထားခြင်းကို ထိန်းချုပ်ပါသည်။"</string>
<string name="capability_title_canPerformGestures" msgid="9106545062106728987">"လက်ဟန်များ အသုံးပြုပါ"</string>
@@ -899,13 +899,13 @@
<string name="lockscreen_password_wrong" msgid="8605355913868947490">"ထပ် စမ်းပါ"</string>
<string name="lockscreen_storage_locked" msgid="634993789186443380">"ဝန်ဆောင်မှုနှင့် ဒေတာအားလုံးအတွက် လော့ခ်ဖွင့်ပါ"</string>
<string name="faceunlock_multiple_failures" msgid="681991538434031708">"မျက်မှာပြ လော့ခ်ဖွင့်ခြင်း ခွင့်ပြုသော အကြိမ်ရေထက် ကျော်လွန်သွားပါပြီ"</string>
- <string name="lockscreen_missing_sim_message_short" msgid="1248431165144893792">"ဆင်းကဒ် မရှိပါ"</string>
- <string name="lockscreen_missing_sim_message" product="tablet" msgid="8596805728510570760">"တက်ပလက်ထဲတွင်း ဆင်းကဒ် မရှိပါ"</string>
+ <string name="lockscreen_missing_sim_message_short" msgid="1248431165144893792">"ဆင်းမ်ကတ် မရှိပါ"</string>
+ <string name="lockscreen_missing_sim_message" product="tablet" msgid="8596805728510570760">"တက်ဘလက်ထဲတွင်း ဆင်းမ်ကတ်မရှိပါ"</string>
<string name="lockscreen_missing_sim_message" product="tv" msgid="2582768023352171073">"သင့် Android TV စက်ပစ္စည်းပေါ်တွင် ဆင်းမ်ကတ်မရှိပါ။"</string>
- <string name="lockscreen_missing_sim_message" product="default" msgid="1408695081255172556">"ဖုန်းထဲတွင် ဆင်းကဒ် မရှိပါ"</string>
+ <string name="lockscreen_missing_sim_message" product="default" msgid="1408695081255172556">"ဖုန်းထဲတွင် ဆင်းကတ်မရှိပါ"</string>
<string name="lockscreen_missing_sim_instructions" msgid="8473601862688263903">"ဆင်းမ်ကတ် ထည့်ပါ"</string>
<string name="lockscreen_missing_sim_instructions_long" msgid="3664999892038416334">"ဆင်းမ်ကတ် မရှိဘူး သို့မဟုတ် ဖတ်မရပါ။ ဆင်းမ်ကတ် တစ်ခုကို ထည့်ပါ။"</string>
- <string name="lockscreen_permanent_disabled_sim_message_short" msgid="3812893366715730539">"သုံးစွဲ မရတော့သော ဆင်းကဒ်"</string>
+ <string name="lockscreen_permanent_disabled_sim_message_short" msgid="3812893366715730539">"သုံး၍ မရတော့သော ဆင်းမ်ကတ်"</string>
<string name="lockscreen_permanent_disabled_sim_instructions" msgid="4358929052509450807">"သင့် ဆင်းမ်ကတ်ကို ထာဝရ ပိတ်လိုက်ပါပြီ။\n နောက် ဆင်းမ်ကတ် တစ်ခု အတွက် သင်၏ ကြိုးမဲ့ ဝန်ဆောင်မှု စီမံပေးသူကို ဆက်သွယ်ပါ"</string>
<string name="lockscreen_transport_prev_description" msgid="2879469521751181478">"ယခင် တစ်ပုဒ်"</string>
<string name="lockscreen_transport_next_description" msgid="2931509904881099919">"နောက် တစ်ပုဒ်"</string>
@@ -1349,8 +1349,8 @@
<string name="sms_short_code_remember_undo_instruction" msgid="2620984439143080410">"နောင်တွင် ဆက်တင် > အပလီကေးရှင်းများ မှပြောင်းနိုင်သည်"</string>
<string name="sms_short_code_confirm_always_allow" msgid="2223014893129755950">"အမြဲခွင့်ပြုရန်"</string>
<string name="sms_short_code_confirm_never_allow" msgid="2688828813521652079">"ဘယ်တော့မှခွင့်မပြုပါ"</string>
- <string name="sim_removed_title" msgid="5387212933992546283">"SIMကဒ်ဖယ်ရှားခြင်း"</string>
- <string name="sim_removed_message" msgid="9051174064474904617">"သတ်မှတ်ထားသောဆင်းမ်ကဒ်ဖြင့် ပြန်လည်ဖွင့်သည့်အထိ မိုဘိုင်းကွန်ယက်ရရှိမည်မဟုတ်ပါ"</string>
+ <string name="sim_removed_title" msgid="5387212933992546283">"SIM ကတ်ဖယ်ရှားခြင်း"</string>
+ <string name="sim_removed_message" msgid="9051174064474904617">"သတ်မှတ်ထားသောဆင်းမ်ကတ်ဖြင့် ပြန်လည်ဖွင့်သည့်အထိ မိုဘိုင်းကွန်ရက်ရရှိမည်မဟုတ်ပါ"</string>
<string name="sim_done_button" msgid="6464250841528410598">"ပြီးပါပြီ"</string>
<string name="sim_added_title" msgid="7930779986759414595">"ဆင်းမ်ကတ် ထည့်ပါသည်"</string>
<string name="sim_added_message" msgid="6602906609509958680">"မိုးဘိုင်းကွန်ရက်ကို ဆက်သွယ်ရန် စက်ကို ပြန် စ ပါ"</string>
@@ -2055,7 +2055,7 @@
<string name="autofill_continue_yes" msgid="7914985605534510385">"ရှေ့ဆက်ရန်"</string>
<string name="autofill_save_type_password" msgid="5624528786144539944">"စကားဝှက်"</string>
<string name="autofill_save_type_address" msgid="3111006395818252885">"လိပ်စာ"</string>
- <string name="autofill_save_type_credit_card" msgid="3583795235862046693">"ခရက်တစ်ကတ်"</string>
+ <string name="autofill_save_type_credit_card" msgid="3583795235862046693">"ခရက်ဒစ်ကတ်"</string>
<string name="autofill_save_type_debit_card" msgid="3169397504133097468">"ဒက်ဘစ် ကတ်"</string>
<string name="autofill_save_type_payment_card" msgid="6555012156728690856">"ငွေပေးချေမှုကတ်"</string>
<string name="autofill_save_type_generic_card" msgid="1019367283921448608">"ကတ်"</string>
diff --git a/core/res/res/values-ne/strings.xml b/core/res/res/values-ne/strings.xml
index c6f3826..b741507 100644
--- a/core/res/res/values-ne/strings.xml
+++ b/core/res/res/values-ne/strings.xml
@@ -728,10 +728,8 @@
<string name="permdesc_access_notification_policy" msgid="8538374112403845013">"बाधा नपुर्याउँनुहोस् कन्फिगरेसन पढ्न र लेख्नको लागि एपलाई अनुमति दिनुहोस्।"</string>
<string name="permlab_startViewPermissionUsage" msgid="1504564328641112341">"हेर्ने अनुमतिको प्रयोग सुरु गर्नुहोस्"</string>
<string name="permdesc_startViewPermissionUsage" msgid="2820325605959586538">"वाहकलाई कुनै एपसम्बन्धी अनुमतिको प्रयोग सुरु गर्न दिन्छ। साधारण एपहरूलाई कहिल्यै आवश्यक नपर्नु पर्ने हो।"</string>
- <!-- no translation found for permlab_startViewAppFeatures (7955084203185903001) -->
- <skip />
- <!-- no translation found for permdesc_startViewAppFeatures (7207240860165206107) -->
- <skip />
+ <string name="permlab_startViewAppFeatures" msgid="7955084203185903001">"एपका सुविधासम्बन्धी जानकारी हेर्न थाल्नुहोस्"</string>
+ <string name="permdesc_startViewAppFeatures" msgid="7207240860165206107">"होल्डरलाई एपका सुविधासम्बन्धी जानकारी हेर्न दिन्छ।"</string>
<string name="permlab_highSamplingRateSensors" msgid="3941068435726317070">"नमुना लिने उच्च दरमा सेन्सरसम्बन्धी डेटा प्रयोग गर्ने"</string>
<string name="permdesc_highSamplingRateSensors" msgid="8430061978931155995">"यो अनुमति दिइएमा एपले २०० हर्जभन्दा बढी दरमा सेन्सरसम्बन्धी डेटाको नमुना लिन सक्छ"</string>
<string name="policylab_limitPassword" msgid="4851829918814422199">"पासवर्ड नियमहरू मिलाउनुहोस्"</string>
diff --git a/core/res/res/values-or/strings.xml b/core/res/res/values-or/strings.xml
index cc368a0..29aea5e 100644
--- a/core/res/res/values-or/strings.xml
+++ b/core/res/res/values-or/strings.xml
@@ -728,10 +728,8 @@
<string name="permdesc_access_notification_policy" msgid="8538374112403845013">"\"ବିରକ୍ତ କରନ୍ତୁ ନାହିଁ\" କନଫିଗରେଶନ୍ ପଢ଼ିବା ତଥା ଲେଖିବା ପାଇଁ ଆପକୁ ଅନୁମତି ଦେଇଥାଏ।"</string>
<string name="permlab_startViewPermissionUsage" msgid="1504564328641112341">"ଅନୁମତି ବ୍ୟବହାର ଦେଖିବା ଆରମ୍ଭ କରନ୍ତୁ"</string>
<string name="permdesc_startViewPermissionUsage" msgid="2820325605959586538">"ଏକ ଆପ୍ ପାଇଁ ଅନୁମତିର ବ୍ୟବହାର ଆରମ୍ଭ କରିବାକୁ ଧାରକକୁ ଅନୁମତି ଦେଇଥାଏ। ସାଧାରଣ ଆପ୍ଗୁଡ଼ିକ ପାଇଁ ଏହା ଆବଶ୍ୟକ ନୁହେଁ।"</string>
- <!-- no translation found for permlab_startViewAppFeatures (7955084203185903001) -->
- <skip />
- <!-- no translation found for permdesc_startViewAppFeatures (7207240860165206107) -->
- <skip />
+ <string name="permlab_startViewAppFeatures" msgid="7955084203185903001">"ଆପର ଫିଚରଗୁଡ଼ିକୁ ଦେଖିବା ଆରମ୍ଭ କରନ୍ତୁ"</string>
+ <string name="permdesc_startViewAppFeatures" msgid="7207240860165206107">"କୌଣସି ଆପ ପାଇଁ ଫିଚରଗୁଡ଼ିକ ବିଷୟରେ ସୂଚନା ଦେଖିବା ଆରମ୍ଭ କରିବାକୁ ହୋଲଡରଙ୍କୁ ଅନୁମତି ଦିଏ।"</string>
<string name="permlab_highSamplingRateSensors" msgid="3941068435726317070">"ଏକ ଉଚ୍ଚ ନମୁନାକରଣ ରେଟରେ ସେନ୍ସର୍ ଡାଟାକୁ ଆକ୍ସେସ୍ କରନ୍ତୁ"</string>
<string name="permdesc_highSamplingRateSensors" msgid="8430061978931155995">"200 Hz ଠାରୁ ଅଧିକ ଏକ ରେଟରେ ସେନ୍ସର୍ ଡାଟାର ନମୁନା ନେବା ପାଇଁ ଆପକୁ ଅନୁମତି ଦିଏ"</string>
<string name="policylab_limitPassword" msgid="4851829918814422199">"ପାସ୍ୱର୍ଡ ନିୟମାବଳୀ ସେଟ୍ କରନ୍ତୁ"</string>
diff --git a/core/res/res/values-pa/strings.xml b/core/res/res/values-pa/strings.xml
index 9090830..a619f18 100644
--- a/core/res/res/values-pa/strings.xml
+++ b/core/res/res/values-pa/strings.xml
@@ -226,9 +226,9 @@
<string name="reboot_to_update_title" msgid="2125818841916373708">"Android ਸਿਸਟਮ ਅੱਪਡੇਟ"</string>
<string name="reboot_to_update_prepare" msgid="6978842143587422365">"ਅੱਪਡੇਟ ਦੀ ਤਿਆਰੀ ਕਰ ਰਿਹਾ ਹੈ…"</string>
<string name="reboot_to_update_package" msgid="4644104795527534811">"ਅੱਪਡੇਟ ਪੈਕੇਜ ਦੀ ਕਾਰਵਾਈ ਕਰ ਰਿਹਾ ਹੈ..."</string>
- <string name="reboot_to_update_reboot" msgid="4474726009984452312">"ਰੀਸਟਾਰਟ ਹੋ ਰਿਹਾ ਹੈ…"</string>
+ <string name="reboot_to_update_reboot" msgid="4474726009984452312">"ਮੁੜ-ਸ਼ੁਰੂ ਹੋ ਰਿਹਾ ਹੈ…"</string>
<string name="reboot_to_reset_title" msgid="2226229680017882787">"ਫੈਕਟਰੀ ਡਾਟਾ ਰੀਸੈੱਟ"</string>
- <string name="reboot_to_reset_message" msgid="3347690497972074356">"ਰੀਸਟਾਰਟ ਹੋ ਰਿਹਾ ਹੈ…"</string>
+ <string name="reboot_to_reset_message" msgid="3347690497972074356">"ਮੁੜ-ਸ਼ੁਰੂ ਹੋ ਰਿਹਾ ਹੈ…"</string>
<string name="shutdown_progress" msgid="5017145516412657345">"ਬੰਦ ਹੋ ਰਿਹਾ ਹੈ…"</string>
<string name="shutdown_confirm" product="tablet" msgid="2872769463279602432">"ਤੁਹਾਡਾ ਟੈਬਲੈੱਟ ਬੰਦ ਕੀਤਾ ਜਾਵੇਗਾ।"</string>
<string name="shutdown_confirm" product="tv" msgid="7975942887313518330">"ਤੁਹਾਡਾ Android TV ਡੀਵਾਈਸ ਜਲਦ ਬੰਦ ਕੀਤਾ ਜਾਵੇਗਾ।"</string>
@@ -543,10 +543,8 @@
<string name="permdesc_bluetooth_advertise" product="default" msgid="6085174451034210183">"ਐਪ ਨੂੰ ਨਜ਼ਦੀਕੀ ਬਲੂਟੁੱਥ ਡੀਵਾਈਸਾਂ \'ਤੇ ਵਿਗਿਆਪਨ ਦੇਣ ਦੀ ਇਜਾਜ਼ਤ ਦਿੱਤੀ ਜਾਂਦੀ ਹੈ"</string>
<string name="permlab_uwb_ranging" msgid="8141915781475770665">"ਨਜ਼ਦੀਕੀ ਅਲਟ੍ਰਾ-ਵਾਈਡਬੈਂਡ ਡੀਵਾਈਸਾਂ ਵਿਚਾਲੇ ਸੰਬੰਧਿਤ ਸਥਿਤੀ ਨਿਰਧਾਰਿਤ ਕਰੋ"</string>
<string name="permdesc_uwb_ranging" msgid="2519723069604307055">"ਐਪ ਨੂੰ ਨਜ਼ਦੀਕੀ ਅਲਟ੍ਰਾ-ਵਾਈਡਬੈਂਡ ਡੀਵਾਈਸਾਂ ਦੇ ਵਿਚਾਲੇ ਸੰਬੰਧਿਤ ਸਥਿਤੀ ਨੂੰ ਨਿਰਧਾਰਿਤ ਕਰਨ ਦੀ ਇਜਾਜ਼ਤ ਦਿਓ"</string>
- <!-- no translation found for permlab_nearby_wifi_devices (392774237063608500) -->
- <skip />
- <!-- no translation found for permdesc_nearby_wifi_devices (3054307728646332906) -->
- <skip />
+ <string name="permlab_nearby_wifi_devices" msgid="392774237063608500">"ਨਜ਼ਦੀਕੀ ਵਾਈ-ਫਾਈ ਡੀਵਾਈਸਾਂ ਨਾਲ ਅੰਤਰਕਿਰਿਆ ਕਰੋ"</string>
+ <string name="permdesc_nearby_wifi_devices" msgid="3054307728646332906">"ਐਪ ਨੂੰ ਨਜ਼ਦੀਕੀ ਵਾਈ-ਫਾਈ ਡੀਵਾਈਸਾਂ \'ਤੇ ਵਿਗਿਆਪਨ ਦੇਣ, ਕਨੈਕਟ ਕਰਨ ਅਤੇ ਉਨ੍ਹਾਂ ਦੀ ਸੰਬੰਧਿਤ ਸਥਿਤੀ ਨੂੰ ਨਿਰਧਾਰਿਤ ਕਰਨ ਦੀ ਆਗਿਆ ਦਿੱਤੀ ਜਾਂਦੀ ਹੈ"</string>
<string name="permlab_preferredPaymentInfo" msgid="5274423844767445054">"ਤਰਜੀਹੀ NFC ਭੁਗਤਾਨਸ਼ੁਦਾ ਸੇਵਾ ਜਾਣਕਾਰੀ"</string>
<string name="permdesc_preferredPaymentInfo" msgid="8583552469807294967">"ਐਪ ਨੂੰ ਤਰਜੀਹੀ NFC ਭੁਗਤਾਨਸ਼ੁਦਾ ਸੇਵਾ ਜਾਣਕਾਰੀ ਪ੍ਰਾਪਤ ਕਰਨ ਦਿੰਦਾ ਹੈ ਜਿਵੇਂ ਕਿ ਰਜਿਸਟਰ ਕੀਤੇ ਸਾਧਨ ਅਤੇ ਮੰਜ਼ਿਲ ਰਸਤਾ।"</string>
<string name="permlab_nfc" msgid="1904455246837674977">"ਨਜ਼ਦੀਕੀ ਖੇਤਰ ਸੰਚਾਰ ਤੇ ਨਿਯੰਤਰਣ ਪਾਓ"</string>
@@ -730,10 +728,8 @@
<string name="permdesc_access_notification_policy" msgid="8538374112403845013">"ਐਪ ਨੂੰ ਪਰੇਸ਼ਾਨ ਨਾ ਕਰੋ ਕੌਂਫਿਗਰੇਸ਼ਨ ਨੂੰ ਪੜ੍ਹਨ ਅਤੇ ਲਿਖਣ ਦੀ ਆਗਿਆ ਦਿੰਦਾ ਹੈ।"</string>
<string name="permlab_startViewPermissionUsage" msgid="1504564328641112341">"ਇਜਾਜ਼ਤ ਵਰਤੋਂ ਦੇਖਣਾ ਸ਼ੁਰੂ ਕਰੋ"</string>
<string name="permdesc_startViewPermissionUsage" msgid="2820325605959586538">"ਧਾਰਕ ਨੂੰ ਕਿਸੇ ਹੋਰ ਐਪ ਲਈ ਇਜਾਜ਼ਤ ਵਰਤੋਂ ਨੂੰ ਸ਼ੁਰੂ ਕਰਨ ਦਿੰਦਾ ਹੈ। ਸਧਾਰਨ ਐਪਾਂ ਲਈ ਕਦੇ ਵੀ ਲੋੜੀਂਦਾ ਨਹੀਂ ਹੋਵੇਗਾ।"</string>
- <!-- no translation found for permlab_startViewAppFeatures (7955084203185903001) -->
- <skip />
- <!-- no translation found for permdesc_startViewAppFeatures (7207240860165206107) -->
- <skip />
+ <string name="permlab_startViewAppFeatures" msgid="7955084203185903001">"ਐਪ ਦੀਆਂ ਵਿਸ਼ੇਸ਼ਤਾਵਾਂ ਨੂੰ ਦੇਖਣਾ ਸ਼ੁਰੂ ਕਰੋ"</string>
+ <string name="permdesc_startViewAppFeatures" msgid="7207240860165206107">"ਇਸ ਨਾਲ ਹੋਲਡਰ ਨੂੰ ਕਿਸੇ ਐਪ ਦੀਆਂ ਵਿਸ਼ੇਸ਼ਤਾਵਾਂ ਬਾਰੇ ਜਾਣਕਾਰੀ ਦੇਖਣ ਦੀ ਆਗਿਆ ਮਿਲਦੀ ਹੈ।"</string>
<string name="permlab_highSamplingRateSensors" msgid="3941068435726317070">"ਉੱਚ ਸੈਂਪਲਿੰਗ ਰੇਟ \'ਤੇ ਸੈਂਸਰ ਡਾਟਾ ਤੱਕ ਪਹੁੰਚ ਕਰੋ"</string>
<string name="permdesc_highSamplingRateSensors" msgid="8430061978931155995">"ਐਪ ਨੂੰ 200 Hz ਤੋਂ ਵੱਧ ਦੀ ਦਰ \'ਤੇ ਸੈਂਸਰ ਡਾਟੇ ਦਾ ਨਮੂਨਾ ਲੈਣ ਦੀ ਆਗਿਆ ਦਿੰਦਾ ਹੈ"</string>
<string name="policylab_limitPassword" msgid="4851829918814422199">"ਪਾਸਵਰਡ ਨਿਯਮ ਸੈੱਟ ਕਰੋ"</string>
diff --git a/core/res/res/values-sv/strings.xml b/core/res/res/values-sv/strings.xml
index 357f98a..2220931 100644
--- a/core/res/res/values-sv/strings.xml
+++ b/core/res/res/values-sv/strings.xml
@@ -728,10 +728,8 @@
<string name="permdesc_access_notification_policy" msgid="8538374112403845013">"Ger appen läs- och skrivbehörighet till konfigurationen för Stör ej."</string>
<string name="permlab_startViewPermissionUsage" msgid="1504564328641112341">"börja visa behörighetsanvändningen"</string>
<string name="permdesc_startViewPermissionUsage" msgid="2820325605959586538">"Gör att innehavaren kan öppna behörighetsanvändning för en app. Ska inte behövas för vanliga appar."</string>
- <!-- no translation found for permlab_startViewAppFeatures (7955084203185903001) -->
- <skip />
- <!-- no translation found for permdesc_startViewAppFeatures (7207240860165206107) -->
- <skip />
+ <string name="permlab_startViewAppFeatures" msgid="7955084203185903001">"börja visa appfunktioner"</string>
+ <string name="permdesc_startViewAppFeatures" msgid="7207240860165206107">"Tillåter att innehavaren börjar visa information om funktioner för en app."</string>
<string name="permlab_highSamplingRateSensors" msgid="3941068435726317070">"åtkomst till sensordata med en hög samplingsfrekvens"</string>
<string name="permdesc_highSamplingRateSensors" msgid="8430061978931155995">"Tillåter att appen får åtkomst till sensordata med en högre samplingsfrekvens än 200 Hz"</string>
<string name="policylab_limitPassword" msgid="4851829918814422199">"Ange lösenordsregler"</string>
diff --git a/core/res/res/values-vi/strings.xml b/core/res/res/values-vi/strings.xml
index 052a658..1367485 100644
--- a/core/res/res/values-vi/strings.xml
+++ b/core/res/res/values-vi/strings.xml
@@ -1026,7 +1026,7 @@
<string name="permlab_writeGeolocationPermissions" msgid="8605631647492879449">"sửa đổi các quyền về vị trí địa lý của Trình duyệt"</string>
<string name="permdesc_writeGeolocationPermissions" msgid="5817346421222227772">"Cho phép ứng dụng sửa đổi cấp phép vị trí địa lý của Trình duyệt. Ứng dụng độc hại có thể lợi dụng quyền này để cho phép gửi thông tin vị trí tới các trang web tùy ý."</string>
<string name="save_password_message" msgid="2146409467245462965">"Bạn có muốn trình duyệt nhớ mật khẩu này không?"</string>
- <string name="save_password_notnow" msgid="2878327088951240061">"Không phải bây giờ"</string>
+ <string name="save_password_notnow" msgid="2878327088951240061">"Để sau"</string>
<string name="save_password_remember" msgid="6490888932657708341">"Nhớ"</string>
<string name="save_password_never" msgid="6776808375903410659">"Chưa bao giờ"</string>
<string name="open_permission_deny" msgid="5136793905306987251">"Bạn không được phép mở trang này."</string>
diff --git a/core/res/res/values-zh-rTW/strings.xml b/core/res/res/values-zh-rTW/strings.xml
index d7db7ed..6df610c 100644
--- a/core/res/res/values-zh-rTW/strings.xml
+++ b/core/res/res/values-zh-rTW/strings.xml
@@ -543,10 +543,8 @@
<string name="permdesc_bluetooth_advertise" product="default" msgid="6085174451034210183">"允許應用程式向附近的藍牙裝置廣播"</string>
<string name="permlab_uwb_ranging" msgid="8141915781475770665">"判斷附近超寬頻裝置間的相對位置"</string>
<string name="permdesc_uwb_ranging" msgid="2519723069604307055">"允許應用程式判斷附近超寬頻裝置間的相對位置"</string>
- <!-- no translation found for permlab_nearby_wifi_devices (392774237063608500) -->
- <skip />
- <!-- no translation found for permdesc_nearby_wifi_devices (3054307728646332906) -->
- <skip />
+ <string name="permlab_nearby_wifi_devices" msgid="392774237063608500">"與鄰近的 Wi-Fi 裝置互動"</string>
+ <string name="permdesc_nearby_wifi_devices" msgid="3054307728646332906">"允許應用程式向鄰近的 Wi-Fi 裝置廣播、與這些裝置連線,並能判斷這些裝置的相對位置"</string>
<string name="permlab_preferredPaymentInfo" msgid="5274423844767445054">"首選 NFC 付費服務資訊"</string>
<string name="permdesc_preferredPaymentInfo" msgid="8583552469807294967">"允許應用程式取得首選 NFC 付費服務資訊,例如已註冊的輔助工具和路線目的地。"</string>
<string name="permlab_nfc" msgid="1904455246837674977">"控制近距離無線通訊"</string>
@@ -990,7 +988,7 @@
<string name="factorytest_reboot" msgid="2050147445567257365">"重新開機"</string>
<string name="js_dialog_title" msgid="7464775045615023241">"「<xliff:g id="TITLE">%s</xliff:g>」網頁指出:"</string>
<string name="js_dialog_title_default" msgid="3769524569903332476">"JavaScript"</string>
- <string name="js_dialog_before_unload_title" msgid="7012587995876771246">"確認瀏覽"</string>
+ <string name="js_dialog_before_unload_title" msgid="7012587995876771246">"確認離開網頁"</string>
<string name="js_dialog_before_unload_positive_button" msgid="4274257182303565509">"離開這一頁"</string>
<string name="js_dialog_before_unload_negative_button" msgid="3873765747622415310">"停留在這一頁"</string>
<string name="js_dialog_before_unload" msgid="7213364985774778744">"<xliff:g id="MESSAGE">%s</xliff:g>\n\n你確定要前往其他網頁瀏覽嗎?"</string>
diff --git a/core/res/res/values/attrs.xml b/core/res/res/values/attrs.xml
index 765495a..06333e1 100644
--- a/core/res/res/values/attrs.xml
+++ b/core/res/res/values/attrs.xml
@@ -1984,6 +1984,22 @@
<enum name="KEYCODE_THUMBS_UP" value="286" />
<enum name="KEYCODE_THUMBS_DOWN" value="287" />
<enum name="KEYCODE_PROFILE_SWITCH" value="288" />
+ <enum name="KEYCODE_VIDEO_APP_1" value="289" />
+ <enum name="KEYCODE_VIDEO_APP_2" value="290" />
+ <enum name="KEYCODE_VIDEO_APP_3" value="291" />
+ <enum name="KEYCODE_VIDEO_APP_4" value="292" />
+ <enum name="KEYCODE_VIDEO_APP_5" value="293" />
+ <enum name="KEYCODE_VIDEO_APP_6" value="294" />
+ <enum name="KEYCODE_VIDEO_APP_7" value="295" />
+ <enum name="KEYCODE_VIDEO_APP_8" value="296" />
+ <enum name="KEYCODE_FEATURED_APP_1" value="297" />
+ <enum name="KEYCODE_FEATURED_APP_2" value="298" />
+ <enum name="KEYCODE_FEATURED_APP_3" value="299" />
+ <enum name="KEYCODE_FEATURED_APP_4" value="300" />
+ <enum name="KEYCODE_DEMO_APP_1" value="301" />
+ <enum name="KEYCODE_DEMO_APP_2" value="302" />
+ <enum name="KEYCODE_DEMO_APP_3" value="303" />
+ <enum name="KEYCODE_DEMO_APP_4" value="304" />
</attr>
<!-- ***************************************************************** -->
diff --git a/core/res/res/values/config.xml b/core/res/res/values/config.xml
index 74ce8f2..fceb951 100644
--- a/core/res/res/values/config.xml
+++ b/core/res/res/values/config.xml
@@ -4697,6 +4697,9 @@
only. The component must be part of a system app. -->
<string name="config_defaultSupervisionProfileOwnerComponent" translatable="false"></string>
+ <!-- The package name of the default supervision package. -->
+ <string name="config_systemSupervision" translatable="false"></string>
+
<!-- Trigger a warning for notifications with RemoteView objects that are larger in bytes than
this value (default 1MB)-->
<integer name="config_notificationWarnRemoteViewSizeBytes">2000000</integer>
@@ -5280,6 +5283,11 @@
to 0, the seconds hand will be disabled. -->
<integer name="config_defaultAnalogClockSecondsHandFps">1</integer>
+ <!-- List of shared library packages that should be loaded by the classloader after the
+ code and resources provided by applications. This value will be set by the manufacturer -->
+ <string-array name="config_sharedLibrariesLoadedAfterApp" translatable="false">
+ </string-array>
+
<!-- the number of the max cached processes in the system. -->
<integer name="config_customizedMaxCachedProcesses">32</integer>
diff --git a/core/res/res/values/dimens.xml b/core/res/res/values/dimens.xml
index 45201a9..c40ec4f 100644
--- a/core/res/res/values/dimens.xml
+++ b/core/res/res/values/dimens.xml
@@ -39,15 +39,21 @@
<!-- Elevation of toast view -->
<dimen name="toast_elevation">2dp</dimen>
- <!-- Height of the status bar -->
- <dimen name="status_bar_height">@dimen/status_bar_height_portrait</dimen>
- <!-- Height of the status bar in portrait. The height should be
- Max((status bar content height + waterfall top size), top cutout size) -->
- <dimen name="status_bar_height_portrait">24dp</dimen>
- <!-- Height of the status bar in landscape. The height should be
- Max((status bar content height + waterfall top size), top cutout size) -->
+ <!-- Height of the status bar.
+ Do not read this dimen directly. Use {@link SystemBarUtils#getStatusBarHeight} instead.
+ -->
+ <dimen name="status_bar_height">24dp</dimen>
+ <!-- Height of the status bar in portrait.
+ Do not read this dimen directly. Use {@link SystemBarUtils#getStatusBarHeight} instead.
+ -->
+ <dimen name="status_bar_height_portrait">@dimen/status_bar_height</dimen>
+ <!-- Height of the status bar in landscape.
+ Do not read this dimen directly. Use {@link SystemBarUtils#getStatusBarHeight} instead.
+ -->
<dimen name="status_bar_height_landscape">@dimen/status_bar_height_portrait</dimen>
- <!-- Height of area above QQS where battery/time go -->
+ <!-- Height of area above QQS where battery/time go.
+ Do not read this dimen directly. Use {@link SystemBarUtils#getQuickQsOffsetHeight} instead.
+ -->
<dimen name="quick_qs_offset_height">48dp</dimen>
<!-- Height of the bottom navigation / system bar. -->
<dimen name="navigation_bar_height">48dp</dimen>
diff --git a/core/res/res/values/dimens_car.xml b/core/res/res/values/dimens_car.xml
index 36f1edb..c5dddb8 100644
--- a/core/res/res/values/dimens_car.xml
+++ b/core/res/res/values/dimens_car.xml
@@ -17,7 +17,7 @@
-->
<resources>
<dimen name="car_large_avatar_size">96dp</dimen>
- <dimen name="car_large_avatar_badge_size">32dp</dimen>
+ <dimen name="car_large_avatar_badge_size">24dp</dimen>
<!-- Application Bar -->
<dimen name="car_app_bar_height">80dp</dimen>
<!-- Margin -->
diff --git a/core/res/res/values/public.xml b/core/res/res/values/public.xml
index ed49fe4..366dccb 100644
--- a/core/res/res/values/public.xml
+++ b/core/res/res/values/public.xml
@@ -3315,7 +3315,9 @@
<staging-public-group type="style" first-id="0x0dfd0000">
</staging-public-group>
- <staging-public-group type="string" first-id="0x0dfc0000">
+ <staging-public-group type="string" first-id="0x01dc0000">
+ <!-- @hide @SystemApi -->
+ <public name="config_systemSupervision" />
</staging-public-group>
<staging-public-group type="dimen" first-id="0x01db0000">
diff --git a/core/res/res/values/symbols.xml b/core/res/res/values/symbols.xml
index 846ec60..f166b73 100644
--- a/core/res/res/values/symbols.xml
+++ b/core/res/res/values/symbols.xml
@@ -4559,6 +4559,10 @@
<java-symbol type="bool" name="config_volumeShowRemoteSessions" />
+ <!-- List of shared library packages that should be loaded by the classloader after the
+ code and resources provided by applications. -->
+ <java-symbol type="array" name="config_sharedLibrariesLoadedAfterApp" />
+
<java-symbol type="integer" name="config_customizedMaxCachedProcesses" />
<java-symbol type="color" name="overview_background"/>
diff --git a/core/res/res/xml/sms_short_codes.xml b/core/res/res/xml/sms_short_codes.xml
index a65de91..205c517 100644
--- a/core/res/res/xml/sms_short_codes.xml
+++ b/core/res/res/xml/sms_short_codes.xml
@@ -105,6 +105,9 @@
http://www.tja.ee/public/documents/Elektrooniline_side/Oigusaktid/ENG/Estonian_Numbering_Plan_annex_06_09_2010.mht -->
<shortcode country="ee" pattern="1\\d{2,4}" premium="90\\d{5}|15330|1701[0-3]" free="116\\d{3}|95034" />
+ <!-- Egypt: 4 digits, known codes listed -->
+ <shortcode country="eg" pattern="\\d{4}" free="1499" />
+
<!-- Spain: 5-6 digits: 25xxx, 27xxx, 280xx, 35xxx, 37xxx, 795xxx, 797xxx, 995xxx, 997xxx, plus EU.
http://www.legallink.es/?q=en/content/which-current-regulatory-status-premium-rate-services-spain -->
<shortcode country="es" premium="[23][57]\\d{3}|280\\d{2}|[79]9[57]\\d{3}" free="116\\d{3}|22791|222145|22189" />
@@ -196,7 +199,7 @@
<shortcode country="nl" pattern="\\d{4}" premium="4466|5040" free="116\\d{3}|2223|6225|2223|1662" />
<!-- Nigeria -->
- <shortcode country="ng" pattern="\\d{1,5}" free="2441|55019" />
+ <shortcode country="ng" pattern="\\d{1,5}" free="2441|55020" />
<!-- Norway: 4-5 digits (not confirmed), known premium codes listed -->
<shortcode country="no" pattern="\\d{4,5}" premium="2201|222[67]" free="2171" />
diff --git a/core/tests/batterystatstests/BatteryStatsViewer/src/com/android/frameworks/core/batterystatsviewer/BatteryConsumerData.java b/core/tests/batterystatstests/BatteryStatsViewer/src/com/android/frameworks/core/batterystatsviewer/BatteryConsumerData.java
index 0c7218e..eb378b9 100644
--- a/core/tests/batterystatstests/BatteryStatsViewer/src/com/android/frameworks/core/batterystatsviewer/BatteryConsumerData.java
+++ b/core/tests/batterystatstests/BatteryStatsViewer/src/com/android/frameworks/core/batterystatsviewer/BatteryConsumerData.java
@@ -34,7 +34,9 @@
enum EntryType {
UID_TOTAL_POWER,
UID_POWER_MODELED,
+ UID_POWER_MODELED_PROCESS_STATE,
UID_POWER_MEASURED,
+ UID_POWER_MEASURED_PROCESS_STATE,
UID_POWER_CUSTOM,
UID_DURATION,
DEVICE_TOTAL_POWER,
@@ -135,10 +137,16 @@
requestedBatteryConsumer.getConsumedPower(component),
totalPowerByComponentMah[component]
);
+ addProcessStateEntries(metricTitle, EntryType.UID_POWER_MEASURED_PROCESS_STATE,
+ requestedBatteryConsumer, component
+ );
addEntry(metricTitle + " (modeled)", EntryType.UID_POWER_MODELED,
requestedModeledBatteryConsumer.getConsumedPower(component),
totalModeledPowerByComponentMah[component]
);
+ addProcessStateEntries(metricTitle, EntryType.UID_POWER_MODELED_PROCESS_STATE,
+ requestedModeledBatteryConsumer, component
+ );
}
}
@@ -164,6 +172,33 @@
batteryConsumerId, context.getPackageManager());
}
+ private void addProcessStateEntries(String metricTitle, EntryType entryType,
+ BatteryConsumer batteryConsumer, int component) {
+ final BatteryConsumer.Key[] keys = batteryConsumer.getKeys(component);
+ if (keys == null || keys.length <= 1) {
+ return;
+ }
+
+ for (BatteryConsumer.Key key : keys) {
+ String label;
+ switch (key.processState) {
+ case BatteryConsumer.PROCESS_STATE_FOREGROUND:
+ label = "foreground";
+ break;
+ case BatteryConsumer.PROCESS_STATE_BACKGROUND:
+ label = "background";
+ break;
+ case BatteryConsumer.PROCESS_STATE_FOREGROUND_SERVICE:
+ label = "FGS";
+ break;
+ default:
+ continue;
+ }
+ addEntry(metricTitle + " \u2022 " + label, entryType,
+ batteryConsumer.getConsumedPower(key), 0);
+ }
+ }
+
private void populateForAggregateBatteryConsumer(Context context,
List<BatteryUsageStats> batteryUsageStatsList) {
BatteryUsageStats batteryUsageStats = batteryUsageStatsList.get(0);
diff --git a/core/tests/batterystatstests/BatteryStatsViewer/src/com/android/frameworks/core/batterystatsviewer/BatteryStatsViewerActivity.java b/core/tests/batterystatstests/BatteryStatsViewer/src/com/android/frameworks/core/batterystatsviewer/BatteryStatsViewerActivity.java
index 33ce6bf..0f45c3b 100644
--- a/core/tests/batterystatstests/BatteryStatsViewer/src/com/android/frameworks/core/batterystatsviewer/BatteryStatsViewerActivity.java
+++ b/core/tests/batterystatstests/BatteryStatsViewer/src/com/android/frameworks/core/batterystatsviewer/BatteryStatsViewerActivity.java
@@ -138,12 +138,14 @@
final BatteryUsageStatsQuery queryDefault =
new BatteryUsageStatsQuery.Builder()
.includePowerModels()
+ .includeProcessStateData()
.setMaxStatsAgeMs(maxStatsAgeMs)
.build();
final BatteryUsageStatsQuery queryPowerProfileModeledOnly =
new BatteryUsageStatsQuery.Builder()
.powerProfileModeledOnly()
.includePowerModels()
+ .includeProcessStateData()
.setMaxStatsAgeMs(maxStatsAgeMs)
.build();
return mBatteryStatsManager.getBatteryUsageStats(
@@ -290,6 +292,13 @@
setPowerText(viewHolder.value1TextView, entry.value1);
setProportionText(viewHolder.value2TextView, entry);
break;
+ case UID_POWER_MODELED_PROCESS_STATE:
+ setTitleIconAndBackground(viewHolder, " " + entry.title,
+ R.drawable.gm_calculate_24,
+ R.color.battery_consumer_bg_power_profile);
+ setPowerText(viewHolder.value1TextView, entry.value1);
+ viewHolder.value2TextView.setVisibility(View.INVISIBLE);
+ break;
case UID_POWER_MEASURED:
setTitleIconAndBackground(viewHolder, entry.title,
R.drawable.gm_amp_24,
@@ -297,6 +306,13 @@
setPowerText(viewHolder.value1TextView, entry.value1);
setProportionText(viewHolder.value2TextView, entry);
break;
+ case UID_POWER_MEASURED_PROCESS_STATE:
+ setTitleIconAndBackground(viewHolder, " " + entry.title,
+ R.drawable.gm_amp_24,
+ R.color.battery_consumer_bg_measured_energy);
+ setPowerText(viewHolder.value1TextView, entry.value1);
+ viewHolder.value2TextView.setVisibility(View.INVISIBLE);
+ break;
case UID_POWER_CUSTOM:
setTitleIconAndBackground(viewHolder, entry.title,
R.drawable.gm_custom_24,
diff --git a/core/tests/bluetoothtests/Android.bp b/core/tests/bluetoothtests/Android.bp
index a2e4dff..68416dd 100644
--- a/core/tests/bluetoothtests/Android.bp
+++ b/core/tests/bluetoothtests/Android.bp
@@ -15,7 +15,10 @@
"android.test.runner",
"android.test.base",
],
- static_libs: ["junit"],
+ static_libs: [
+ "junit",
+ "modules-utils-bytesmatcher",
+ ],
platform_apis: true,
certificate: "platform",
}
diff --git a/core/tests/bluetoothtests/src/android/bluetooth/le/ScanRecordTest.java b/core/tests/bluetoothtests/src/android/bluetooth/le/ScanRecordTest.java
index c287ea9..4e817d4 100644
--- a/core/tests/bluetoothtests/src/android/bluetooth/le/ScanRecordTest.java
+++ b/core/tests/bluetoothtests/src/android/bluetooth/le/ScanRecordTest.java
@@ -16,11 +16,11 @@
package android.bluetooth.le;
-import android.os.BytesMatcher;
import android.os.ParcelUuid;
import android.test.suitebuilder.annotation.SmallTest;
import com.android.internal.util.HexDump;
+import com.android.modules.utils.BytesMatcher;
import junit.framework.TestCase;
diff --git a/core/tests/coretests/src/android/net/SntpClientTest.java b/core/tests/coretests/src/android/net/SntpClientTest.java
index b400b9b..ba7df1e 100644
--- a/core/tests/coretests/src/android/net/SntpClientTest.java
+++ b/core/tests/coretests/src/android/net/SntpClientTest.java
@@ -26,6 +26,7 @@
import android.net.sntp.Duration64;
import android.net.sntp.Timestamp64;
+import android.platform.test.annotations.Presubmit;
import android.util.Log;
import androidx.test.runner.AndroidJUnit4;
@@ -49,6 +50,7 @@
import java.util.Random;
import java.util.function.Supplier;
+@Presubmit
@RunWith(AndroidJUnit4.class)
public class SntpClientTest {
private static final String TAG = "SntpClientTest";
diff --git a/core/tests/coretests/src/android/net/sntp/Duration64Test.java b/core/tests/coretests/src/android/net/sntp/Duration64Test.java
index 60b69f6..b228596 100644
--- a/core/tests/coretests/src/android/net/sntp/Duration64Test.java
+++ b/core/tests/coretests/src/android/net/sntp/Duration64Test.java
@@ -21,6 +21,8 @@
import static org.junit.Assert.assertNotEquals;
import static org.junit.Assert.assertTrue;
+import android.platform.test.annotations.Presubmit;
+
import androidx.test.runner.AndroidJUnit4;
import org.junit.Test;
@@ -31,6 +33,7 @@
import java.time.LocalDateTime;
import java.time.ZoneOffset;
+@Presubmit
@RunWith(AndroidJUnit4.class)
public class Duration64Test {
diff --git a/core/tests/coretests/src/android/net/sntp/Timestamp64Test.java b/core/tests/coretests/src/android/net/sntp/Timestamp64Test.java
index 1b1c500..200c80e 100644
--- a/core/tests/coretests/src/android/net/sntp/Timestamp64Test.java
+++ b/core/tests/coretests/src/android/net/sntp/Timestamp64Test.java
@@ -21,6 +21,8 @@
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;
+import android.platform.test.annotations.Presubmit;
+
import androidx.test.runner.AndroidJUnit4;
import org.junit.Test;
@@ -31,6 +33,7 @@
import java.util.Random;
import java.util.Set;
+@Presubmit
@RunWith(AndroidJUnit4.class)
public class Timestamp64Test {
diff --git a/core/tests/coretests/src/android/os/BundleTest.java b/core/tests/coretests/src/android/os/BundleTest.java
index ddd0070..09f4840 100644
--- a/core/tests/coretests/src/android/os/BundleTest.java
+++ b/core/tests/coretests/src/android/os/BundleTest.java
@@ -273,16 +273,21 @@
Parcelable p1 = new CustomParcelable(13, "Tiramisu");
Parcelable p2 = new CustomParcelable(13, "Tiramisu");
Bundle a = new Bundle();
- a.putParcelable("key", p1);
+ a.putParcelable("key1", p1);
a.readFromParcel(getParcelledBundle(a));
a.setClassLoader(getClass().getClassLoader());
Bundle b = new Bundle();
- b.putParcelable("key", p2);
+ // Adding extra element so that the position of the elements of interest in their respective
+ // source parcels are different so we can cover that case of Parcel.compareData(). We'll
+ // remove the element later so the map is equal.
+ b.putString("key0", "string");
+ b.putParcelable("key1", p2);
b.readFromParcel(getParcelledBundle(b));
b.setClassLoader(getClass().getClassLoader());
- // 2 lazy values with identical parcels inside
a.isEmpty();
b.isEmpty();
+ b.remove("key0");
+ // 2 lazy values with identical parcels inside
assertTrue(Bundle.kindofEquals(a, b));
}
diff --git a/core/tests/coretests/src/android/os/BytesMatcherTest.java b/core/tests/coretests/src/android/os/BytesMatcherTest.java
deleted file mode 100644
index b28e309..0000000
--- a/core/tests/coretests/src/android/os/BytesMatcherTest.java
+++ /dev/null
@@ -1,178 +0,0 @@
-/*
- * Copyright (C) 2021 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.os;
-
-import static com.android.internal.util.HexDump.hexStringToByteArray;
-
-import android.bluetooth.BluetoothUuid;
-import android.net.MacAddress;
-
-import androidx.test.filters.SmallTest;
-
-import junit.framework.TestCase;
-
-import org.junit.Test;
-import org.junit.runner.RunWith;
-import org.junit.runners.JUnit4;
-
-@RunWith(JUnit4.class)
-@SmallTest
-public class BytesMatcherTest extends TestCase {
- @Test
- public void testEmpty() throws Exception {
- BytesMatcher matcher = BytesMatcher.decode("");
- assertFalse(matcher.test(hexStringToByteArray("cafe")));
- assertFalse(matcher.test(hexStringToByteArray("")));
- }
-
- @Test
- public void testExact() throws Exception {
- BytesMatcher matcher = BytesMatcher.decode("+cafe");
- assertTrue(matcher.test(hexStringToByteArray("cafe")));
- assertFalse(matcher.test(hexStringToByteArray("beef")));
- assertFalse(matcher.test(hexStringToByteArray("ca")));
- assertFalse(matcher.test(hexStringToByteArray("cafe00")));
- }
-
- @Test
- public void testMask() throws Exception {
- BytesMatcher matcher = BytesMatcher.decode("+cafe/ff00");
- assertTrue(matcher.test(hexStringToByteArray("cafe")));
- assertTrue(matcher.test(hexStringToByteArray("ca88")));
- assertFalse(matcher.test(hexStringToByteArray("beef")));
- assertFalse(matcher.test(hexStringToByteArray("ca")));
- assertFalse(matcher.test(hexStringToByteArray("cafe00")));
- }
-
- @Test
- public void testPrefix() throws Exception {
- BytesMatcher matcher = BytesMatcher.decode("⊆cafe,⊆beef/ff00");
- assertTrue(matcher.test(hexStringToByteArray("cafe")));
- assertFalse(matcher.test(hexStringToByteArray("caff")));
- assertTrue(matcher.test(hexStringToByteArray("cafecafe")));
- assertFalse(matcher.test(hexStringToByteArray("ca")));
- assertTrue(matcher.test(hexStringToByteArray("beef")));
- assertTrue(matcher.test(hexStringToByteArray("beff")));
- assertTrue(matcher.test(hexStringToByteArray("beffbeff")));
- assertFalse(matcher.test(hexStringToByteArray("be")));
- }
-
- @Test
- public void testMacAddress() throws Exception {
- BytesMatcher matcher = BytesMatcher.decode("+cafe00112233/ffffff000000");
- assertTrue(matcher.testMacAddress(
- MacAddress.fromString("ca:fe:00:00:00:00")));
- assertFalse(matcher.testMacAddress(
- MacAddress.fromString("f0:0d:00:00:00:00")));
- }
-
- @Test
- public void testBluetoothUuid() throws Exception {
- BytesMatcher matcher = BytesMatcher.decode("+cafe/ff00");
- assertTrue(matcher.testBluetoothUuid(
- BluetoothUuid.parseUuidFrom(hexStringToByteArray("cafe"))));
- assertFalse(matcher.testBluetoothUuid(
- BluetoothUuid.parseUuidFrom(hexStringToByteArray("beef"))));
- }
-
- /**
- * Verify that single matcher can be configured to match Bluetooth UUIDs of
- * varying lengths.
- */
- @Test
- public void testBluetoothUuid_Mixed() throws Exception {
- BytesMatcher matcher = BytesMatcher.decode("+aaaa/ff00,+bbbbbbbb/ffff0000");
- assertTrue(matcher.testBluetoothUuid(
- BluetoothUuid.parseUuidFrom(hexStringToByteArray("aaaa"))));
- assertFalse(matcher.testBluetoothUuid(
- BluetoothUuid.parseUuidFrom(hexStringToByteArray("bbbb"))));
- assertTrue(matcher.testBluetoothUuid(
- BluetoothUuid.parseUuidFrom(hexStringToByteArray("bbbbbbbb"))));
- assertFalse(matcher.testBluetoothUuid(
- BluetoothUuid.parseUuidFrom(hexStringToByteArray("aaaaaaaa"))));
- }
-
- @Test
- public void testSerialize_Empty() throws Exception {
- BytesMatcher matcher = new BytesMatcher();
- matcher = BytesMatcher.decode(BytesMatcher.encode(matcher));
-
- // Also very empty and null values
- BytesMatcher.decode("");
- BytesMatcher.decode(null);
- }
-
- @Test
- public void testSerialize_Exact() throws Exception {
- BytesMatcher matcher = new BytesMatcher();
- matcher.addExactRejectRule(hexStringToByteArray("cafe00112233"),
- hexStringToByteArray("ffffff000000"));
- matcher.addExactRejectRule(hexStringToByteArray("beef00112233"),
- null);
- matcher.addExactAcceptRule(hexStringToByteArray("000000000000"),
- hexStringToByteArray("000000000000"));
-
- assertFalse(matcher.test(hexStringToByteArray("cafe00ffffff")));
- assertFalse(matcher.test(hexStringToByteArray("beef00112233")));
- assertTrue(matcher.test(hexStringToByteArray("beef00ffffff")));
-
- // Bounce through serialization pass and confirm it still works
- matcher = BytesMatcher.decode(BytesMatcher.encode(matcher));
-
- assertFalse(matcher.test(hexStringToByteArray("cafe00ffffff")));
- assertFalse(matcher.test(hexStringToByteArray("beef00112233")));
- assertTrue(matcher.test(hexStringToByteArray("beef00ffffff")));
- }
-
- @Test
- public void testSerialize_Prefix() throws Exception {
- BytesMatcher matcher = new BytesMatcher();
- matcher.addExactRejectRule(hexStringToByteArray("aa"), null);
- matcher.addExactAcceptRule(hexStringToByteArray("bb"), null);
- matcher.addPrefixAcceptRule(hexStringToByteArray("aa"), null);
- matcher.addPrefixRejectRule(hexStringToByteArray("bb"), null);
-
- assertFalse(matcher.test(hexStringToByteArray("aa")));
- assertTrue(matcher.test(hexStringToByteArray("bb")));
- assertTrue(matcher.test(hexStringToByteArray("aaaa")));
- assertFalse(matcher.test(hexStringToByteArray("bbbb")));
-
- // Bounce through serialization pass and confirm it still works
- matcher = BytesMatcher.decode(BytesMatcher.encode(matcher));
-
- assertFalse(matcher.test(hexStringToByteArray("aa")));
- assertTrue(matcher.test(hexStringToByteArray("bb")));
- assertTrue(matcher.test(hexStringToByteArray("aaaa")));
- assertFalse(matcher.test(hexStringToByteArray("bbbb")));
- }
-
- @Test
- public void testOrdering_RejectFirst() throws Exception {
- BytesMatcher matcher = BytesMatcher.decode("-ff/0f,+ff/f0");
- assertFalse(matcher.test(hexStringToByteArray("ff")));
- assertTrue(matcher.test(hexStringToByteArray("f0")));
- assertFalse(matcher.test(hexStringToByteArray("0f")));
- }
-
- @Test
- public void testOrdering_AcceptFirst() throws Exception {
- BytesMatcher matcher = BytesMatcher.decode("+ff/f0,-ff/0f");
- assertTrue(matcher.test(hexStringToByteArray("ff")));
- assertTrue(matcher.test(hexStringToByteArray("f0")));
- assertFalse(matcher.test(hexStringToByteArray("0f")));
- }
-}
diff --git a/core/tests/coretests/src/android/os/ParcelTest.java b/core/tests/coretests/src/android/os/ParcelTest.java
index dcb3e2f..fdd278b 100644
--- a/core/tests/coretests/src/android/os/ParcelTest.java
+++ b/core/tests/coretests/src/android/os/ParcelTest.java
@@ -17,6 +17,9 @@
package android.os;
import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertThrows;
+import static org.junit.Assert.assertTrue;
import android.platform.test.annotations.Presubmit;
@@ -110,4 +113,130 @@
assertEquals(string, p.readString16());
}
}
+
+ @Test
+ public void testCompareDataInRange_whenSameData() {
+ Parcel pA = Parcel.obtain();
+ int iA = pA.dataPosition();
+ pA.writeInt(13);
+ pA.writeString("Tiramisu");
+ int length = pA.dataPosition() - iA;
+ Parcel pB = Parcel.obtain();
+ pB.writeString("Prefix");
+ int iB = pB.dataPosition();
+ pB.writeInt(13);
+ pB.writeString("Tiramisu");
+
+ assertTrue(Parcel.compareData(pA, iA, pB, iB, length));
+ }
+
+ @Test
+ public void testCompareDataInRange_whenSameDataWithBinder() {
+ Binder binder = new Binder();
+ Parcel pA = Parcel.obtain();
+ int iA = pA.dataPosition();
+ pA.writeInt(13);
+ pA.writeStrongBinder(binder);
+ pA.writeString("Tiramisu");
+ int length = pA.dataPosition() - iA;
+ Parcel pB = Parcel.obtain();
+ pB.writeString("Prefix");
+ int iB = pB.dataPosition();
+ pB.writeInt(13);
+ pB.writeStrongBinder(binder);
+ pB.writeString("Tiramisu");
+
+ assertTrue(Parcel.compareData(pA, iA, pB, iB, length));
+ }
+
+ @Test
+ public void testCompareDataInRange_whenDifferentData() {
+ Parcel pA = Parcel.obtain();
+ int iA = pA.dataPosition();
+ pA.writeInt(13);
+ pA.writeString("Tiramisu");
+ int length = pA.dataPosition() - iA;
+ Parcel pB = Parcel.obtain();
+ int iB = pB.dataPosition();
+ pB.writeString("Prefix");
+ pB.writeInt(13);
+ pB.writeString("Tiramisu");
+
+ assertFalse(Parcel.compareData(pA, iA, pB, iB, length));
+ }
+
+ @Test
+ public void testCompareDataInRange_whenLimitOutOfBounds_throws() {
+ Parcel pA = Parcel.obtain();
+ int iA = pA.dataPosition();
+ pA.writeInt(12);
+ pA.writeString("Tiramisu");
+ int length = pA.dataPosition() - iA;
+ Parcel pB = Parcel.obtain();
+ pB.writeString("Prefix");
+ int iB = pB.dataPosition();
+ pB.writeInt(13);
+ pB.writeString("Tiramisu");
+ pB.writeInt(-1);
+
+ assertThrows(IllegalArgumentException.class,
+ () -> Parcel.compareData(pA, iA + length, pB, iB, 1));
+ assertThrows(IllegalArgumentException.class,
+ () -> Parcel.compareData(pA, iA, pB, pB.dataSize(), 1));
+ assertThrows(IllegalArgumentException.class,
+ () -> Parcel.compareData(pA, iA, pB, iB, length + 1));
+ assertThrows(IllegalArgumentException.class,
+ () -> Parcel.compareData(pA, iA + length + 1, pB, iB, 0));
+ assertThrows(IllegalArgumentException.class,
+ () -> Parcel.compareData(pA, iA, pB, iB + pB.dataSize() + 1, 0));
+ }
+
+ @Test
+ public void testCompareDataInRange_whenLengthZero() {
+ Parcel pA = Parcel.obtain();
+ int iA = pA.dataPosition();
+ pA.writeInt(12);
+ pA.writeString("Tiramisu");
+ int length = pA.dataPosition() - iA;
+ Parcel pB = Parcel.obtain();
+ pB.writeString("Prefix");
+ int iB = pB.dataPosition();
+ pB.writeInt(13);
+ pB.writeString("Tiramisu");
+
+ assertTrue(Parcel.compareData(pA, 0, pB, iB, 0));
+ assertTrue(Parcel.compareData(pA, iA + length, pB, iB, 0));
+ assertTrue(Parcel.compareData(pA, iA, pB, pB.dataSize(), 0));
+ }
+
+ @Test
+ public void testCompareDataInRange_whenNegativeLength_throws() {
+ Parcel pA = Parcel.obtain();
+ int iA = pA.dataPosition();
+ pA.writeInt(12);
+ pA.writeString("Tiramisu");
+ Parcel pB = Parcel.obtain();
+ pB.writeString("Prefix");
+ int iB = pB.dataPosition();
+ pB.writeInt(13);
+ pB.writeString("Tiramisu");
+
+ assertThrows(IllegalArgumentException.class, () -> Parcel.compareData(pA, iA, pB, iB, -1));
+ }
+
+ @Test
+ public void testCompareDataInRange_whenNegativeOffset_throws() {
+ Parcel pA = Parcel.obtain();
+ int iA = pA.dataPosition();
+ pA.writeInt(12);
+ pA.writeString("Tiramisu");
+ Parcel pB = Parcel.obtain();
+ pB.writeString("Prefix");
+ int iB = pB.dataPosition();
+ pB.writeInt(13);
+ pB.writeString("Tiramisu");
+
+ assertThrows(IllegalArgumentException.class, () -> Parcel.compareData(pA, -1, pB, iB, 0));
+ assertThrows(IllegalArgumentException.class, () -> Parcel.compareData(pA, 0, pB, -1, 0));
+ }
}
diff --git a/core/tests/coretests/src/com/android/internal/content/res/OverlayConfigIterationRule.java b/core/tests/coretests/src/com/android/internal/content/res/OverlayConfigIterationRule.java
index 3c093d8..2c31b08 100644
--- a/core/tests/coretests/src/com/android/internal/content/res/OverlayConfigIterationRule.java
+++ b/core/tests/coretests/src/com/android/internal/content/res/OverlayConfigIterationRule.java
@@ -30,6 +30,7 @@
import com.android.internal.content.om.OverlayConfig.PackageProvider;
import com.android.internal.content.om.OverlayScanner;
import com.android.internal.content.om.OverlayScanner.ParsedOverlayInfo;
+import com.android.internal.util.function.TriConsumer;
import org.junit.Assert;
import org.junit.rules.TestRule;
@@ -42,7 +43,6 @@
import java.io.IOException;
import java.util.List;
import java.util.Map;
-import java.util.function.BiConsumer;
import java.util.function.Supplier;
/**
@@ -74,7 +74,7 @@
TestOverlayInfo(String packageName, String targetPackageName,
int targetSdkVersion, boolean isStatic, int priority, File path,
String requiredSystemPropertyName, String requiredSystemPropertyValue) {
- super(packageName, targetPackageName, targetSdkVersion, isStatic, priority, path);
+ super(packageName, targetPackageName, targetSdkVersion, isStatic, priority, path, null);
this.requiredSystemPropertyName = requiredSystemPropertyName;
this.requiredSystemPropertyValue = requiredSystemPropertyValue;
}
@@ -174,8 +174,8 @@
mIteration = Iteration.SYSTEM_SERVER;
doAnswer((InvocationOnMock invocation) -> {
final Object[] args = invocation.getArguments();
- final BiConsumer<ParsingPackageRead, Boolean> f =
- (BiConsumer<ParsingPackageRead, Boolean>) args[0];
+ final TriConsumer<ParsingPackageRead, Boolean, File> f =
+ (TriConsumer<ParsingPackageRead, Boolean, File>) args[0];
for (Map.Entry<File, TestOverlayInfo> overlay :
mTestOverlayInfos.entrySet()) {
final ParsingPackageRead a = Mockito.mock(ParsingPackageRead.class);
@@ -191,7 +191,8 @@
when(a.isOverlayIsStatic()).thenReturn(info.isStatic);
when(a.getOverlayPriority()).thenReturn(info.priority);
when(a.getBaseApkPath()).thenReturn(info.path.getPath());
- f.accept(a, !info.path.getPath().contains("data/overlay"));
+ f.accept(a, !info.path.getPath().contains("data/overlay"),
+ /*preInstalledApexPath=*/null);
}
return null;
}).when(mPkgProvider).forEachPackage(any());
diff --git a/core/tests/coretests/src/com/android/internal/os/BluetoothPowerCalculatorTest.java b/core/tests/coretests/src/com/android/internal/os/BluetoothPowerCalculatorTest.java
index 5c84794..d361da9 100644
--- a/core/tests/coretests/src/com/android/internal/os/BluetoothPowerCalculatorTest.java
+++ b/core/tests/coretests/src/com/android/internal/os/BluetoothPowerCalculatorTest.java
@@ -33,6 +33,8 @@
import org.junit.Test;
import org.junit.runner.RunWith;
+import java.util.ArrayList;
+
@RunWith(AndroidJUnit4.class)
@SmallTest
public class BluetoothPowerCalculatorTest {
@@ -105,10 +107,10 @@
final BluetoothActivityEnergyInfo info = new BluetoothActivityEnergyInfo(1000,
BluetoothActivityEnergyInfo.BT_STACK_STATE_STATE_ACTIVE, 7000, 5000, 0,
reportedEnergyUc);
- info.setUidTraffic(new UidTraffic[]{
- new UidTraffic(Process.BLUETOOTH_UID, 1000, 2000),
- new UidTraffic(APP_UID, 3000, 4000)
- });
+ info.setUidTraffic(new ArrayList<UidTraffic>(){{
+ add(new UidTraffic(Process.BLUETOOTH_UID, 1000, 2000));
+ add(new UidTraffic(APP_UID, 3000, 4000));
+ }});
mStatsRule.getBatteryStats().updateBluetoothStateLocked(info,
consumedEnergyUc, 1000, 1000);
}
diff --git a/core/tests/coretests/src/com/android/internal/os/CpuPowerCalculatorTest.java b/core/tests/coretests/src/com/android/internal/os/CpuPowerCalculatorTest.java
index 152d246..8540d91d 100644
--- a/core/tests/coretests/src/com/android/internal/os/CpuPowerCalculatorTest.java
+++ b/core/tests/coretests/src/com/android/internal/os/CpuPowerCalculatorTest.java
@@ -21,13 +21,18 @@
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.anyBoolean;
import static org.mockito.ArgumentMatchers.anyInt;
+import static org.mockito.ArgumentMatchers.anyLong;
+import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.Mockito.doAnswer;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;
import android.os.BatteryConsumer;
+import android.os.BatteryStats;
+import android.os.BatteryUsageStatsQuery;
import android.os.Process;
import android.os.UidBatteryConsumer;
+import android.util.SparseArray;
import androidx.test.filters.SmallTest;
import androidx.test.runner.AndroidJUnit4;
@@ -43,12 +48,15 @@
@RunWith(AndroidJUnit4.class)
@SmallTest
+@SuppressWarnings("GuardedBy")
public class CpuPowerCalculatorTest {
private static final double PRECISION = 0.00001;
private static final int APP_UID1 = Process.FIRST_APPLICATION_UID + 42;
private static final int APP_UID2 = Process.FIRST_APPLICATION_UID + 272;
+ private static final int NUM_CPU_FREQS = 2 + 2; // 2 clusters * 2 freqs each
+
@Rule
public final BatteryUsageStatsRule mStatsRule = new BatteryUsageStatsRule()
.setAveragePower(PowerProfile.POWER_CPU_ACTIVE, 720)
@@ -79,6 +87,8 @@
private KernelCpuUidTimeReader.KernelCpuUidActiveTimeReader mMockKerneCpuUidActiveTimeReader;
@Mock
private SystemServerCpuThreadReader mMockSystemServerCpuThreadReader;
+ @Mock
+ private KernelSingleUidTimeReader mMockKernelSingleUidTimeReader;
@Before
public void setUp() {
@@ -95,6 +105,7 @@
.setKernelCpuUidClusterTimeReader(mMockKernelCpuUidClusterTimeReader)
.setKernelCpuUidUserSysTimeReader(mMockKernelCpuUidUserSysTimeReader)
.setKernelCpuUidActiveTimeReader(mMockKerneCpuUidActiveTimeReader)
+ .setKernelSingleUidTimeReader(mMockKernelSingleUidTimeReader)
.setSystemServerCpuThreadReader(mMockSystemServerCpuThreadReader)
.initMeasuredEnergyStatsLocked(supportedPowerBuckets, new String[0]);
}
@@ -133,6 +144,14 @@
return null;
}).when(mMockKernelCpuUidClusterTimeReader).readDelta(anyBoolean(), any());
+ // Per-frequency CPU time
+ doAnswer(invocation -> {
+ final KernelCpuUidTimeReader.Callback<long[]> callback = invocation.getArgument(1);
+ callback.onUidCpuTime(APP_UID1, new long[]{1100, 11, 2200, 22});
+ callback.onUidCpuTime(APP_UID2, new long[]{3300, 33, 4400, 44});
+ return null;
+ }).when(mMockCpuUidFreqTimeReader).readDelta(anyBoolean(), any());
+
mStatsRule.getBatteryStats().updateCpuTimeLocked(true, true, null);
mStatsRule.getUidStats(APP_UID1).getProcessStatsLocked("foo").addCpuTimeLocked(4321, 1234);
@@ -147,7 +166,7 @@
assertThat(uidConsumer1.getUsageDurationMillis(BatteryConsumer.POWER_COMPONENT_CPU))
.isEqualTo(3333);
assertThat(uidConsumer1.getConsumedPower(BatteryConsumer.POWER_COMPONENT_CPU))
- .isWithin(PRECISION).of(1.092233);
+ .isWithin(PRECISION).of(1.031677);
assertThat(uidConsumer1.getPowerModel(BatteryConsumer.POWER_COMPONENT_CPU))
.isEqualTo(BatteryConsumer.POWER_MODEL_POWER_PROFILE);
assertThat(uidConsumer1.getPackageWithHighestDrain()).isEqualTo("bar");
@@ -156,20 +175,20 @@
assertThat(uidConsumer2.getUsageDurationMillis(BatteryConsumer.POWER_COMPONENT_CPU))
.isEqualTo(7777);
assertThat(uidConsumer2.getConsumedPower(BatteryConsumer.POWER_COMPONENT_CPU))
- .isWithin(PRECISION).of(2.672322);
+ .isWithin(PRECISION).of(2.489544);
assertThat(uidConsumer2.getPowerModel(BatteryConsumer.POWER_COMPONENT_CPU))
.isEqualTo(BatteryConsumer.POWER_MODEL_POWER_PROFILE);
assertThat(uidConsumer2.getPackageWithHighestDrain()).isNull();
final BatteryConsumer deviceBatteryConsumer = mStatsRule.getDeviceBatteryConsumer();
assertThat(deviceBatteryConsumer.getConsumedPower(BatteryConsumer.POWER_COMPONENT_CPU))
- .isWithin(PRECISION).of(3.76455);
+ .isWithin(PRECISION).of(3.52122);
assertThat(deviceBatteryConsumer.getPowerModel(BatteryConsumer.POWER_COMPONENT_CPU))
.isEqualTo(BatteryConsumer.POWER_MODEL_POWER_PROFILE);
final BatteryConsumer appsBatteryConsumer = mStatsRule.getAppsBatteryConsumer();
assertThat(appsBatteryConsumer.getConsumedPower(BatteryConsumer.POWER_COMPONENT_CPU))
- .isWithin(PRECISION).of(3.76455);
+ .isWithin(PRECISION).of(3.52122);
assertThat(appsBatteryConsumer.getPowerModel(BatteryConsumer.POWER_COMPONENT_CPU))
.isEqualTo(BatteryConsumer.POWER_MODEL_POWER_PROFILE);
}
@@ -249,4 +268,189 @@
assertThat(appsBatteryConsumer.getPowerModel(BatteryConsumer.POWER_COMPONENT_CPU))
.isEqualTo(BatteryConsumer.POWER_MODEL_MEASURED_ENERGY);
}
+
+ @Test
+ public void testTimerBasedModel_byProcessState() {
+ mStatsRule.getBatteryStats().setTrackingCpuByProcStateEnabled(true);
+
+ when(mMockUserInfoProvider.exists(anyInt())).thenReturn(true);
+
+ when(mMockCpuUidFreqTimeReader.allUidTimesAvailable()).thenReturn(true);
+ when(mMockCpuUidFreqTimeReader.readFreqs(any())).thenReturn(new long[]{100, 200, 300, 400});
+
+ when(mMockKernelSingleUidTimeReader.singleUidCpuTimesAvailable()).thenReturn(true);
+
+ SparseArray<long[]> allUidCpuFreqTimeMs = new SparseArray<>();
+ allUidCpuFreqTimeMs.put(APP_UID1, new long[0]);
+ allUidCpuFreqTimeMs.put(APP_UID2, new long[0]);
+ when(mMockCpuUidFreqTimeReader.getAllUidCpuFreqTimeMs()).thenReturn(allUidCpuFreqTimeMs);
+
+ mStatsRule.setTime(1000, 1000);
+
+ mStatsRule.getUidStats(APP_UID1).setProcessStateForTest(
+ BatteryStats.Uid.PROCESS_STATE_FOREGROUND, 1000);
+ mStatsRule.getUidStats(APP_UID2).setProcessStateForTest(
+ BatteryStats.Uid.PROCESS_STATE_BACKGROUND, 1000);
+
+ // Initialize time-in-state counts to 0
+ mockSingleUidTimeReader(APP_UID1, new long[NUM_CPU_FREQS]);
+ mockSingleUidTimeReader(APP_UID2, new long[NUM_CPU_FREQS]);
+
+ mStatsRule.getBatteryStats().copyFromAllUidsCpuTimes(true, true);
+
+ mockSingleUidTimeReader(APP_UID1, new long[]{1000, 2000, 3000, 4000});
+ mockSingleUidTimeReader(APP_UID2, new long[]{1111, 2222, 3333, 4444});
+
+ mStatsRule.setTime(2000, 2000);
+ mStatsRule.getBatteryStats().updateCpuTimeLocked(true, true, null);
+ mStatsRule.getBatteryStats().copyFromAllUidsCpuTimes(true, true);
+
+ mockSingleUidTimeReader(APP_UID1, new long[] {5000, 6000, 7000, 8000});
+ mockSingleUidTimeReader(APP_UID2, new long[]{5555, 6666, 7777, 8888});
+
+ mStatsRule.getUidStats(APP_UID1).setProcessStateForTest(
+ BatteryStats.Uid.PROCESS_STATE_FOREGROUND_SERVICE, 2000);
+ mStatsRule.getUidStats(APP_UID2).setProcessStateForTest(
+ BatteryStats.Uid.PROCESS_STATE_TOP, 2000);
+
+ mStatsRule.setTime(3000, 3000);
+ mStatsRule.getBatteryStats().updateCpuTimeLocked(true, true, null);
+ mStatsRule.getBatteryStats().copyFromAllUidsCpuTimes(true, true);
+
+ CpuPowerCalculator calculator =
+ new CpuPowerCalculator(mStatsRule.getPowerProfile());
+
+ mStatsRule.apply(new BatteryUsageStatsQuery.Builder()
+ .powerProfileModeledOnly()
+ .includePowerModels()
+ .includeProcessStateData()
+ .build(), calculator);
+
+ UidBatteryConsumer uidConsumer1 = mStatsRule.getUidBatteryConsumer(APP_UID1);
+ UidBatteryConsumer uidConsumer2 = mStatsRule.getUidBatteryConsumer(APP_UID2);
+
+ final BatteryConsumer.Key foreground = uidConsumer1.getKey(
+ BatteryConsumer.POWER_COMPONENT_CPU,
+ BatteryConsumer.PROCESS_STATE_FOREGROUND);
+ final BatteryConsumer.Key background = uidConsumer1.getKey(
+ BatteryConsumer.POWER_COMPONENT_CPU,
+ BatteryConsumer.PROCESS_STATE_BACKGROUND);
+ final BatteryConsumer.Key fgs = uidConsumer1.getKey(
+ BatteryConsumer.POWER_COMPONENT_CPU,
+ BatteryConsumer.PROCESS_STATE_FOREGROUND_SERVICE);
+
+ assertThat(uidConsumer1.getConsumedPower(foreground)).isWithin(PRECISION).of(1.388888);
+ assertThat(uidConsumer1.getConsumedPower(background)).isWithin(PRECISION).of(0);
+ assertThat(uidConsumer1.getConsumedPower(fgs)).isWithin(PRECISION).of(2.0);
+ assertThat(uidConsumer2.getConsumedPower(foreground)).isWithin(PRECISION).of(2.222);
+ assertThat(uidConsumer2.getConsumedPower(background)).isWithin(PRECISION).of(1.543055);
+ assertThat(uidConsumer2.getConsumedPower(fgs)).isWithin(PRECISION).of(0);
+ }
+
+ private void mockSingleUidTimeReader(int uid, long[] cpuTimes) {
+ doAnswer(invocation -> {
+ LongArrayMultiStateCounter counter = invocation.getArgument(1);
+ long timestampMs = invocation.getArgument(2);
+ LongArrayMultiStateCounter.LongArrayContainer container =
+ new LongArrayMultiStateCounter.LongArrayContainer(NUM_CPU_FREQS);
+ container.setValues(cpuTimes);
+ counter.updateValues(container, timestampMs);
+ return null;
+ }).when(mMockKernelSingleUidTimeReader).addDelta(eq(uid),
+ any(LongArrayMultiStateCounter.class), anyLong());
+ }
+
+ @Test
+ public void testMeasuredEnergyBasedModel_perProcessState() {
+ when(mMockUserInfoProvider.exists(anyInt())).thenReturn(true);
+
+ when(mMockKernelCpuSpeedReaders[0].readDelta()).thenReturn(new long[]{1000, 2000});
+ when(mMockKernelCpuSpeedReaders[1].readDelta()).thenReturn(new long[]{3000, 4000});
+
+ when(mMockCpuUidFreqTimeReader.perClusterTimesAvailable()).thenReturn(false);
+
+ mStatsRule.setTime(1000, 1000);
+
+ mStatsRule.getUidStats(APP_UID1).setProcessStateForTest(
+ BatteryStats.Uid.PROCESS_STATE_FOREGROUND, 1000);
+ mStatsRule.getUidStats(APP_UID2).setProcessStateForTest(
+ BatteryStats.Uid.PROCESS_STATE_BACKGROUND, 1000);
+
+ // User/System CPU time
+ doAnswer(invocation -> {
+ final KernelCpuUidTimeReader.Callback<long[]> callback = invocation.getArgument(1);
+ // User/system time in microseconds
+ callback.onUidCpuTime(APP_UID1, new long[]{1111000, 2222000});
+ callback.onUidCpuTime(APP_UID2, new long[]{3333000, 4444000});
+ return null;
+ }).when(mMockKernelCpuUidUserSysTimeReader).readDelta(anyBoolean(), any());
+
+ // Per-frequency CPU time
+ doAnswer(invocation -> {
+ final KernelCpuUidTimeReader.Callback<long[]> callback = invocation.getArgument(1);
+ callback.onUidCpuTime(APP_UID1, new long[]{1100, 11, 2200, 22});
+ callback.onUidCpuTime(APP_UID2, new long[]{3300, 33, 4400, 44});
+ return null;
+ }).when(mMockCpuUidFreqTimeReader).readDelta(anyBoolean(), any());
+
+ mStatsRule.setTime(2000, 2000);
+ final long[] clusterChargesUC = new long[]{13577531, 24688642};
+ mStatsRule.getBatteryStats().updateCpuTimeLocked(true, true, clusterChargesUC);
+
+ mStatsRule.getUidStats(APP_UID1).setProcessStateForTest(
+ BatteryStats.Uid.PROCESS_STATE_FOREGROUND_SERVICE, 2000);
+ mStatsRule.getUidStats(APP_UID2).setProcessStateForTest(
+ BatteryStats.Uid.PROCESS_STATE_TOP, 2000);
+
+ // User/System CPU time
+ doAnswer(invocation -> {
+ final KernelCpuUidTimeReader.Callback<long[]> callback = invocation.getArgument(1);
+ // User/system time in microseconds
+ callback.onUidCpuTime(APP_UID1, new long[]{5555000, 6666000});
+ callback.onUidCpuTime(APP_UID2, new long[]{7777000, 8888000});
+ return null;
+ }).when(mMockKernelCpuUidUserSysTimeReader).readDelta(anyBoolean(), any());
+
+ // Per-frequency CPU time
+ doAnswer(invocation -> {
+ final KernelCpuUidTimeReader.Callback<long[]> callback = invocation.getArgument(1);
+ callback.onUidCpuTime(APP_UID1, new long[]{5500, 55, 6600, 66});
+ callback.onUidCpuTime(APP_UID2, new long[]{7700, 77, 8800, 88});
+ return null;
+ }).when(mMockCpuUidFreqTimeReader).readDelta(anyBoolean(), any());
+
+ mStatsRule.setTime(3000, 3000);
+
+ clusterChargesUC[0] += 10000000;
+ clusterChargesUC[1] += 20000000;
+ mStatsRule.getBatteryStats().updateCpuTimeLocked(true, true, clusterChargesUC);
+
+ CpuPowerCalculator calculator =
+ new CpuPowerCalculator(mStatsRule.getPowerProfile());
+
+ mStatsRule.apply(new BatteryUsageStatsQuery.Builder()
+ .includePowerModels()
+ .includeProcessStateData()
+ .build(), calculator);
+
+ UidBatteryConsumer uidConsumer1 = mStatsRule.getUidBatteryConsumer(APP_UID1);
+ UidBatteryConsumer uidConsumer2 = mStatsRule.getUidBatteryConsumer(APP_UID2);
+
+ final BatteryConsumer.Key foreground = uidConsumer1.getKey(
+ BatteryConsumer.POWER_COMPONENT_CPU,
+ BatteryConsumer.PROCESS_STATE_FOREGROUND);
+ final BatteryConsumer.Key background = uidConsumer1.getKey(
+ BatteryConsumer.POWER_COMPONENT_CPU,
+ BatteryConsumer.PROCESS_STATE_BACKGROUND);
+ final BatteryConsumer.Key fgs = uidConsumer1.getKey(
+ BatteryConsumer.POWER_COMPONENT_CPU,
+ BatteryConsumer.PROCESS_STATE_FOREGROUND_SERVICE);
+
+ assertThat(uidConsumer1.getConsumedPower(foreground)).isWithin(PRECISION).of(3.18884);
+ assertThat(uidConsumer1.getConsumedPower(background)).isWithin(PRECISION).of(0);
+ assertThat(uidConsumer1.getConsumedPower(fgs)).isWithin(PRECISION).of(8.02273);
+ assertThat(uidConsumer2.getConsumedPower(foreground)).isWithin(PRECISION).of(10.94009);
+ assertThat(uidConsumer2.getConsumedPower(background)).isWithin(PRECISION).of(7.44064);
+ assertThat(uidConsumer2.getConsumedPower(fgs)).isWithin(PRECISION).of(0);
+ }
}
diff --git a/core/tests/coretests/src/com/android/internal/os/MockBatteryStatsImpl.java b/core/tests/coretests/src/com/android/internal/os/MockBatteryStatsImpl.java
index c24dc67..d16689c 100644
--- a/core/tests/coretests/src/com/android/internal/os/MockBatteryStatsImpl.java
+++ b/core/tests/coretests/src/com/android/internal/os/MockBatteryStatsImpl.java
@@ -65,8 +65,9 @@
final boolean[] supportedStandardBuckets =
new boolean[MeasuredEnergyStats.NUMBER_STANDARD_POWER_BUCKETS];
Arrays.fill(supportedStandardBuckets, true);
- mGlobalMeasuredEnergyStats =
- new MeasuredEnergyStats(supportedStandardBuckets, customBucketNames);
+ mMeasuredEnergyStatsConfig = new MeasuredEnergyStats.Config(supportedStandardBuckets,
+ customBucketNames, new int[0], new String[]{""});
+ mGlobalMeasuredEnergyStats = new MeasuredEnergyStats(mMeasuredEnergyStatsConfig);
}
public TimeBase getOnBatteryTimeBase() {
diff --git a/core/tests/coretests/src/com/android/internal/os/SystemServicePowerCalculatorTest.java b/core/tests/coretests/src/com/android/internal/os/SystemServicePowerCalculatorTest.java
index a36d9fe..33222dd 100644
--- a/core/tests/coretests/src/com/android/internal/os/SystemServicePowerCalculatorTest.java
+++ b/core/tests/coretests/src/com/android/internal/os/SystemServicePowerCalculatorTest.java
@@ -47,6 +47,7 @@
@SmallTest
@RunWith(AndroidJUnit4.class)
+@SuppressWarnings("GuardedBy")
public class SystemServicePowerCalculatorTest {
private static final double PRECISION = 0.000001;
@@ -78,6 +79,8 @@
private KernelCpuUidTimeReader.KernelCpuUidActiveTimeReader mMockKerneCpuUidActiveTimeReader;
@Mock
private SystemServerCpuThreadReader mMockSystemServerCpuThreadReader;
+ @Mock
+ private KernelSingleUidTimeReader mMockKernelSingleUidTimeReader;
private final KernelCpuSpeedReader[] mMockKernelCpuSpeedReaders = new KernelCpuSpeedReader[]{
mock(KernelCpuSpeedReader.class),
@@ -96,6 +99,7 @@
.setKernelCpuUidClusterTimeReader(mMockKernelCpuUidClusterTimeReader)
.setKernelCpuUidUserSysTimeReader(mMockKernelCpuUidUserSysTimeReader)
.setKernelCpuUidActiveTimeReader(mMockKerneCpuUidActiveTimeReader)
+ .setKernelSingleUidTimeReader(mMockKernelSingleUidTimeReader)
.setSystemServerCpuThreadReader(mMockSystemServerCpuThreadReader);
}
@@ -142,19 +146,19 @@
assertThat(mStatsRule.getUidBatteryConsumer(APP_UID1)
.getConsumedPower(BatteryConsumer.POWER_COMPONENT_SYSTEM_SERVICES))
- .isWithin(PRECISION).of(1.979351);
+ .isWithin(PRECISION).of(2.105425);
assertThat(mStatsRule.getUidBatteryConsumer(APP_UID2)
.getConsumedPower(BatteryConsumer.POWER_COMPONENT_SYSTEM_SERVICES))
- .isWithin(PRECISION).of(17.814165);
+ .isWithin(PRECISION).of(18.948825);
assertThat(mStatsRule.getUidBatteryConsumer(Process.SYSTEM_UID)
.getConsumedPower(BatteryConsumer.POWER_COMPONENT_REATTRIBUTED_TO_OTHER_CONSUMERS))
- .isWithin(PRECISION).of(-19.793517);
+ .isWithin(PRECISION).of(-21.054250);
assertThat(mStatsRule.getDeviceBatteryConsumer()
.getConsumedPower(BatteryConsumer.POWER_COMPONENT_SYSTEM_SERVICES))
- .isWithin(PRECISION).of(19.793517);
+ .isWithin(PRECISION).of(21.054250);
assertThat(mStatsRule.getAppsBatteryConsumer()
.getConsumedPower(BatteryConsumer.POWER_COMPONENT_SYSTEM_SERVICES))
- .isWithin(PRECISION).of(19.793517);
+ .isWithin(PRECISION).of(21.054250);
}
private void prepareBatteryStats(long[] clusterChargesUc) {
@@ -192,6 +196,17 @@
return null;
}).when(mMockKernelCpuUidClusterTimeReader).readDelta(anyBoolean(), any());
+ when(mMockKernelSingleUidTimeReader.singleUidCpuTimesAvailable()).thenReturn(true);
+
+ // Per-frequency CPU time
+ doAnswer(invocation -> {
+ final KernelCpuUidTimeReader.Callback<long[]> callback = invocation.getArgument(1);
+ callback.onUidCpuTime(APP_UID1, new long[]{1100, 11, 2200, 22});
+ callback.onUidCpuTime(APP_UID2, new long[]{3300, 33, 4400, 44});
+ callback.onUidCpuTime(Process.SYSTEM_UID, new long[]{20_000, 30_000, 40_000, 40_000});
+ return null;
+ }).when(mMockCpuUidFreqTimeReader).readDelta(anyBoolean(), any());
+
// System service CPU time
final SystemServerCpuThreadReader.SystemServiceCpuThreadTimes threadTimes =
new SystemServerCpuThreadReader.SystemServiceCpuThreadTimes();
diff --git a/core/tests/coretests/src/com/android/internal/power/MeasuredEnergyStatsTest.java b/core/tests/coretests/src/com/android/internal/power/MeasuredEnergyStatsTest.java
index a70033b..dc5bc97 100644
--- a/core/tests/coretests/src/com/android/internal/power/MeasuredEnergyStatsTest.java
+++ b/core/tests/coretests/src/com/android/internal/power/MeasuredEnergyStatsTest.java
@@ -19,9 +19,12 @@
import static android.os.BatteryStats.POWER_DATA_UNAVAILABLE;
import static com.android.internal.power.MeasuredEnergyStats.NUMBER_STANDARD_POWER_BUCKETS;
+import static com.android.internal.power.MeasuredEnergyStats.POWER_BUCKET_BLUETOOTH;
+import static com.android.internal.power.MeasuredEnergyStats.POWER_BUCKET_CPU;
import static com.android.internal.power.MeasuredEnergyStats.POWER_BUCKET_SCREEN_DOZE;
import static com.android.internal.power.MeasuredEnergyStats.POWER_BUCKET_SCREEN_ON;
import static com.android.internal.power.MeasuredEnergyStats.POWER_BUCKET_SCREEN_OTHER;
+import static com.android.internal.power.MeasuredEnergyStats.POWER_BUCKET_WIFI;
import static com.google.common.truth.Truth.assertThat;
@@ -56,55 +59,32 @@
supportedStandardBuckets[POWER_BUCKET_SCREEN_DOZE] = false;
supportedStandardBuckets[POWER_BUCKET_SCREEN_OTHER] = true;
- final MeasuredEnergyStats stats =
- new MeasuredEnergyStats(supportedStandardBuckets, customBucketNames);
+ final MeasuredEnergyStats.Config config =
+ new MeasuredEnergyStats.Config(supportedStandardBuckets, customBucketNames,
+ new int[]{POWER_BUCKET_SCREEN_ON, POWER_BUCKET_WIFI},
+ new String[]{"state0", "state1", "state3"});
+ final MeasuredEnergyStats stats = new MeasuredEnergyStats(config);
- for (int i = 0; i < NUMBER_STANDARD_POWER_BUCKETS; i++) {
- if (supportedStandardBuckets[i]) {
- assertTrue(stats.isStandardBucketSupported(i));
- assertEquals(0L, stats.getAccumulatedStandardBucketCharge(i));
+ for (int bucket = 0; bucket < NUMBER_STANDARD_POWER_BUCKETS; bucket++) {
+ if (supportedStandardBuckets[bucket]) {
+ assertTrue(stats.isStandardBucketSupported(bucket));
+ assertEquals(0L, stats.getAccumulatedStandardBucketCharge(bucket));
} else {
- assertFalse(stats.isStandardBucketSupported(i));
- assertEquals(POWER_DATA_UNAVAILABLE, stats.getAccumulatedStandardBucketCharge(i));
+ assertFalse(stats.isStandardBucketSupported(bucket));
+ assertEquals(POWER_DATA_UNAVAILABLE,
+ stats.getAccumulatedStandardBucketCharge(bucket));
+ }
+ if (bucket == POWER_BUCKET_SCREEN_ON) {
+ assertThat(config.isSupportedMultiStateBucket(bucket)).isTrue();
+ } else {
+ assertThat(config.isSupportedMultiStateBucket(bucket)).isFalse();
}
}
for (int i = 0; i < customBucketNames.length; i++) {
assertEquals(0L, stats.getAccumulatedCustomBucketCharge(i));
}
- assertThat(stats.getCustomBucketNames()).asList().containsExactly("A", "B");
- }
-
- @Test
- public void testCreateFromTemplate() {
- final boolean[] supportedStandardBuckets = new boolean[NUMBER_STANDARD_POWER_BUCKETS];
- final String[] customBucketNames = {"A", "B"};
- supportedStandardBuckets[POWER_BUCKET_SCREEN_ON] = true;
- supportedStandardBuckets[POWER_BUCKET_SCREEN_DOZE] = false;
- supportedStandardBuckets[POWER_BUCKET_SCREEN_OTHER] = true;
-
- final MeasuredEnergyStats stats =
- new MeasuredEnergyStats(supportedStandardBuckets, customBucketNames);
- stats.updateStandardBucket(POWER_BUCKET_SCREEN_ON, 10);
- stats.updateStandardBucket(POWER_BUCKET_SCREEN_ON, 5);
- stats.updateStandardBucket(POWER_BUCKET_SCREEN_OTHER, 40);
- stats.updateCustomBucket(0, 50);
- stats.updateCustomBucket(1, 60);
-
- final MeasuredEnergyStats newStats = MeasuredEnergyStats.createFromTemplate(stats);
-
- for (int i = 0; i < NUMBER_STANDARD_POWER_BUCKETS; i++) {
- if (supportedStandardBuckets[i]) {
- assertTrue(newStats.isStandardBucketSupported(i));
- assertEquals(0L, newStats.getAccumulatedStandardBucketCharge(i));
- } else {
- assertFalse(newStats.isStandardBucketSupported(i));
- assertEquals(POWER_DATA_UNAVAILABLE,
- newStats.getAccumulatedStandardBucketCharge(i));
- }
- }
- for (int i = 0; i < customBucketNames.length; i++) {
- assertEquals(0L, newStats.getAccumulatedCustomBucketCharge(i));
- }
+ assertThat(config.getCustomBucketNames()).asList().containsExactly("A", "B");
+ assertThat(config.getStateNames()).asList().containsExactly("state0", "state1", "state3");
}
@Test
@@ -115,23 +95,32 @@
supportedStandardBuckets[POWER_BUCKET_SCREEN_DOZE] = false;
supportedStandardBuckets[POWER_BUCKET_SCREEN_OTHER] = true;
- final MeasuredEnergyStats stats =
- new MeasuredEnergyStats(supportedStandardBuckets, customBucketNames);
- stats.updateStandardBucket(POWER_BUCKET_SCREEN_ON, 10);
- stats.updateStandardBucket(POWER_BUCKET_SCREEN_ON, 5);
- stats.updateStandardBucket(POWER_BUCKET_SCREEN_OTHER, 40);
- stats.updateCustomBucket(0, 50);
- stats.updateCustomBucket(1, 60);
+ final MeasuredEnergyStats.Config config =
+ new MeasuredEnergyStats.Config(supportedStandardBuckets, customBucketNames,
+ new int[]{POWER_BUCKET_SCREEN_ON}, new String[]{"s0", "s1"});
+ final MeasuredEnergyStats stats = new MeasuredEnergyStats(config);
+
+ stats.setState(0, 1000);
+ stats.updateStandardBucket(POWER_BUCKET_SCREEN_ON, 10, 2000);
+ stats.setState(1, 3000);
+ stats.updateStandardBucket(POWER_BUCKET_SCREEN_ON, 5, 4000);
+ stats.updateStandardBucket(POWER_BUCKET_SCREEN_OTHER, 40, 5000);
+ stats.updateCustomBucket(0, 50, 6000);
+ stats.updateCustomBucket(1, 60, 7000);
final Parcel parcel = Parcel.obtain();
stats.writeToParcel(parcel);
parcel.setDataPosition(0);
- MeasuredEnergyStats newStats = new MeasuredEnergyStats(parcel);
+ MeasuredEnergyStats newStats = new MeasuredEnergyStats(config, parcel);
- for (int i = 0; i < NUMBER_STANDARD_POWER_BUCKETS; i++) {
- assertEquals(stats.getAccumulatedStandardBucketCharge(i),
- newStats.getAccumulatedStandardBucketCharge(i));
+ for (int bucket = 0; bucket < NUMBER_STANDARD_POWER_BUCKETS; bucket++) {
+ assertEquals(stats.getAccumulatedStandardBucketCharge(bucket),
+ newStats.getAccumulatedStandardBucketCharge(bucket));
+ for (int state = 0; state < 2; state++) {
+ assertEquals(stats.getAccumulatedStandardBucketCharge(bucket, state),
+ newStats.getAccumulatedStandardBucketCharge(bucket, state));
+ }
}
for (int i = 0; i < customBucketNames.length; i++) {
assertEquals(stats.getAccumulatedCustomBucketCharge(i),
@@ -143,6 +132,57 @@
}
@Test
+ public void testCreateAndReadConfigFromParcel() {
+ final boolean[] supportedStandardBuckets = new boolean[NUMBER_STANDARD_POWER_BUCKETS];
+ final String[] customBucketNames = {"A", "B"};
+ supportedStandardBuckets[POWER_BUCKET_SCREEN_ON] = true;
+ supportedStandardBuckets[POWER_BUCKET_SCREEN_DOZE] = false;
+ supportedStandardBuckets[POWER_BUCKET_SCREEN_OTHER] = true;
+
+ final MeasuredEnergyStats.Config config =
+ new MeasuredEnergyStats.Config(supportedStandardBuckets, customBucketNames,
+ new int[]{POWER_BUCKET_SCREEN_ON, POWER_BUCKET_WIFI},
+ new String[] {"state0", "state1", "state2"});
+
+ final Parcel parcel = Parcel.obtain();
+ MeasuredEnergyStats.Config.writeToParcel(config, parcel);
+
+ parcel.setDataPosition(0);
+
+ final MeasuredEnergyStats.Config newConfig = MeasuredEnergyStats.Config.createFromParcel(
+ parcel);
+
+ assertThat(newConfig).isNotNull();
+ for (int bucket = 0; bucket < NUMBER_STANDARD_POWER_BUCKETS; bucket++) {
+ if (bucket == POWER_BUCKET_SCREEN_ON || bucket == POWER_BUCKET_SCREEN_OTHER) {
+ assertThat(newConfig.isSupportedBucket(bucket)).isTrue();
+ } else {
+ assertThat(newConfig.isSupportedBucket(bucket)).isFalse();
+ }
+ if (bucket == POWER_BUCKET_SCREEN_ON) {
+ assertThat(newConfig.isSupportedMultiStateBucket(bucket)).isTrue();
+ } else {
+ assertThat(newConfig.isSupportedMultiStateBucket(bucket)).isFalse();
+ }
+ }
+ assertThat(newConfig.getCustomBucketNames()).isEqualTo(new String[]{"A", "B"});
+ assertThat(newConfig.getStateNames()).isEqualTo(new String[]{"state0", "state1", "state2"});
+ }
+
+ @Test
+ public void testCreateAndReadConfigFromParcel_nullConfig() {
+ final Parcel parcel = Parcel.obtain();
+ MeasuredEnergyStats.Config.writeToParcel(null, parcel);
+
+ parcel.setDataPosition(0);
+
+ final MeasuredEnergyStats.Config newConfig = MeasuredEnergyStats.Config.createFromParcel(
+ parcel);
+
+ assertThat(newConfig).isNull();
+ }
+
+ @Test
public void testCreateAndReadSummaryFromParcel() {
final boolean[] supportedStandardBuckets = new boolean[NUMBER_STANDARD_POWER_BUCKETS];
final String[] customBucketNames = {"A", "B"};
@@ -150,8 +190,11 @@
supportedStandardBuckets[POWER_BUCKET_SCREEN_DOZE] = false;
supportedStandardBuckets[POWER_BUCKET_SCREEN_OTHER] = true;
- final MeasuredEnergyStats stats =
- new MeasuredEnergyStats(supportedStandardBuckets, customBucketNames);
+ final MeasuredEnergyStats.Config config =
+ new MeasuredEnergyStats.Config(supportedStandardBuckets, customBucketNames,
+ new int[0], new String[]{"s"});
+ final MeasuredEnergyStats stats = new MeasuredEnergyStats(config);
+
stats.updateStandardBucket(POWER_BUCKET_SCREEN_ON, 10);
stats.updateStandardBucket(POWER_BUCKET_SCREEN_ON, 5);
stats.updateStandardBucket(POWER_BUCKET_SCREEN_OTHER, 40);
@@ -159,9 +202,12 @@
stats.updateCustomBucket(1, 60);
final Parcel parcel = Parcel.obtain();
- MeasuredEnergyStats.writeSummaryToParcel(stats, parcel, false, false);
+ MeasuredEnergyStats.writeSummaryToParcel(stats, parcel);
+
parcel.setDataPosition(0);
- MeasuredEnergyStats newStats = MeasuredEnergyStats.createAndReadSummaryFromParcel(parcel);
+
+ MeasuredEnergyStats newStats =
+ MeasuredEnergyStats.createAndReadSummaryFromParcel(config, parcel);
for (int i = 0; i < NUMBER_STANDARD_POWER_BUCKETS; i++) {
assertEquals(stats.isStandardBucketSupported(i),
@@ -175,48 +221,44 @@
}
assertEquals(POWER_DATA_UNAVAILABLE,
newStats.getAccumulatedCustomBucketCharge(customBucketNames.length + 1));
- assertThat(newStats.getCustomBucketNames()).asList().containsExactly("A", "B");
parcel.recycle();
}
@Test
- public void testCreateAndReadSummaryFromParcel_existingTemplate() {
+ public void testCreateAndReadSummaryFromParcel_configChange() {
final boolean[] supportedStandardBuckets = new boolean[NUMBER_STANDARD_POWER_BUCKETS];
final String[] customBucketNames = {"A", "B"};
supportedStandardBuckets[POWER_BUCKET_SCREEN_ON] = true;
supportedStandardBuckets[POWER_BUCKET_SCREEN_DOZE] = false;
supportedStandardBuckets[POWER_BUCKET_SCREEN_OTHER] = true;
- final MeasuredEnergyStats template =
- new MeasuredEnergyStats(supportedStandardBuckets, customBucketNames);
- template.updateStandardBucket(POWER_BUCKET_SCREEN_ON, 10);
- template.updateStandardBucket(POWER_BUCKET_SCREEN_ON, 5);
- template.updateStandardBucket(POWER_BUCKET_SCREEN_OTHER, 40);
- template.updateCustomBucket(0, 50);
-
- final MeasuredEnergyStats stats = MeasuredEnergyStats.createFromTemplate(template);
- stats.updateStandardBucket(POWER_BUCKET_SCREEN_ON, 200);
- stats.updateStandardBucket(POWER_BUCKET_SCREEN_ON, 7);
- stats.updateStandardBucket(POWER_BUCKET_SCREEN_OTHER, 63);
- stats.updateCustomBucket(0, 315);
- stats.updateCustomBucket(1, 316);
+ final MeasuredEnergyStats.Config config =
+ new MeasuredEnergyStats.Config(supportedStandardBuckets, customBucketNames,
+ new int[0], new String[]{"s"});
+ final MeasuredEnergyStats stats = new MeasuredEnergyStats(config);
+ stats.updateStandardBucket(POWER_BUCKET_SCREEN_ON, 10);
+ stats.updateStandardBucket(POWER_BUCKET_SCREEN_ON, 5);
+ stats.updateStandardBucket(POWER_BUCKET_SCREEN_OTHER, 40);
+ stats.updateCustomBucket(0, 50);
final Parcel parcel = Parcel.obtain();
- MeasuredEnergyStats.writeSummaryToParcel(stats, parcel, false, true);
-
- final boolean[] newsupportedStandardBuckets = new boolean[NUMBER_STANDARD_POWER_BUCKETS];
- newsupportedStandardBuckets[POWER_BUCKET_SCREEN_ON] = true;
- newsupportedStandardBuckets[POWER_BUCKET_SCREEN_DOZE] = true; // switched false > true
- newsupportedStandardBuckets[POWER_BUCKET_SCREEN_OTHER] = false; // switched true > false
- final MeasuredEnergyStats newTemplate =
- new MeasuredEnergyStats(newsupportedStandardBuckets, customBucketNames);
+ MeasuredEnergyStats.writeSummaryToParcel(stats, parcel);
parcel.setDataPosition(0);
+ final boolean[] newSupportedStandardBuckets = new boolean[NUMBER_STANDARD_POWER_BUCKETS];
+ newSupportedStandardBuckets[POWER_BUCKET_SCREEN_ON] = true;
+ newSupportedStandardBuckets[POWER_BUCKET_SCREEN_DOZE] = true; // switched false > true
+ newSupportedStandardBuckets[POWER_BUCKET_SCREEN_OTHER] = false; // switched true > false
+
+ final MeasuredEnergyStats.Config newConfig =
+ new MeasuredEnergyStats.Config(newSupportedStandardBuckets, customBucketNames,
+ new int[0], new String[]{"s"});
+
final MeasuredEnergyStats newStats =
- MeasuredEnergyStats.createAndReadSummaryFromParcel(parcel, newTemplate);
+ MeasuredEnergyStats.createAndReadSummaryFromParcel(newConfig, parcel);
for (int i = 0; i < NUMBER_STANDARD_POWER_BUCKETS; i++) {
- if (!newsupportedStandardBuckets[i]) {
+ if (!newSupportedStandardBuckets[i]) {
assertFalse(newStats.isStandardBucketSupported(i));
assertEquals(POWER_DATA_UNAVAILABLE,
newStats.getAccumulatedStandardBucketCharge(i));
@@ -235,81 +277,22 @@
}
assertEquals(POWER_DATA_UNAVAILABLE,
newStats.getAccumulatedCustomBucketCharge(customBucketNames.length + 1));
- assertThat(newStats.getCustomBucketNames()).asList().containsExactly("A", "B");
parcel.recycle();
}
@Test
- public void testCreateAndReadSummaryFromParcel_skipZero() {
- final boolean[] supportedStandardBuckets = new boolean[NUMBER_STANDARD_POWER_BUCKETS];
- final String[] customBucketNames = {"A", "B"};
- Arrays.fill(supportedStandardBuckets, true);
-
- final MeasuredEnergyStats stats =
- new MeasuredEnergyStats(supportedStandardBuckets, customBucketNames);
- // Accumulate charge in one bucket and one custom bucket, the rest should be zero
- stats.updateStandardBucket(POWER_BUCKET_SCREEN_ON, 200);
- stats.updateCustomBucket(1, 60);
-
- // Let's try parcelling with including zeros
- final Parcel includeZerosParcel = Parcel.obtain();
- MeasuredEnergyStats.writeSummaryToParcel(stats, includeZerosParcel, false, false);
- includeZerosParcel.setDataPosition(0);
-
- MeasuredEnergyStats newStats = MeasuredEnergyStats.createAndReadSummaryFromParcel(
- includeZerosParcel);
-
- for (int i = 0; i < NUMBER_STANDARD_POWER_BUCKETS; i++) {
- if (i == POWER_BUCKET_SCREEN_ON) {
- assertEquals(stats.isStandardBucketSupported(i),
- newStats.isStandardBucketSupported(i));
- assertEquals(stats.getAccumulatedStandardBucketCharge(i),
- newStats.getAccumulatedStandardBucketCharge(i));
- } else {
- assertTrue(newStats.isStandardBucketSupported(i));
- assertEquals(0L, newStats.getAccumulatedStandardBucketCharge(i));
- }
- }
- assertEquals(0L, newStats.getAccumulatedCustomBucketCharge(0));
- assertEquals(stats.getAccumulatedCustomBucketCharge(1),
- newStats.getAccumulatedCustomBucketCharge(1));
- includeZerosParcel.recycle();
-
- // Now let's try parcelling with skipping zeros
- final Parcel skipZerosParcel = Parcel.obtain();
- MeasuredEnergyStats.writeSummaryToParcel(stats, skipZerosParcel, true, false);
- skipZerosParcel.setDataPosition(0);
-
- newStats = MeasuredEnergyStats.createAndReadSummaryFromParcel(skipZerosParcel);
-
- for (int i = 0; i < NUMBER_STANDARD_POWER_BUCKETS; i++) {
- if (i == POWER_BUCKET_SCREEN_ON) {
- assertEquals(stats.isStandardBucketSupported(i),
- newStats.isStandardBucketSupported(i));
- assertEquals(stats.getAccumulatedStandardBucketCharge(i),
- newStats.getAccumulatedStandardBucketCharge(i));
- } else {
- assertFalse(newStats.isStandardBucketSupported(i));
- assertEquals(POWER_DATA_UNAVAILABLE,
- newStats.getAccumulatedStandardBucketCharge(i));
- }
- }
- assertEquals(0L, newStats.getAccumulatedCustomBucketCharge(0));
- assertEquals(stats.getAccumulatedCustomBucketCharge(1),
- newStats.getAccumulatedCustomBucketCharge(1));
- skipZerosParcel.recycle();
- }
-
- @Test
- public void testCreateAndReadSummaryFromParcel_nullTemplate() {
+ public void testCreateAndReadSummaryFromParcel_nullConfig() {
final boolean[] supportedStandardBuckets = new boolean[NUMBER_STANDARD_POWER_BUCKETS];
final String[] customBucketNames = {"A", "B"};
supportedStandardBuckets[POWER_BUCKET_SCREEN_ON] = true;
supportedStandardBuckets[POWER_BUCKET_SCREEN_DOZE] = false;
supportedStandardBuckets[POWER_BUCKET_SCREEN_OTHER] = true;
- final MeasuredEnergyStats stats =
- new MeasuredEnergyStats(supportedStandardBuckets, customBucketNames);
+ final MeasuredEnergyStats.Config config =
+ new MeasuredEnergyStats.Config(supportedStandardBuckets, customBucketNames,
+ new int[0], new String[]{"s"});
+ final MeasuredEnergyStats stats = new MeasuredEnergyStats(config);
+
stats.updateStandardBucket(POWER_BUCKET_SCREEN_ON, 10);
stats.updateStandardBucket(POWER_BUCKET_SCREEN_ON, 5);
stats.updateStandardBucket(POWER_BUCKET_SCREEN_OTHER, 40);
@@ -317,11 +300,11 @@
stats.updateCustomBucket(1, 60);
final Parcel parcel = Parcel.obtain();
- MeasuredEnergyStats.writeSummaryToParcel(stats, parcel, false, true);
+ MeasuredEnergyStats.writeSummaryToParcel(stats, parcel);
parcel.setDataPosition(0);
MeasuredEnergyStats newStats =
- MeasuredEnergyStats.createAndReadSummaryFromParcel(parcel, null);
+ MeasuredEnergyStats.createAndReadSummaryFromParcel(null, parcel);
assertNull(newStats);
parcel.recycle();
}
@@ -334,30 +317,30 @@
supportedStandardBuckets[POWER_BUCKET_SCREEN_DOZE] = false;
supportedStandardBuckets[POWER_BUCKET_SCREEN_OTHER] = true;
- final MeasuredEnergyStats template =
- new MeasuredEnergyStats(supportedStandardBuckets, customBucketNames);
- template.updateStandardBucket(POWER_BUCKET_SCREEN_ON, 10);
- template.updateStandardBucket(POWER_BUCKET_SCREEN_ON, 5);
- template.updateStandardBucket(POWER_BUCKET_SCREEN_OTHER, 40);
- template.updateCustomBucket(0, 50);
+ final MeasuredEnergyStats.Config config =
+ new MeasuredEnergyStats.Config(supportedStandardBuckets, customBucketNames,
+ new int[0], new String[]{"s"});
+ final MeasuredEnergyStats stats = new MeasuredEnergyStats(config);
- final MeasuredEnergyStats stats = MeasuredEnergyStats.createFromTemplate(template);
- stats.updateStandardBucket(POWER_BUCKET_SCREEN_ON, 0L);
- stats.updateStandardBucket(POWER_BUCKET_SCREEN_OTHER, 7L);
+ stats.updateStandardBucket(POWER_BUCKET_SCREEN_ON, 0);
+ stats.updateStandardBucket(POWER_BUCKET_SCREEN_OTHER, 40);
final Parcel parcel = Parcel.obtain();
- MeasuredEnergyStats.writeSummaryToParcel(stats, parcel, false, true);
+ MeasuredEnergyStats.writeSummaryToParcel(stats, parcel);
final boolean[] newSupportedStandardBuckets = new boolean[NUMBER_STANDARD_POWER_BUCKETS];
newSupportedStandardBuckets[POWER_BUCKET_SCREEN_ON] = true;
newSupportedStandardBuckets[POWER_BUCKET_SCREEN_DOZE] = true; // switched false > true
newSupportedStandardBuckets[POWER_BUCKET_SCREEN_OTHER] = false; // switched true > false
- final MeasuredEnergyStats newTemplate =
- new MeasuredEnergyStats(newSupportedStandardBuckets, customBucketNames);
+ final MeasuredEnergyStats.Config newConfig =
+ new MeasuredEnergyStats.Config(newSupportedStandardBuckets, customBucketNames,
+ new int[0], new String[]{"s"});
+
parcel.setDataPosition(0);
final MeasuredEnergyStats newStats =
- MeasuredEnergyStats.createAndReadSummaryFromParcel(parcel, newTemplate);
+ MeasuredEnergyStats.createAndReadSummaryFromParcel(newConfig, parcel);
+
// The only non-0 entry in stats is no longer supported, so now there's no interesting data.
assertNull(newStats);
assertEquals("Parcel was not properly consumed", 0, parcel.dataAvail());
@@ -372,30 +355,47 @@
supportedStandardBuckets[POWER_BUCKET_SCREEN_DOZE] = false;
supportedStandardBuckets[POWER_BUCKET_SCREEN_OTHER] = true;
- final MeasuredEnergyStats stats =
- new MeasuredEnergyStats(supportedStandardBuckets, customBucketNames);
- stats.updateStandardBucket(POWER_BUCKET_SCREEN_ON, 10);
- stats.updateStandardBucket(POWER_BUCKET_SCREEN_DOZE, 30);
- stats.updateStandardBucket(POWER_BUCKET_SCREEN_OTHER, 40);
- stats.updateStandardBucket(POWER_BUCKET_SCREEN_ON, 5);
+ final MeasuredEnergyStats.Config config =
+ new MeasuredEnergyStats.Config(supportedStandardBuckets, customBucketNames,
+ new int[]{POWER_BUCKET_SCREEN_ON, POWER_BUCKET_SCREEN_OTHER},
+ new String[]{"s0", "s1"});
+ final MeasuredEnergyStats stats = new MeasuredEnergyStats(config);
- stats.updateCustomBucket(0, 50);
- stats.updateCustomBucket(1, 60);
- stats.updateCustomBucket(0, 3);
+ stats.setState(0, 1000);
+ stats.updateStandardBucket(POWER_BUCKET_SCREEN_ON, 10, 2000);
+ stats.updateStandardBucket(POWER_BUCKET_SCREEN_DOZE, 30, 3000);
+ stats.setState(1, 4000);
+ stats.updateStandardBucket(POWER_BUCKET_SCREEN_OTHER, 40, 5000);
+ stats.updateStandardBucket(POWER_BUCKET_SCREEN_ON, 6, 6000);
- assertEquals(15, stats.getAccumulatedStandardBucketCharge(POWER_BUCKET_SCREEN_ON));
+ stats.updateCustomBucket(0, 50, 7000);
+ stats.updateCustomBucket(1, 60, 8000);
+ stats.updateCustomBucket(0, 3, 9000);
+
+ assertEquals(16, stats.getAccumulatedStandardBucketCharge(POWER_BUCKET_SCREEN_ON));
assertEquals(POWER_DATA_UNAVAILABLE,
stats.getAccumulatedStandardBucketCharge(POWER_BUCKET_SCREEN_DOZE));
assertEquals(40, stats.getAccumulatedStandardBucketCharge(POWER_BUCKET_SCREEN_OTHER));
assertEquals(50 + 3, stats.getAccumulatedCustomBucketCharge(0));
assertEquals(60, stats.getAccumulatedCustomBucketCharge(1));
+
+ // 10 + 6 * (4000-2000)/(6000-2000)
+ assertEquals(13, stats.getAccumulatedStandardBucketCharge(POWER_BUCKET_SCREEN_ON, 0));
+ // 6 * (6000-4000)/(6000-2000)
+ assertEquals(3, stats.getAccumulatedStandardBucketCharge(POWER_BUCKET_SCREEN_ON, 1));
+
+ // POWER_BUCKET_SCREEN_OTHER was only present along with state=1
+ assertEquals(0, stats.getAccumulatedStandardBucketCharge(POWER_BUCKET_SCREEN_OTHER, 0));
+ assertEquals(40, stats.getAccumulatedStandardBucketCharge(POWER_BUCKET_SCREEN_OTHER, 1));
}
@Test
public void testIsValidCustomBucket() {
- final MeasuredEnergyStats stats =
- new MeasuredEnergyStats(new boolean[NUMBER_STANDARD_POWER_BUCKETS],
- new String[]{"A", "B", "C"});
+ final MeasuredEnergyStats.Config config =
+ new MeasuredEnergyStats.Config(new boolean[NUMBER_STANDARD_POWER_BUCKETS],
+ new String[]{"A", "B", "C"},
+ new int[0], new String[]{"s"});
+ final MeasuredEnergyStats stats = new MeasuredEnergyStats(config);
assertFalse(stats.isValidCustomBucket(-1));
assertTrue(stats.isValidCustomBucket(0));
assertTrue(stats.isValidCustomBucket(1));
@@ -403,8 +403,10 @@
assertFalse(stats.isValidCustomBucket(3));
assertFalse(stats.isValidCustomBucket(4));
- final MeasuredEnergyStats boringStats =
- new MeasuredEnergyStats(new boolean[NUMBER_STANDARD_POWER_BUCKETS], new String[0]);
+ final MeasuredEnergyStats.Config boringConfig =
+ new MeasuredEnergyStats.Config(new boolean[NUMBER_STANDARD_POWER_BUCKETS],
+ new String[0], new int[0], new String[]{"s"});
+ final MeasuredEnergyStats boringStats = new MeasuredEnergyStats(boringConfig);
assertFalse(boringStats.isValidCustomBucket(-1));
assertFalse(boringStats.isValidCustomBucket(0));
assertFalse(boringStats.isValidCustomBucket(1));
@@ -412,9 +414,11 @@
@Test
public void testGetAccumulatedCustomBucketCharges() {
- final MeasuredEnergyStats stats =
- new MeasuredEnergyStats(new boolean[NUMBER_STANDARD_POWER_BUCKETS],
- new String[]{"A", "B", "C"});
+ final MeasuredEnergyStats.Config config =
+ new MeasuredEnergyStats.Config(new boolean[NUMBER_STANDARD_POWER_BUCKETS],
+ new String[]{"A", "B", "C"},
+ new int[0], new String[]{"s"});
+ final MeasuredEnergyStats stats = new MeasuredEnergyStats(config);
stats.updateCustomBucket(0, 50);
stats.updateCustomBucket(1, 60);
stats.updateCustomBucket(2, 13);
@@ -430,8 +434,10 @@
@Test
public void testGetAccumulatedCustomBucketCharges_empty() {
- final MeasuredEnergyStats stats =
- new MeasuredEnergyStats(new boolean[NUMBER_STANDARD_POWER_BUCKETS], new String[0]);
+ final MeasuredEnergyStats.Config config =
+ new MeasuredEnergyStats.Config(new boolean[NUMBER_STANDARD_POWER_BUCKETS],
+ new String[0], new int[0], new String[]{"s"});
+ final MeasuredEnergyStats stats = new MeasuredEnergyStats(config);
final long[] output = stats.getAccumulatedCustomBucketCharges();
assertEquals(0, output.length);
@@ -440,10 +446,15 @@
@Test
public void testGetNumberCustomChargeBuckets() {
assertEquals(0,
- new MeasuredEnergyStats(new boolean[NUMBER_STANDARD_POWER_BUCKETS], new String[0])
+ new MeasuredEnergyStats(
+ new MeasuredEnergyStats.Config(new boolean[NUMBER_STANDARD_POWER_BUCKETS],
+ new String[0], new int[0], new String[]{"s"}))
.getNumberCustomPowerBuckets());
- assertEquals(3, new MeasuredEnergyStats(new boolean[NUMBER_STANDARD_POWER_BUCKETS],
- new String[]{"A", "B", "C"}).getNumberCustomPowerBuckets());
+ assertEquals(3,
+ new MeasuredEnergyStats(
+ new MeasuredEnergyStats.Config(new boolean[NUMBER_STANDARD_POWER_BUCKETS],
+ new String[]{"A", "B", "C"}, new int[0], new String[]{"s"}))
+ .getNumberCustomPowerBuckets());
}
@Test
@@ -454,8 +465,10 @@
supportedStandardBuckets[POWER_BUCKET_SCREEN_DOZE] = false;
supportedStandardBuckets[POWER_BUCKET_SCREEN_OTHER] = true;
- final MeasuredEnergyStats stats =
- new MeasuredEnergyStats(supportedStandardBuckets, customBucketNames);
+ final MeasuredEnergyStats.Config config =
+ new MeasuredEnergyStats.Config(supportedStandardBuckets, customBucketNames,
+ new int[0], new String[]{"s"});
+ final MeasuredEnergyStats stats = new MeasuredEnergyStats(config);
stats.updateStandardBucket(POWER_BUCKET_SCREEN_ON, 10);
stats.updateStandardBucket(POWER_BUCKET_SCREEN_ON, 5);
stats.updateStandardBucket(POWER_BUCKET_SCREEN_OTHER, 40);
@@ -500,83 +513,62 @@
assertEquals(exp, MeasuredEnergyStats.getDisplayPowerBucket(Display.STATE_DOZE_SUSPEND));
}
- /** Test MeasuredEnergyStats#isSupportEqualTo */
@Test
- public void testIsSupportEqualTo() {
+ public void testConfig_isCompatible() {
final boolean[] supportedStandardBuckets = new boolean[NUMBER_STANDARD_POWER_BUCKETS];
Arrays.fill(supportedStandardBuckets, true);
final String[] customBucketNames = {"A", "B"};
+ final int[] supportedMultiStateBuckets = {POWER_BUCKET_CPU, POWER_BUCKET_WIFI};
+ final String[] stateNames = {"s"};
- final MeasuredEnergyStats stats =
- new MeasuredEnergyStats(supportedStandardBuckets.clone(),
- customBucketNames.clone());
-
+ final MeasuredEnergyStats.Config config = new MeasuredEnergyStats.Config(
+ supportedStandardBuckets,
+ customBucketNames,
+ supportedMultiStateBuckets,
+ stateNames);
assertTrue(
"All standard and custom bucket supports match",
- stats.isSupportEqualTo(supportedStandardBuckets, customBucketNames));
+ config.isCompatible(
+ new MeasuredEnergyStats.Config(
+ supportedStandardBuckets,
+ customBucketNames,
+ supportedMultiStateBuckets,
+ stateNames)));
boolean[] differentSupportedStandardBuckets = supportedStandardBuckets.clone();
differentSupportedStandardBuckets[0] = !differentSupportedStandardBuckets[0];
+
assertFalse(
"Standard bucket support mismatch",
- stats.isSupportEqualTo(differentSupportedStandardBuckets, customBucketNames));
-
+ config.isCompatible(
+ new MeasuredEnergyStats.Config(
+ differentSupportedStandardBuckets,
+ customBucketNames,
+ supportedMultiStateBuckets,
+ stateNames)));
assertFalse(
"Custom bucket support mismatch",
- stats.isSupportEqualTo(supportedStandardBuckets, new String[]{"C", "B"}));
-
+ config.isCompatible(
+ new MeasuredEnergyStats.Config(
+ supportedStandardBuckets,
+ new String[]{"C", "B"},
+ supportedMultiStateBuckets,
+ stateNames)));
assertFalse(
- "Fewer custom buckets supported",
- stats.isSupportEqualTo(supportedStandardBuckets, new String[]{"A"}));
-
+ "Multi-state bucket mismatch",
+ config.isCompatible(
+ new MeasuredEnergyStats.Config(
+ supportedStandardBuckets,
+ new String[]{"A"},
+ new int[] {POWER_BUCKET_CPU, POWER_BUCKET_BLUETOOTH},
+ stateNames)));
assertFalse(
- "More custom bucket supported",
- stats.isSupportEqualTo(supportedStandardBuckets, new String[]{"A", "B", "C"}));
-
- assertFalse(
- "Custom bucket support order changed",
- stats.isSupportEqualTo(supportedStandardBuckets, new String[]{"B", "A"}));
- }
-
- /** Test MeasuredEnergyStats#isSupportEqualTo when holding a null array of custom buckets */
- @Test
- public void testIsSupportEqualTo_nullCustomBuckets() {
- final boolean[] supportedStandardBuckets = new boolean[NUMBER_STANDARD_POWER_BUCKETS];
-
- final MeasuredEnergyStats stats =
- new MeasuredEnergyStats(supportedStandardBuckets.clone(), null);
-
- assertTrue(
- "Null custom bucket name lists should match",
- stats.isSupportEqualTo(supportedStandardBuckets, null));
-
- assertTrue(
- "Null and empty custom buckets should match",
- stats.isSupportEqualTo(supportedStandardBuckets, new String[0]));
-
- assertFalse(
- "Null custom buckets should not match populated list",
- stats.isSupportEqualTo(supportedStandardBuckets, new String[]{"A", "B"}));
- }
-
- /** Test MeasuredEnergyStats#isSupportEqualTo when holding an empty array of custom buckets */
- @Test
- public void testIsSupportEqualTo_emptyCustomBuckets() {
- final boolean[] supportedStandardBuckets = new boolean[NUMBER_STANDARD_POWER_BUCKETS];
-
- final MeasuredEnergyStats stats =
- new MeasuredEnergyStats(supportedStandardBuckets.clone(), new String[0]);
-
- assertTrue(
- "Empty custom buckets should match",
- stats.isSupportEqualTo(supportedStandardBuckets, new String[0]));
-
- assertTrue(
- "Empty and null custom buckets should match",
- stats.isSupportEqualTo(supportedStandardBuckets, null));
-
- assertFalse(
- "Empty custom buckets should not match populated list",
- stats.isSupportEqualTo(supportedStandardBuckets, new String[]{"A", "B"}));
+ "Multi-state bucket state list mismatch",
+ config.isCompatible(
+ new MeasuredEnergyStats.Config(
+ supportedStandardBuckets,
+ new String[]{"A"},
+ supportedMultiStateBuckets,
+ new String[]{"s1", "s2"})));
}
}
diff --git a/data/etc/privapp-permissions-platform.xml b/data/etc/privapp-permissions-platform.xml
index 25fb223..33cc61b 100644
--- a/data/etc/privapp-permissions-platform.xml
+++ b/data/etc/privapp-permissions-platform.xml
@@ -425,6 +425,7 @@
<permission name="android.permission.MODIFY_DEFAULT_AUDIO_EFFECTS"/>
<!-- Permissions required for CTS test - TunerTest -->
<permission name="android.permission.ACCESS_TV_DESCRAMBLER" />
+ <permission name="android.permission.ACCESS_TV_SHARED_FILTER" />
<permission name="android.permission.ACCESS_TV_TUNER" />
<permission name="android.permission.TUNER_RESOURCE_ACCESS" />
<!-- Permissions required for CTS test - TVInputManagerTest -->
diff --git a/data/etc/services.core.protolog.json b/data/etc/services.core.protolog.json
index 6e92755..8b37805 100644
--- a/data/etc/services.core.protolog.json
+++ b/data/etc/services.core.protolog.json
@@ -1561,6 +1561,12 @@
"group": "WM_DEBUG_ORIENTATION",
"at": "com\/android\/server\/wm\/DisplayRotation.java"
},
+ "-436553282": {
+ "message": "Remove sleep token: tag=%s, displayId=%d",
+ "level": "DEBUG",
+ "group": "WM_DEBUG_STATES",
+ "at": "com\/android\/server\/wm\/RootWindowContainer.java"
+ },
"-415865166": {
"message": "findFocusedWindow: Found new focus @ %s",
"level": "VERBOSE",
@@ -1669,6 +1675,12 @@
"group": "WM_DEBUG_ADD_REMOVE",
"at": "com\/android\/server\/wm\/WindowState.java"
},
+ "-317761482": {
+ "message": "Create sleep token: tag=%s, displayId=%d",
+ "level": "DEBUG",
+ "group": "WM_DEBUG_STATES",
+ "at": "com\/android\/server\/wm\/RootWindowContainer.java"
+ },
"-317194205": {
"message": "clearLockedTasks: %s",
"level": "INFO",
diff --git a/libs/WindowManager/Jetpack/src/androidx/window/extensions/embedding/SplitController.java b/libs/WindowManager/Jetpack/src/androidx/window/extensions/embedding/SplitController.java
index 42b4380..20515e7 100644
--- a/libs/WindowManager/Jetpack/src/androidx/window/extensions/embedding/SplitController.java
+++ b/libs/WindowManager/Jetpack/src/androidx/window/extensions/embedding/SplitController.java
@@ -516,12 +516,8 @@
// Skipping containers that do not have any activities to report.
continue;
}
- ActivityStack primaryContainer =
- new ActivityStack(
- container.getPrimaryContainer().collectActivities());
- ActivityStack secondaryContainer =
- new ActivityStack(
- container.getSecondaryContainer().collectActivities());
+ ActivityStack primaryContainer = container.getPrimaryContainer().toActivityStack();
+ ActivityStack secondaryContainer = container.getSecondaryContainer().toActivityStack();
SplitInfo splitState = new SplitInfo(primaryContainer,
secondaryContainer,
// Splits that are not showing side-by-side are reported as having 0 split
diff --git a/libs/WindowManager/Jetpack/src/androidx/window/extensions/embedding/TaskFragmentContainer.java b/libs/WindowManager/Jetpack/src/androidx/window/extensions/embedding/TaskFragmentContainer.java
index 54e44a7..80d9c2c 100644
--- a/libs/WindowManager/Jetpack/src/androidx/window/extensions/embedding/TaskFragmentContainer.java
+++ b/libs/WindowManager/Jetpack/src/androidx/window/extensions/embedding/TaskFragmentContainer.java
@@ -109,6 +109,10 @@
return allActivities;
}
+ ActivityStack toActivityStack() {
+ return new ActivityStack(collectActivities(), mInfo.getRunningActivityCount() == 0);
+ }
+
void addPendingAppearedActivity(@NonNull Activity pendingAppearedActivity) {
mPendingAppearedActivities.add(pendingAppearedActivity);
}
diff --git a/libs/WindowManager/Jetpack/window-extensions-release.aar b/libs/WindowManager/Jetpack/window-extensions-release.aar
index 4f36c9c..830d13d 100644
--- a/libs/WindowManager/Jetpack/window-extensions-release.aar
+++ b/libs/WindowManager/Jetpack/window-extensions-release.aar
Binary files differ
diff --git a/packages/SystemUI/res/layout/udfps_surface_view.xml b/libs/WindowManager/Shell/res/layout/split_decor.xml
similarity index 61%
rename from packages/SystemUI/res/layout/udfps_surface_view.xml
rename to libs/WindowManager/Shell/res/layout/split_decor.xml
index 18858d6..9ffa5e8 100644
--- a/packages/SystemUI/res/layout/udfps_surface_view.xml
+++ b/libs/WindowManager/Shell/res/layout/split_decor.xml
@@ -1,4 +1,3 @@
-<?xml version="1.0" encoding="utf-8"?>
<!--
~ Copyright (C) 2021 The Android Open Source Project
~
@@ -14,8 +13,18 @@
~ See the License for the specific language governing permissions and
~ limitations under the License.
-->
-<com.android.systemui.biometrics.UdfpsSurfaceView
+
+<FrameLayout
xmlns:android="http://schemas.android.com/apk/res/android"
- android:id="@+id/udfps_surface_view"
- android:layout_width="match_parent"
- android:layout_height="match_parent"/>
+ android:layout_height="match_parent"
+ android:layout_width="match_parent">
+
+ <ImageView android:id="@+id/split_resizing_icon"
+ android:layout_height="wrap_content"
+ android:layout_width="wrap_content"
+ android:layout_gravity="center"
+ android:padding="0dp"
+ android:visibility="gone"
+ android:background="@null"/>
+
+</FrameLayout>
diff --git a/libs/WindowManager/Shell/res/layout/split_outline.xml b/libs/WindowManager/Shell/res/layout/split_outline.xml
index 13a30f5..6cb9ebb 100644
--- a/libs/WindowManager/Shell/res/layout/split_outline.xml
+++ b/libs/WindowManager/Shell/res/layout/split_outline.xml
@@ -1,18 +1,19 @@
<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2021 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.
--->
+<!--
+ ~ Copyright (C) 2021 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.
+ -->
<FrameLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
diff --git a/libs/WindowManager/Shell/res/values-land/styles.xml b/libs/WindowManager/Shell/res/values-land/styles.xml
index 9eddac4..0ed9368 100644
--- a/libs/WindowManager/Shell/res/values-land/styles.xml
+++ b/libs/WindowManager/Shell/res/values-land/styles.xml
@@ -23,7 +23,7 @@
</style>
<style name="DockedDividerHandle">
- <item name="android:layout_gravity">center_vertical</item>
+ <item name="android:layout_gravity">center</item>
<item name="android:layout_width">48dp</item>
<item name="android:layout_height">96dp</item>
</style>
diff --git a/libs/WindowManager/Shell/res/values/styles.xml b/libs/WindowManager/Shell/res/values/styles.xml
index cb6d4de..7733201 100644
--- a/libs/WindowManager/Shell/res/values/styles.xml
+++ b/libs/WindowManager/Shell/res/values/styles.xml
@@ -43,7 +43,7 @@
</style>
<style name="DockedDividerHandle">
- <item name="android:layout_gravity">center_horizontal</item>
+ <item name="android:layout_gravity">center</item>
<item name="android:layout_width">96dp</item>
<item name="android:layout_height">48dp</item>
</style>
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/ShellCommandHandlerImpl.java b/libs/WindowManager/Shell/src/com/android/wm/shell/ShellCommandHandlerImpl.java
index 9113c79..e87b150 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/ShellCommandHandlerImpl.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/ShellCommandHandlerImpl.java
@@ -103,8 +103,6 @@
return runMoveToSideStage(args, pw);
case "removeFromSideStage":
return runRemoveFromSideStage(args, pw);
- case "setSideStageOutline":
- return runSetSideStageOutline(args, pw);
case "setSideStagePosition":
return runSetSideStagePosition(args, pw);
case "setSideStageVisibility":
@@ -163,18 +161,6 @@
return true;
}
- private boolean runSetSideStageOutline(String[] args, PrintWriter pw) {
- if (args.length < 3) {
- // First arguments are "WMShell" and command name.
- pw.println("Error: whether to enable or disable side stage outline border should be"
- + " provided as arguments");
- return false;
- }
- final boolean enable = new Boolean(args[2]);
- mSplitScreenOptional.ifPresent(split -> split.setSideStageOutline(enable));
- return true;
- }
-
private boolean runSetSideStagePosition(String[] args, PrintWriter pw) {
if (args.length < 3) {
// First arguments are "WMShell" and command name.
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/apppairs/AppPair.java b/libs/WindowManager/Shell/src/com/android/wm/shell/apppairs/AppPair.java
index 6a252e0..c8449a3 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/apppairs/AppPair.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/apppairs/AppPair.java
@@ -131,7 +131,8 @@
mSplitLayout = new SplitLayout(TAG + "SplitDivider",
mDisplayController.getDisplayContext(mRootTaskInfo.displayId),
mRootTaskInfo.configuration, this /* layoutChangeListener */,
- mParentContainerCallbacks, mDisplayImeController, mController.getTaskOrganizer());
+ mParentContainerCallbacks, mDisplayImeController, mController.getTaskOrganizer(),
+ true /* applyDismissingParallax */);
mDisplayInsetsController.addInsetsChangedListener(mRootTaskInfo.displayId, mSplitLayout);
final WindowContainerToken token1 = task1.token;
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/back/BackPreviewHandler.java b/libs/WindowManager/Shell/src/com/android/wm/shell/back/BackPreviewHandler.java
new file mode 100644
index 0000000..dc20f7b
--- /dev/null
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/back/BackPreviewHandler.java
@@ -0,0 +1,41 @@
+/*
+ * Copyright (C) 2021 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.back;
+
+import android.os.SystemProperties;
+import android.view.IWindowManager;
+
+import javax.inject.Inject;
+
+/**
+ * Handle the preview of what a back gesture will lead to.
+ */
+public class BackPreviewHandler {
+
+ private static final String BACK_PREDICTABILITY_PROP = "persist.debug.back_predictability";
+
+ public static boolean isEnabled() {
+ return SystemProperties.getInt(BACK_PREDICTABILITY_PROP, 0) > 0;
+ }
+
+ private final IWindowManager mWmService;
+
+ @Inject
+ public BackPreviewHandler(IWindowManager windowManagerService) {
+ mWmService = windowManagerService;
+ }
+}
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/common/DisplayLayout.java b/libs/WindowManager/Shell/src/com/android/wm/shell/common/DisplayLayout.java
index 962aca1..7784665 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/common/DisplayLayout.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/common/DisplayLayout.java
@@ -48,9 +48,11 @@
import android.view.InsetsSource;
import android.view.InsetsState;
import android.view.Surface;
-import android.view.WindowInsets;
+
+import androidx.annotation.VisibleForTesting;
import com.android.internal.R;
+import com.android.internal.policy.SystemBarUtils;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
@@ -198,12 +200,13 @@
recalcInsets(res);
}
- private void recalcInsets(Resources res) {
+ @VisibleForTesting
+ void recalcInsets(Resources res) {
computeNonDecorInsets(res, mRotation, mWidth, mHeight, mCutout, mInsetsState, mUiMode,
mNonDecorInsets, mHasNavigationBar);
mStableInsets.set(mNonDecorInsets);
if (mHasStatusBar) {
- convertNonDecorInsetsToStableInsets(res, mStableInsets, mWidth, mHeight, mHasStatusBar);
+ convertNonDecorInsetsToStableInsets(res, mStableInsets, mCutout, mHasStatusBar);
}
mNavBarFrameHeight = getNavigationBarFrameHeight(res, mWidth > mHeight);
}
@@ -323,12 +326,12 @@
/**
* Calculates the stable insets if we already have the non-decor insets.
*/
- private static void convertNonDecorInsetsToStableInsets(Resources res, Rect inOutInsets,
- int displayWidth, int displayHeight, boolean hasStatusBar) {
+ private void convertNonDecorInsetsToStableInsets(Resources res, Rect inOutInsets,
+ DisplayCutout cutout, boolean hasStatusBar) {
if (!hasStatusBar) {
return;
}
- int statusBarHeight = getStatusBarHeight(displayWidth > displayHeight, res);
+ int statusBarHeight = SystemBarUtils.getStatusBarHeight(res, cutout);
inOutInsets.top = Math.max(inOutInsets.top, statusBarHeight);
}
@@ -377,35 +380,6 @@
}
}
- /**
- * Calculates the stable insets without running a layout.
- *
- * @param displayRotation the current display rotation
- * @param displayWidth the current display width
- * @param displayHeight the current display height
- * @param displayCutout the current display cutout
- * @param outInsets the insets to return
- */
- static void computeStableInsets(Resources res, int displayRotation, int displayWidth,
- int displayHeight, DisplayCutout displayCutout, InsetsState insetsState, int uiMode,
- Rect outInsets, boolean hasNavigationBar, boolean hasStatusBar) {
- outInsets.setEmpty();
-
- // Navigation bar and status bar.
- computeNonDecorInsets(res, displayRotation, displayWidth, displayHeight, displayCutout,
- insetsState, uiMode, outInsets, hasNavigationBar);
- convertNonDecorInsetsToStableInsets(res, outInsets, displayWidth, displayHeight,
- hasStatusBar);
- }
-
- /** Retrieve the statusbar height from resources. */
- static int getStatusBarHeight(boolean landscape, Resources res) {
- return landscape ? res.getDimensionPixelSize(
- com.android.internal.R.dimen.status_bar_height_landscape)
- : res.getDimensionPixelSize(
- com.android.internal.R.dimen.status_bar_height_portrait);
- }
-
/** Calculate the DisplayCutout for a particular display size/rotation. */
public static DisplayCutout calculateDisplayCutoutForRotation(
DisplayCutout cutout, int rotation, int displayWidth, int displayHeight) {
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/common/SurfaceUtils.java b/libs/WindowManager/Shell/src/com/android/wm/shell/common/SurfaceUtils.java
index 55c5125..4b138e4 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/common/SurfaceUtils.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/common/SurfaceUtils.java
@@ -23,16 +23,22 @@
* Helpers for handling surface.
*/
public class SurfaceUtils {
- /** Creates a dim layer above indicated host surface. */
+ /** Creates a dim layer above host surface. */
public static SurfaceControl makeDimLayer(SurfaceControl.Transaction t, SurfaceControl host,
String name, SurfaceSession surfaceSession) {
- SurfaceControl dimLayer = new SurfaceControl.Builder(surfaceSession)
+ final SurfaceControl dimLayer = makeColorLayer(host, name, surfaceSession);
+ t.setLayer(dimLayer, Integer.MAX_VALUE).setColor(dimLayer, new float[]{0f, 0f, 0f});
+ return dimLayer;
+ }
+
+ /** Creates a color layer for host surface. */
+ public static SurfaceControl makeColorLayer(SurfaceControl host, String name,
+ SurfaceSession surfaceSession) {
+ return new SurfaceControl.Builder(surfaceSession)
.setParent(host)
.setColorLayer()
.setName(name)
- .setCallsite("SurfaceUtils.makeDimLayer")
+ .setCallsite("SurfaceUtils.makeColorLayer")
.build();
- t.setLayer(dimLayer, Integer.MAX_VALUE).setColor(dimLayer, new float[]{0f, 0f, 0f});
- return dimLayer;
}
}
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/common/split/DividerView.java b/libs/WindowManager/Shell/src/com/android/wm/shell/common/split/DividerView.java
index 6ea806b..4b125b1 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/common/split/DividerView.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/common/split/DividerView.java
@@ -19,6 +19,8 @@
import static android.content.res.Configuration.ORIENTATION_LANDSCAPE;
import static android.view.WindowManager.LayoutParams.FLAG_SLIPPERY;
+import android.animation.Animator;
+import android.animation.AnimatorListenerAdapter;
import android.animation.ObjectAnimator;
import android.content.Context;
import android.graphics.Rect;
@@ -57,6 +59,7 @@
private final int mTouchSlop = ViewConfiguration.get(getContext()).getScaledTouchSlop();
private SplitLayout mSplitLayout;
+ private SplitWindowManager mSplitWindowManager;
private SurfaceControlViewHost mViewHost;
private DividerHandleView mHandle;
private View mBackground;
@@ -67,6 +70,7 @@
private int mStartPos;
private GestureDetector mDoubleTapDetector;
private boolean mInteractive;
+ private boolean mSetTouchRegion = true;
/**
* Tracks divider bar visible bounds in screen-based coordination. Used to calculate with
@@ -93,6 +97,18 @@
}
};
+ private AnimatorListenerAdapter mAnimatorListener = new AnimatorListenerAdapter() {
+ @Override
+ public void onAnimationEnd(Animator animation) {
+ mSetTouchRegion = true;
+ }
+
+ @Override
+ public void onAnimationCancel(Animator animation) {
+ mSetTouchRegion = true;
+ }
+ };
+
public DividerView(@NonNull Context context) {
super(context);
}
@@ -114,9 +130,11 @@
/** Sets up essential dependencies of the divider bar. */
public void setup(
SplitLayout layout,
+ SplitWindowManager splitWindowManager,
SurfaceControlViewHost viewHost,
InsetsState insetsState) {
mSplitLayout = layout;
+ mSplitWindowManager = splitWindowManager;
mViewHost = viewHost;
mDividerBounds.set(layout.getDividerBounds());
onInsetsChanged(insetsState, false /* animate */);
@@ -138,9 +156,11 @@
DIVIDER_HEIGHT_PROPERTY, mDividerBounds.height(), mTempRect.height());
animator.setInterpolator(InsetsController.RESIZE_INTERPOLATOR);
animator.setDuration(InsetsController.ANIMATION_DURATION_RESIZE);
+ animator.addListener(mAnimatorListener);
animator.start();
} else {
DIVIDER_HEIGHT_PROPERTY.set(this, mTempRect.height());
+ mSetTouchRegion = true;
}
mDividerBounds.set(mTempRect);
}
@@ -162,6 +182,17 @@
}
@Override
+ protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
+ super.onLayout(changed, left, top, right, bottom);
+ if (mSetTouchRegion) {
+ mTempRect.set(mHandle.getLeft(), mHandle.getTop(), mHandle.getRight(),
+ mHandle.getBottom());
+ mSplitWindowManager.setTouchRegion(mTempRect);
+ mSetTouchRegion = false;
+ }
+ }
+
+ @Override
public boolean onTouch(View v, MotionEvent event) {
if (mSplitLayout == null || !mInteractive) {
return false;
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
new file mode 100644
index 0000000..ad9ebb2
--- /dev/null
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/common/split/SplitDecorManager.java
@@ -0,0 +1,184 @@
+/*
+ * Copyright (C) 2021 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.common.split;
+
+import static android.view.WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE;
+import static android.view.WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE;
+import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_NO_MOVE_ANIMATION;
+import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_TRUSTED_OVERLAY;
+import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION_OVERLAY;
+import static android.view.WindowManagerPolicyConstants.SPLIT_DIVIDER_LAYER;
+
+import android.app.ActivityManager;
+import android.content.Context;
+import android.content.res.Configuration;
+import android.graphics.Color;
+import android.graphics.PixelFormat;
+import android.graphics.Rect;
+import android.graphics.drawable.Drawable;
+import android.os.Binder;
+import android.view.IWindow;
+import android.view.LayoutInflater;
+import android.view.SurfaceControl;
+import android.view.SurfaceControlViewHost;
+import android.view.SurfaceSession;
+import android.view.View;
+import android.view.WindowManager;
+import android.view.WindowlessWindowManager;
+import android.widget.FrameLayout;
+import android.widget.ImageView;
+
+import com.android.launcher3.icons.IconProvider;
+import com.android.wm.shell.R;
+import com.android.wm.shell.common.SurfaceUtils;
+
+/**
+ * Handles split decor like showing resizing hint for a specific split.
+ */
+public class SplitDecorManager extends WindowlessWindowManager {
+ private static final String TAG = SplitDecorManager.class.getSimpleName();
+ private static final String RESIZING_BACKGROUND_SURFACE_NAME = "ResizingBackground";
+
+ private final IconProvider mIconProvider;
+ private final SurfaceSession mSurfaceSession;
+
+ private Drawable mIcon;
+ private ImageView mResizingIconView;
+ private SurfaceControlViewHost mViewHost;
+ private SurfaceControl mHostLeash;
+ private SurfaceControl mIconLeash;
+ private SurfaceControl mBackgroundLeash;
+
+ public SplitDecorManager(Configuration configuration, IconProvider iconProvider,
+ SurfaceSession surfaceSession) {
+ super(configuration, null /* rootSurface */, null /* hostInputToken */);
+ mIconProvider = iconProvider;
+ mSurfaceSession = surfaceSession;
+ }
+
+ @Override
+ protected void attachToParentSurface(IWindow window, SurfaceControl.Builder b) {
+ // Can't set position for the ViewRootImpl SC directly. Create a leash to manipulate later.
+ final SurfaceControl.Builder builder = new SurfaceControl.Builder(new SurfaceSession())
+ .setContainerLayer()
+ .setName(TAG)
+ .setHidden(true)
+ .setParent(mHostLeash)
+ .setCallsite("SplitDecorManager#attachToParentSurface");
+ mIconLeash = builder.build();
+ b.setParent(mIconLeash);
+ }
+
+ /** Inflates split decor surface on the root surface. */
+ public void inflate(Context context, SurfaceControl rootLeash, Rect rootBounds) {
+ if (mIconLeash != null && mViewHost != null) {
+ return;
+ }
+
+ context = context.createWindowContext(context.getDisplay(), TYPE_APPLICATION_OVERLAY,
+ null /* options */);
+ mHostLeash = rootLeash;
+ mViewHost = new SurfaceControlViewHost(context, context.getDisplay(), this);
+
+ final FrameLayout rootLayout = (FrameLayout) LayoutInflater.from(context)
+ .inflate(R.layout.split_decor, null);
+ mResizingIconView = rootLayout.findViewById(R.id.split_resizing_icon);
+
+ final WindowManager.LayoutParams lp = new WindowManager.LayoutParams(
+ 0 /* width */, 0 /* height */, TYPE_APPLICATION_OVERLAY,
+ FLAG_NOT_FOCUSABLE | FLAG_NOT_TOUCHABLE, PixelFormat.TRANSLUCENT);
+ lp.width = rootBounds.width();
+ lp.height = rootBounds.height();
+ lp.token = new Binder();
+ lp.setTitle(TAG);
+ lp.privateFlags |= PRIVATE_FLAG_NO_MOVE_ANIMATION | PRIVATE_FLAG_TRUSTED_OVERLAY;
+ // TODO(b/189839391): Set INPUT_FEATURE_NO_INPUT_CHANNEL after WM supports
+ // TRUSTED_OVERLAY for windowless window without input channel.
+ mViewHost.setView(rootLayout, lp);
+ }
+
+ /** Releases the surfaces for split decor. */
+ public void release(SurfaceControl.Transaction t) {
+ if (mViewHost != null) {
+ mViewHost.release();
+ mViewHost = null;
+ }
+ if (mIconLeash != null) {
+ t.remove(mIconLeash);
+ mIconLeash = null;
+ }
+ if (mBackgroundLeash != null) {
+ t.remove(mBackgroundLeash);
+ mBackgroundLeash = null;
+ }
+ mHostLeash = null;
+ mIcon = null;
+ mResizingIconView = null;
+ }
+
+ /** Showing resizing hint. */
+ public void onResizing(ActivityManager.RunningTaskInfo resizingTask, Rect newBounds,
+ SurfaceControl.Transaction t) {
+ if (mResizingIconView == null) {
+ return;
+ }
+
+ if (mIcon == null) {
+ // TODO: add fade-in animation.
+ mBackgroundLeash = SurfaceUtils.makeColorLayer(mHostLeash,
+ RESIZING_BACKGROUND_SURFACE_NAME, mSurfaceSession);
+ t.setColor(mBackgroundLeash, getResizingBackgroundColor(resizingTask))
+ .setLayer(mBackgroundLeash, SPLIT_DIVIDER_LAYER - 1)
+ .show(mBackgroundLeash);
+
+ mIcon = mIconProvider.getIcon(resizingTask.topActivityInfo);
+ mResizingIconView.setImageDrawable(mIcon);
+ mResizingIconView.setVisibility(View.VISIBLE);
+
+ WindowManager.LayoutParams lp =
+ (WindowManager.LayoutParams) mViewHost.getView().getLayoutParams();
+ lp.width = mIcon.getIntrinsicWidth();
+ lp.height = mIcon.getIntrinsicHeight();
+ mViewHost.relayout(lp);
+ t.show(mIconLeash).setLayer(mIconLeash, SPLIT_DIVIDER_LAYER);
+ }
+
+ t.setPosition(mIconLeash,
+ newBounds.width() / 2 - mIcon.getIntrinsicWidth() / 2,
+ newBounds.height() / 2 - mIcon.getIntrinsicWidth() / 2);
+ }
+
+ /** Stops showing resizing hint. */
+ public void onResized(Rect newBounds, SurfaceControl.Transaction t) {
+ if (mResizingIconView == null) {
+ return;
+ }
+
+ if (mIcon != null) {
+ mResizingIconView.setVisibility(View.GONE);
+ mResizingIconView.setImageDrawable(null);
+ t.remove(mBackgroundLeash).hide(mIconLeash);
+ mIcon = null;
+ mBackgroundLeash = null;
+ }
+ }
+
+ private static float[] getResizingBackgroundColor(ActivityManager.RunningTaskInfo taskInfo) {
+ final int taskBgColor = taskInfo.taskDescription.getBackgroundColor();
+ return Color.valueOf(taskBgColor == -1 ? Color.WHITE : taskBgColor).getComponents();
+ }
+}
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/common/split/SplitLayout.java b/libs/WindowManager/Shell/src/com/android/wm/shell/common/split/SplitLayout.java
index 5b3ce2d..625bcee 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/common/split/SplitLayout.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/common/split/SplitLayout.java
@@ -40,8 +40,10 @@
import android.content.res.Resources;
import android.graphics.Point;
import android.graphics.Rect;
+import android.view.Display;
import android.view.InsetsSourceControl;
import android.view.InsetsState;
+import android.view.RoundedCorner;
import android.view.SurfaceControl;
import android.view.WindowInsets;
import android.view.WindowManager;
@@ -53,6 +55,7 @@
import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.policy.DividerSnapAlgorithm;
import com.android.internal.policy.DockedDividerUtils;
+import com.android.wm.shell.R;
import com.android.wm.shell.ShellTaskOrganizer;
import com.android.wm.shell.animation.Interpolators;
import com.android.wm.shell.common.DisplayImeController;
@@ -103,7 +106,7 @@
private final SplitWindowManager mSplitWindowManager;
private final DisplayImeController mDisplayImeController;
private final ImePositionProcessor mImePositionProcessor;
- private final DismissingParallaxPolicy mDismissingParallaxPolicy;
+ private final DismissingEffectPolicy mDismissingEffectPolicy;
private final ShellTaskOrganizer mTaskOrganizer;
private final InsetsState mInsetsState = new InsetsState();
@@ -119,7 +122,8 @@
public SplitLayout(String windowName, Context context, Configuration configuration,
SplitLayoutHandler splitLayoutHandler,
SplitWindowManager.ParentContainerCallbacks parentContainerCallbacks,
- DisplayImeController displayImeController, ShellTaskOrganizer taskOrganizer) {
+ DisplayImeController displayImeController, ShellTaskOrganizer taskOrganizer,
+ boolean applyDismissingParallax) {
mContext = context.createConfigurationContext(configuration);
mOrientation = configuration.orientation;
mRotation = configuration.windowConfiguration.getRotation();
@@ -129,20 +133,35 @@
parentContainerCallbacks);
mTaskOrganizer = taskOrganizer;
mImePositionProcessor = new ImePositionProcessor(mContext.getDisplayId());
- mDismissingParallaxPolicy = new DismissingParallaxPolicy();
+ mDismissingEffectPolicy = new DismissingEffectPolicy(applyDismissingParallax);
final Resources resources = context.getResources();
- mDividerWindowWidth = resources.getDimensionPixelSize(
- com.android.internal.R.dimen.docked_stack_divider_thickness);
- mDividerInsets = resources.getDimensionPixelSize(
- com.android.internal.R.dimen.docked_stack_divider_insets);
- mDividerSize = mDividerWindowWidth - mDividerInsets * 2;
+ mDividerSize = resources.getDimensionPixelSize(R.dimen.split_divider_bar_width);
+ mDividerInsets = getDividerInsets(resources, context.getDisplay());
+ mDividerWindowWidth = mDividerSize + 2 * mDividerInsets;
mRootBounds.set(configuration.windowConfiguration.getBounds());
mDividerSnapAlgorithm = getSnapAlgorithm(mContext, mRootBounds);
resetDividerPosition();
}
+ private int getDividerInsets(Resources resources, Display display) {
+ final int dividerInset = resources.getDimensionPixelSize(
+ com.android.internal.R.dimen.docked_stack_divider_insets);
+
+ int radius = 0;
+ RoundedCorner corner = display.getRoundedCorner(RoundedCorner.POSITION_TOP_LEFT);
+ radius = corner != null ? Math.max(radius, corner.getRadius()) : radius;
+ corner = display.getRoundedCorner(RoundedCorner.POSITION_TOP_RIGHT);
+ radius = corner != null ? Math.max(radius, corner.getRadius()) : radius;
+ corner = display.getRoundedCorner(RoundedCorner.POSITION_BOTTOM_RIGHT);
+ radius = corner != null ? Math.max(radius, corner.getRadius()) : radius;
+ corner = display.getRoundedCorner(RoundedCorner.POSITION_BOTTOM_LEFT);
+ radius = corner != null ? Math.max(radius, corner.getRadius()) : radius;
+
+ return Math.max(dividerInset, radius);
+ }
+
/** Gets bounds of the primary split. */
public Rect getBounds1() {
return new Rect(mBounds1);
@@ -247,7 +266,7 @@
}
DockedDividerUtils.sanitizeStackBounds(mBounds1, true /** topLeft */);
DockedDividerUtils.sanitizeStackBounds(mBounds2, false /** topLeft */);
- mDismissingParallaxPolicy.applyDividerPosition(position, isLandscape);
+ mDismissingEffectPolicy.applyDividerPosition(position, isLandscape);
}
/** Inflates {@link DividerView} on the root surface. */
@@ -290,7 +309,6 @@
*/
void updateDivideBounds(int position) {
updateBounds(position);
- mSplitWindowManager.setResizingSplits(true);
mSplitLayoutHandler.onLayoutSizeChanging(this);
}
@@ -298,13 +316,11 @@
mDividePosition = position;
updateBounds(mDividePosition);
mSplitLayoutHandler.onLayoutSizeChanged(this);
- mSplitWindowManager.setResizingSplits(false);
}
/** Resets divider position. */
public void resetDividerPosition() {
mDividePosition = mDividerSnapAlgorithm.getMiddleTarget().position;
- mSplitWindowManager.setResizingSplits(false);
updateBounds(mDividePosition);
mWinToken1 = null;
mWinToken2 = null;
@@ -360,8 +376,8 @@
@VisibleForTesting
void flingDividePosition(int from, int to, @Nullable Runnable flingFinishedCallback) {
if (from == to) {
- // No animation run, it should stop resizing here.
- mSplitWindowManager.setResizingSplits(false);
+ // No animation run, still callback to stop resizing.
+ mSplitLayoutHandler.onLayoutSizeChanged(this);
return;
}
ValueAnimator animator = ValueAnimator
@@ -425,7 +441,7 @@
return;
}
- mDismissingParallaxPolicy.adjustDismissingSurface(t, leash1, leash2, dimLayer1, dimLayer2);
+ mDismissingEffectPolicy.adjustDismissingSurface(t, leash1, leash2, dimLayer1, dimLayer2);
}
/** Apply recorded task layout to the {@link WindowContainerTransaction}. */
@@ -543,7 +559,10 @@
* Calculates and applies proper dismissing parallax offset and dimming value to hint users
* dismissing gesture.
*/
- private class DismissingParallaxPolicy {
+ private class DismissingEffectPolicy {
+ /** Indicates whether to offset splitting bounds to hint dismissing progress or not. */
+ private final boolean mApplyParallax;
+
// The current dismissing side.
int mDismissingSide = DOCKED_INVALID;
@@ -553,6 +572,10 @@
// The dimming value to hint the dismissing side and progress.
float mDismissingDimValue = 0.0f;
+ DismissingEffectPolicy(boolean applyDismissingParallax) {
+ mApplyParallax = applyDismissingParallax;
+ }
+
/**
* Applies a parallax to the task to hint dismissing progress.
*
@@ -565,11 +588,11 @@
mDismissingDimValue = 0;
int totalDismissingDistance = 0;
- if (position <= mDividerSnapAlgorithm.getFirstSplitTarget().position) {
+ if (position < mDividerSnapAlgorithm.getFirstSplitTarget().position) {
mDismissingSide = isLandscape ? DOCKED_LEFT : DOCKED_TOP;
totalDismissingDistance = mDividerSnapAlgorithm.getDismissStartTarget().position
- mDividerSnapAlgorithm.getFirstSplitTarget().position;
- } else if (position >= mDividerSnapAlgorithm.getLastSplitTarget().position) {
+ } else if (position > mDividerSnapAlgorithm.getLastSplitTarget().position) {
mDismissingSide = isLandscape ? DOCKED_RIGHT : DOCKED_BOTTOM;
totalDismissingDistance = mDividerSnapAlgorithm.getLastSplitTarget().position
- mDividerSnapAlgorithm.getDismissEndTarget().position;
@@ -627,12 +650,14 @@
return false;
}
- t.setPosition(targetLeash,
- mTempRect.left + mDismissingParallaxOffset.x,
- mTempRect.top + mDismissingParallaxOffset.y);
- // Transform the screen-based split bounds to surface-based crop bounds.
- mTempRect.offsetTo(-mDismissingParallaxOffset.x, -mDismissingParallaxOffset.y);
- t.setWindowCrop(targetLeash, mTempRect);
+ if (mApplyParallax) {
+ t.setPosition(targetLeash,
+ mTempRect.left + mDismissingParallaxOffset.x,
+ mTempRect.top + mDismissingParallaxOffset.y);
+ // Transform the screen-based split bounds to surface-based crop bounds.
+ mTempRect.offsetTo(-mDismissingParallaxOffset.x, -mDismissingParallaxOffset.y);
+ t.setWindowCrop(targetLeash, mTempRect);
+ }
t.setAlpha(targetDimLayer, mDismissingDimValue)
.setVisibility(targetDimLayer, mDismissingDimValue > 0.001f);
return true;
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/common/split/SplitWindowManager.java b/libs/WindowManager/Shell/src/com/android/wm/shell/common/split/SplitWindowManager.java
index 47dceb3..4903f9d 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/common/split/SplitWindowManager.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/common/split/SplitWindowManager.java
@@ -25,16 +25,12 @@
import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_TRUSTED_OVERLAY;
import static android.view.WindowManager.LayoutParams.TYPE_DOCK_DIVIDER;
-import android.app.ActivityTaskManager;
import android.content.Context;
import android.content.res.Configuration;
import android.graphics.PixelFormat;
import android.graphics.Rect;
import android.graphics.Region;
import android.os.Binder;
-import android.os.IBinder;
-import android.os.RemoteException;
-import android.util.Slog;
import android.view.IWindow;
import android.view.InsetsState;
import android.view.LayoutInflater;
@@ -44,6 +40,7 @@
import android.view.WindowManager;
import android.view.WindowlessWindowManager;
+import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import com.android.wm.shell.R;
@@ -59,7 +56,6 @@
private Context mContext;
private SurfaceControlViewHost mViewHost;
private SurfaceControl mLeash;
- private boolean mResizingSplits;
private DividerView mDividerView;
public interface ParentContainerCallbacks {
@@ -75,9 +71,10 @@
mWindowName = windowName;
}
- @Override
- public void setTouchRegion(IBinder window, Region region) {
- super.setTouchRegion(window, region);
+ void setTouchRegion(@NonNull Rect region) {
+ if (mViewHost != null) {
+ setTouchRegion(mViewHost.getWindowToken().asBinder(), new Region(region));
+ }
}
@Override
@@ -126,7 +123,7 @@
lp.setTitle(mWindowName);
lp.privateFlags |= PRIVATE_FLAG_NO_MOVE_ANIMATION | PRIVATE_FLAG_TRUSTED_OVERLAY;
mViewHost.setView(mDividerView, lp);
- mDividerView.setup(splitLayout, mViewHost, insetsState);
+ mDividerView.setup(splitLayout, this, mViewHost, insetsState);
}
/**
@@ -154,16 +151,6 @@
mDividerView.setInteractive(interactive);
}
- void setResizingSplits(boolean resizing) {
- if (resizing == mResizingSplits) return;
- try {
- ActivityTaskManager.getService().setSplitScreenResizing(resizing);
- mResizingSplits = resizing;
- } catch (RemoteException e) {
- Slog.w(TAG, "Error calling setSplitScreenResizing", e);
- }
- }
-
/**
* Gets {@link SurfaceControl} of the surface holding divider view. @return {@code null} if not
* feasible.
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/hidedisplaycutout/HideDisplayCutoutOrganizer.java b/libs/WindowManager/Shell/src/com/android/wm/shell/hidedisplaycutout/HideDisplayCutoutOrganizer.java
index 75a1dde..3f7d78d 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/hidedisplaycutout/HideDisplayCutoutOrganizer.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/hidedisplaycutout/HideDisplayCutoutOrganizer.java
@@ -39,7 +39,7 @@
import androidx.annotation.NonNull;
import androidx.annotation.VisibleForTesting;
-import com.android.internal.R;
+import com.android.internal.policy.SystemBarUtils;
import com.android.wm.shell.common.DisplayController;
import com.android.wm.shell.common.DisplayLayout;
import com.android.wm.shell.common.ShellExecutor;
@@ -307,12 +307,9 @@
t.apply();
}
- private int getStatusBarHeight() {
- final boolean isLandscape =
- mIsDefaultPortrait ? isDisplaySizeFlipped() : !isDisplaySizeFlipped();
- return mContext.getResources().getDimensionPixelSize(
- isLandscape ? R.dimen.status_bar_height_landscape
- : R.dimen.status_bar_height_portrait);
+ @VisibleForTesting
+ int getStatusBarHeight() {
+ return SystemBarUtils.getStatusBarHeight(mContext);
}
void dump(@NonNull PrintWriter pw) {
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/onehanded/OneHandedController.java b/libs/WindowManager/Shell/src/com/android/wm/shell/onehanded/OneHandedController.java
index 38079af..90074371 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/onehanded/OneHandedController.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/onehanded/OneHandedController.java
@@ -689,6 +689,8 @@
pw.println(mUserId);
pw.print(innerPrefix + "isShortcutEnabled=");
pw.println(isShortcutEnabled());
+ pw.print(innerPrefix + "mIsSwipeToNotificationEnabled=");
+ pw.println(mIsSwipeToNotificationEnabled);
if (mBackgroundPanelOrganizer != null) {
mBackgroundPanelOrganizer.dump(pw);
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/onehanded/OneHandedSettingsUtil.java b/libs/WindowManager/Shell/src/com/android/wm/shell/onehanded/OneHandedSettingsUtil.java
index ff333c8c..2cb7d1b 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/onehanded/OneHandedSettingsUtil.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/onehanded/OneHandedSettingsUtil.java
@@ -244,6 +244,8 @@
pw.println(TAG);
pw.print(innerPrefix + "isOneHandedModeEnable=");
pw.println(getSettingsOneHandedModeEnabled(resolver, userId));
+ pw.print(innerPrefix + "isSwipeToNotificationEnabled=");
+ pw.println(getSettingsSwipeToNotificationEnabled(resolver, userId));
pw.print(innerPrefix + "oneHandedTimeOut=");
pw.println(getSettingsOneHandedModeTimeout(resolver, userId));
pw.print(innerPrefix + "tapsAppToExit=");
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/pip/PipTaskOrganizer.java b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/PipTaskOrganizer.java
index 291cbb3..b6e5804 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/pip/PipTaskOrganizer.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/PipTaskOrganizer.java
@@ -1292,13 +1292,17 @@
}
Rect baseBounds = direction == TRANSITION_DIRECTION_SNAP_AFTER_RESIZE
? mPipBoundsState.getBounds() : currentBounds;
+ final boolean existingAnimatorRunning = mPipAnimationController.getCurrentAnimator() != null
+ && mPipAnimationController.getCurrentAnimator().isRunning();
final PipAnimationController.PipTransitionAnimator<?> animator = mPipAnimationController
.getAnimator(mTaskInfo, mLeash, baseBounds, currentBounds, destinationBounds,
sourceHintRect, direction, startingAngle, rotationDelta);
animator.setTransitionDirection(direction)
- .setPipAnimationCallback(mPipAnimationCallback)
.setPipTransactionHandler(mPipTransactionHandler)
.setDuration(durationMs);
+ if (!existingAnimatorRunning) {
+ animator.setPipAnimationCallback(mPipAnimationCallback);
+ }
if (isInPipDirection(direction)) {
// Similar to auto-enter-pip transition, we use content overlay when there is no
// source rect hint to enter PiP use bounds animation.
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/pip/PipTransition.java b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/PipTransition.java
index 328f3ed..b31e6e0 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/pip/PipTransition.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/PipTransition.java
@@ -116,6 +116,12 @@
if (mExitTransition == transition || info.getType() == TRANSIT_EXIT_PIP) {
mExitTransition = null;
if (info.getChanges().size() == 1) {
+ if (mFinishCallback != null) {
+ mFinishCallback.onTransitionFinished(null, null);
+ mFinishCallback = null;
+ throw new RuntimeException("Previous callback not called, aborting exit PIP.");
+ }
+
final TransitionInfo.Change change = info.getChanges().get(0);
mFinishCallback = finishCallback;
startTransaction.apply();
@@ -129,6 +135,12 @@
}
if (info.getType() == TRANSIT_REMOVE_PIP) {
+ if (mFinishCallback != null) {
+ mFinishCallback.onTransitionFinished(null /* wct */, null /* callback */);
+ mFinishCallback = null;
+ throw new RuntimeException("Previous callback not called, aborting remove PIP.");
+ }
+
startTransaction.apply();
finishTransaction.setWindowCrop(info.getChanges().get(0).getLeash(),
mPipBoundsState.getDisplayBounds());
@@ -159,6 +171,12 @@
return false;
}
+ if (mFinishCallback != null) {
+ mFinishCallback.onTransitionFinished(null /* wct */, null /* callback */);
+ mFinishCallback = null;
+ throw new RuntimeException("Previous callback not called, aborting entering PIP.");
+ }
+
// Show the wallpaper if there is a wallpaper change.
if (wallpaper != null) {
startTransaction.show(wallpaper.getLeash());
@@ -231,7 +249,7 @@
if (tx != null) {
wct.setBoundsChangeTransaction(taskInfo.token, tx);
}
- mFinishCallback.onTransitionFinished(wct, null /* wctCallback */);
+ mFinishCallback.onTransitionFinished(wct, null /* callback */);
mFinishCallback = null;
}
finishResizeForMenu(destinationBounds);
@@ -240,7 +258,7 @@
@Override
public void forceFinishTransition() {
if (mFinishCallback == null) return;
- mFinishCallback.onTransitionFinished(null /* wct */, null /* wctCallback */);
+ mFinishCallback.onTransitionFinished(null /* wct */, null /* callback */);
mFinishCallback = null;
}
@@ -286,7 +304,6 @@
mPipBoundsState.setBounds(destinationBounds);
onFinishResize(taskInfo, destinationBounds, TRANSITION_DIRECTION_TO_PIP, null /* tx */);
sendOnPipTransitionFinished(TRANSITION_DIRECTION_TO_PIP);
- mFinishCallback = null;
mPipTransitionState.setInSwipePipToHomeTransition(false);
return true;
}
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/MainStage.java b/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/MainStage.java
index a47a152..082fe92 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/MainStage.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/MainStage.java
@@ -16,14 +16,14 @@
package com.android.wm.shell.splitscreen;
-import static android.app.WindowConfiguration.WINDOWING_MODE_MULTI_WINDOW;
-
import android.annotation.Nullable;
+import android.content.Context;
import android.graphics.Rect;
import android.view.SurfaceSession;
import android.window.WindowContainerToken;
import android.window.WindowContainerTransaction;
+import com.android.launcher3.icons.IconProvider;
import com.android.wm.shell.ShellTaskOrganizer;
import com.android.wm.shell.common.SyncTransactionQueue;
@@ -37,11 +37,11 @@
private boolean mIsActive = false;
- MainStage(ShellTaskOrganizer taskOrganizer, int displayId,
+ MainStage(Context context, ShellTaskOrganizer taskOrganizer, int displayId,
StageListenerCallbacks callbacks, SyncTransactionQueue syncQueue,
- SurfaceSession surfaceSession,
+ SurfaceSession surfaceSession, IconProvider iconProvider,
@Nullable StageTaskUnfoldController stageTaskUnfoldController) {
- super(taskOrganizer, displayId, callbacks, syncQueue, surfaceSession,
+ super(context, taskOrganizer, displayId, callbacks, syncQueue, surfaceSession, iconProvider,
stageTaskUnfoldController);
}
@@ -54,7 +54,6 @@
final WindowContainerToken rootToken = mRootTaskInfo.token;
wct.setBounds(rootToken, rootBounds)
- .setWindowingMode(rootToken, WINDOWING_MODE_MULTI_WINDOW)
// Moving the root task to top after the child tasks were re-parented , or the root
// task cannot be visible and focused.
.reorder(rootToken, true /* onTop */);
@@ -81,11 +80,7 @@
if (mRootTaskInfo == null) return;
final WindowContainerToken rootToken = mRootTaskInfo.token;
- wct.setLaunchRoot(
- rootToken,
- null,
- null)
- .reparentTasks(
+ wct.reparentTasks(
rootToken,
null /* newParent */,
CONTROLLED_WINDOWING_MODES_WHEN_ACTIVE,
@@ -95,9 +90,4 @@
// all its tasks.
.reorder(rootToken, false /* onTop */);
}
-
- void updateConfiguration(int windowingMode, Rect bounds, WindowContainerTransaction wct) {
- wct.setBounds(mRootTaskInfo.token, bounds)
- .setWindowingMode(mRootTaskInfo.token, windowingMode);
- }
}
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/OutlineManager.java b/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/OutlineManager.java
deleted file mode 100644
index a459c8d..0000000
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/OutlineManager.java
+++ /dev/null
@@ -1,181 +0,0 @@
-/*
- * Copyright (C) 2021 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.splitscreen;
-
-import static android.view.WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE;
-import static android.view.WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE;
-import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_NO_MOVE_ANIMATION;
-import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_TRUSTED_OVERLAY;
-import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION_OVERLAY;
-
-import android.annotation.Nullable;
-import android.content.Context;
-import android.content.res.Configuration;
-import android.graphics.PixelFormat;
-import android.graphics.Rect;
-import android.os.Binder;
-import android.view.IWindow;
-import android.view.InsetsSource;
-import android.view.InsetsState;
-import android.view.LayoutInflater;
-import android.view.SurfaceControl;
-import android.view.SurfaceControlViewHost;
-import android.view.View;
-import android.view.ViewGroup;
-import android.view.WindowManager;
-import android.view.WindowlessWindowManager;
-import android.widget.FrameLayout;
-
-import com.android.wm.shell.R;
-
-/**
- * Handles drawing outline of the bounds of provided root surface. The outline will be drown with
- * the consideration of display insets like status bar, navigation bar and display cutout.
- */
-class OutlineManager extends WindowlessWindowManager {
- private static final String WINDOW_NAME = "SplitOutlineLayer";
- private final Context mContext;
- private final Rect mRootBounds = new Rect();
- private final Rect mTempRect = new Rect();
- private final Rect mLastOutlineBounds = new Rect();
- private final InsetsState mInsetsState = new InsetsState();
- private final int mExpandedTaskBarHeight;
- private OutlineView mOutlineView;
- private SurfaceControlViewHost mViewHost;
- private SurfaceControl mHostLeash;
- private SurfaceControl mLeash;
-
- OutlineManager(Context context, Configuration configuration) {
- super(configuration, null /* rootSurface */, null /* hostInputToken */);
- mContext = context.createWindowContext(context.getDisplay(), TYPE_APPLICATION_OVERLAY,
- null /* options */);
- mExpandedTaskBarHeight = mContext.getResources().getDimensionPixelSize(
- com.android.internal.R.dimen.taskbar_frame_height);
- }
-
- @Override
- protected void attachToParentSurface(IWindow window, SurfaceControl.Builder b) {
- b.setParent(mHostLeash);
- }
-
- void inflate(SurfaceControl rootLeash, Rect rootBounds) {
- if (mLeash != null || mViewHost != null) return;
-
- mHostLeash = rootLeash;
- mRootBounds.set(rootBounds);
- mViewHost = new SurfaceControlViewHost(mContext, mContext.getDisplay(), this);
-
- final FrameLayout rootLayout = (FrameLayout) LayoutInflater.from(mContext)
- .inflate(R.layout.split_outline, null);
- mOutlineView = rootLayout.findViewById(R.id.split_outline);
-
- final WindowManager.LayoutParams lp = new WindowManager.LayoutParams(
- 0 /* width */, 0 /* height */, TYPE_APPLICATION_OVERLAY,
- FLAG_NOT_FOCUSABLE | FLAG_NOT_TOUCHABLE, PixelFormat.TRANSLUCENT);
- lp.width = mRootBounds.width();
- lp.height = mRootBounds.height();
- lp.token = new Binder();
- lp.setTitle(WINDOW_NAME);
- lp.privateFlags |= PRIVATE_FLAG_NO_MOVE_ANIMATION | PRIVATE_FLAG_TRUSTED_OVERLAY;
- // TODO(b/189839391): Set INPUT_FEATURE_NO_INPUT_CHANNEL after WM supports
- // TRUSTED_OVERLAY for windowless window without input channel.
- mViewHost.setView(rootLayout, lp);
- mLeash = getSurfaceControl(mViewHost.getWindowToken());
-
- drawOutline();
- }
-
- void release() {
- if (mViewHost != null) {
- mViewHost.release();
- mViewHost = null;
- }
- mRootBounds.setEmpty();
- mLastOutlineBounds.setEmpty();
- mOutlineView = null;
- mHostLeash = null;
- mLeash = null;
- }
-
- @Nullable
- SurfaceControl getOutlineLeash() {
- return mLeash;
- }
-
- void setVisibility(boolean visible) {
- if (mOutlineView != null) {
- mOutlineView.setVisibility(visible ? View.VISIBLE : View.INVISIBLE);
- }
- }
-
- void setRootBounds(Rect rootBounds) {
- if (mViewHost == null || mViewHost.getView() == null) {
- return;
- }
-
- if (!mRootBounds.equals(rootBounds)) {
- WindowManager.LayoutParams lp =
- (WindowManager.LayoutParams) mViewHost.getView().getLayoutParams();
- lp.width = rootBounds.width();
- lp.height = rootBounds.height();
- mViewHost.relayout(lp);
- mRootBounds.set(rootBounds);
- drawOutline();
- }
- }
-
- void onInsetsChanged(InsetsState insetsState) {
- if (!mInsetsState.equals(insetsState)) {
- mInsetsState.set(insetsState);
- drawOutline();
- }
- }
-
- private void computeOutlineBounds(Rect rootBounds, InsetsState insetsState, Rect outBounds) {
- outBounds.set(rootBounds);
- final InsetsSource taskBarInsetsSource =
- insetsState.getSource(InsetsState.ITYPE_EXTRA_NAVIGATION_BAR);
- // Only insets the divider bar with task bar when it's expanded so that the rounded corners
- // will be drawn against task bar.
- if (taskBarInsetsSource.getFrame().height() >= mExpandedTaskBarHeight) {
- outBounds.inset(taskBarInsetsSource.calculateVisibleInsets(outBounds));
- }
-
- // Offset the coordinate from screen based to surface based.
- outBounds.offset(-rootBounds.left, -rootBounds.top);
- }
-
- void drawOutline() {
- if (mOutlineView == null) {
- return;
- }
-
- computeOutlineBounds(mRootBounds, mInsetsState, mTempRect);
- if (mTempRect.equals(mLastOutlineBounds)) {
- return;
- }
-
- ViewGroup.MarginLayoutParams lp =
- (ViewGroup.MarginLayoutParams) mOutlineView.getLayoutParams();
- lp.leftMargin = mTempRect.left;
- lp.topMargin = mTempRect.top;
- lp.width = mTempRect.width();
- lp.height = mTempRect.height();
- mOutlineView.setLayoutParams(lp);
- mLastOutlineBounds.set(mTempRect);
- }
-}
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/OutlineView.java b/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/OutlineView.java
deleted file mode 100644
index 94dd9b2..0000000
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/OutlineView.java
+++ /dev/null
@@ -1,82 +0,0 @@
-/*
- * Copyright (C) 2021 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.splitscreen;
-
-import static android.view.RoundedCorner.POSITION_BOTTOM_LEFT;
-import static android.view.RoundedCorner.POSITION_BOTTOM_RIGHT;
-import static android.view.RoundedCorner.POSITION_TOP_LEFT;
-import static android.view.RoundedCorner.POSITION_TOP_RIGHT;
-
-import android.content.Context;
-import android.graphics.Canvas;
-import android.graphics.Paint;
-import android.graphics.Path;
-import android.util.AttributeSet;
-import android.view.RoundedCorner;
-import android.view.View;
-
-import androidx.annotation.NonNull;
-import androidx.annotation.Nullable;
-
-import com.android.internal.R;
-
-/** View for drawing split outline. */
-public class OutlineView extends View {
- private final Paint mPaint = new Paint();
- private final Path mPath = new Path();
- private final float[] mRadii = new float[8];
-
- public OutlineView(@NonNull Context context, @Nullable AttributeSet attrs) {
- super(context, attrs);
- mPaint.setStyle(Paint.Style.STROKE);
- mPaint.setStrokeWidth(
- getResources().getDimension(R.dimen.accessibility_focus_highlight_stroke_width));
- mPaint.setColor(getResources().getColor(R.color.system_accent1_100, null));
- }
-
- @Override
- protected void onAttachedToWindow() {
- // TODO(b/200850654): match the screen corners with the actual display decor.
- mRadii[0] = mRadii[1] = getCornerRadius(POSITION_TOP_LEFT);
- mRadii[2] = mRadii[3] = getCornerRadius(POSITION_TOP_RIGHT);
- mRadii[4] = mRadii[5] = getCornerRadius(POSITION_BOTTOM_RIGHT);
- mRadii[6] = mRadii[7] = getCornerRadius(POSITION_BOTTOM_LEFT);
- }
-
- private int getCornerRadius(@RoundedCorner.Position int position) {
- final RoundedCorner roundedCorner = getDisplay().getRoundedCorner(position);
- return roundedCorner == null ? 0 : roundedCorner.getRadius();
- }
-
- @Override
- protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
- if (changed) {
- mPath.reset();
- mPath.addRoundRect(0, 0, getWidth(), getHeight(), mRadii, Path.Direction.CW);
- }
- }
-
- @Override
- protected void onDraw(Canvas canvas) {
- canvas.drawPath(mPath, mPaint);
- }
-
- @Override
- public boolean hasOverlappingRendering() {
- return false;
- }
-}
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/SideStage.java b/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/SideStage.java
index dc8fb9f..f8c0304 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/SideStage.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/SideStage.java
@@ -16,20 +16,16 @@
package com.android.wm.shell.splitscreen;
-import android.annotation.CallSuper;
import android.annotation.Nullable;
import android.app.ActivityManager;
import android.content.Context;
import android.graphics.Rect;
-import android.view.InsetsSourceControl;
-import android.view.InsetsState;
-import android.view.SurfaceControl;
import android.view.SurfaceSession;
import android.window.WindowContainerToken;
import android.window.WindowContainerTransaction;
+import com.android.launcher3.icons.IconProvider;
import com.android.wm.shell.ShellTaskOrganizer;
-import com.android.wm.shell.common.DisplayInsetsController;
import com.android.wm.shell.common.SyncTransactionQueue;
/**
@@ -38,29 +34,24 @@
*
* @see StageCoordinator
*/
-class SideStage extends StageTaskListener implements
- DisplayInsetsController.OnInsetsChangedListener {
+class SideStage extends StageTaskListener {
private static final String TAG = SideStage.class.getSimpleName();
- private final Context mContext;
- private OutlineManager mOutlineManager;
SideStage(Context context, ShellTaskOrganizer taskOrganizer, int displayId,
StageListenerCallbacks callbacks, SyncTransactionQueue syncQueue,
- SurfaceSession surfaceSession,
+ SurfaceSession surfaceSession, IconProvider iconProvider,
@Nullable StageTaskUnfoldController stageTaskUnfoldController) {
- super(taskOrganizer, displayId, callbacks, syncQueue, surfaceSession,
+ super(context, taskOrganizer, displayId, callbacks, syncQueue, surfaceSession, iconProvider,
stageTaskUnfoldController);
- mContext = context;
}
- void addTask(ActivityManager.RunningTaskInfo task, Rect rootBounds,
- WindowContainerTransaction wct) {
+ void moveToTop(Rect rootBounds, WindowContainerTransaction wct) {
final WindowContainerToken rootToken = mRootTaskInfo.token;
- wct.setBounds(rootToken, rootBounds)
- .reparent(task.token, rootToken, true /* onTop*/)
- // Moving the root task to top after the child tasks were reparented , or the root
- // task cannot be visible and focused.
- .reorder(rootToken, true /* onTop */);
+ wct.setBounds(rootToken, rootBounds).reorder(rootToken, true /* onTop */);
+ }
+
+ void addTask(ActivityManager.RunningTaskInfo task, WindowContainerTransaction wct) {
+ wct.reparent(task.token, mRootTaskInfo.token, true /* onTop*/);
}
boolean removeAllTasks(WindowContainerTransaction wct, boolean toTop) {
@@ -83,62 +74,4 @@
wct.reparent(task.token, newParent, false /* onTop */);
return true;
}
-
- @Nullable
- public SurfaceControl getOutlineLeash() {
- return mOutlineManager.getOutlineLeash();
- }
-
- @Override
- @CallSuper
- public void onTaskAppeared(ActivityManager.RunningTaskInfo taskInfo, SurfaceControl leash) {
- super.onTaskAppeared(taskInfo, leash);
- if (isRootTask(taskInfo)) {
- mOutlineManager = new OutlineManager(mContext, taskInfo.configuration);
- enableOutline(true);
- }
- }
-
- @Override
- @CallSuper
- public void onTaskInfoChanged(ActivityManager.RunningTaskInfo taskInfo) {
- super.onTaskInfoChanged(taskInfo);
- if (isRootTask(taskInfo)) {
- mOutlineManager.setRootBounds(taskInfo.configuration.windowConfiguration.getBounds());
- }
- }
-
- private boolean isRootTask(ActivityManager.RunningTaskInfo taskInfo) {
- return mRootTaskInfo != null && mRootTaskInfo.taskId == taskInfo.taskId;
- }
-
- void enableOutline(boolean enable) {
- if (mOutlineManager == null) {
- return;
- }
-
- if (enable) {
- if (mRootTaskInfo != null) {
- mOutlineManager.inflate(mRootLeash,
- mRootTaskInfo.configuration.windowConfiguration.getBounds());
- }
- } else {
- mOutlineManager.release();
- }
- }
-
- void setOutlineVisibility(boolean visible) {
- mOutlineManager.setVisibility(visible);
- }
-
- @Override
- public void insetsChanged(InsetsState insetsState) {
- mOutlineManager.onInsetsChanged(insetsState);
- }
-
- @Override
- public void insetsControlChanged(InsetsState insetsState,
- InsetsSourceControl[] activeControls) {
- insetsChanged(insetsState);
- }
}
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/SplitDecorManager.java b/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/SplitDecorManager.java
new file mode 100644
index 0000000..8e5cc6d
--- /dev/null
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/SplitDecorManager.java
@@ -0,0 +1,182 @@
+/*
+ * Copyright (C) 2021 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.splitscreen;
+
+import static android.view.WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE;
+import static android.view.WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE;
+import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_NO_MOVE_ANIMATION;
+import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_TRUSTED_OVERLAY;
+import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION_OVERLAY;
+import static android.view.WindowManagerPolicyConstants.SPLIT_DIVIDER_LAYER;
+
+import android.app.ActivityManager;
+import android.content.Context;
+import android.content.res.Configuration;
+import android.graphics.Color;
+import android.graphics.PixelFormat;
+import android.graphics.Rect;
+import android.graphics.drawable.Drawable;
+import android.os.Binder;
+import android.view.IWindow;
+import android.view.LayoutInflater;
+import android.view.SurfaceControl;
+import android.view.SurfaceControlViewHost;
+import android.view.SurfaceSession;
+import android.view.View;
+import android.view.WindowManager;
+import android.view.WindowlessWindowManager;
+import android.widget.FrameLayout;
+import android.widget.ImageView;
+
+import com.android.launcher3.icons.IconProvider;
+import com.android.wm.shell.R;
+import com.android.wm.shell.common.SurfaceUtils;
+
+/**
+ * Handles split decor like showing resizing hint for a specific split.
+ */
+class SplitDecorManager extends WindowlessWindowManager {
+ private static final String TAG = SplitDecorManager.class.getSimpleName();
+ private static final String RESIZING_BACKGROUND_SURFACE_NAME = "ResizingBackground";
+
+ private final IconProvider mIconProvider;
+ private final SurfaceSession mSurfaceSession;
+
+ private Drawable mIcon;
+ private ImageView mResizingIconView;
+ private SurfaceControlViewHost mViewHost;
+ private SurfaceControl mHostLeash;
+ private SurfaceControl mIconLeash;
+ private SurfaceControl mBackgroundLeash;
+
+ SplitDecorManager(Configuration configuration, IconProvider iconProvider,
+ SurfaceSession surfaceSession) {
+ super(configuration, null /* rootSurface */, null /* hostInputToken */);
+ mIconProvider = iconProvider;
+ mSurfaceSession = surfaceSession;
+ }
+
+ @Override
+ protected void attachToParentSurface(IWindow window, SurfaceControl.Builder b) {
+ // Can't set position for the ViewRootImpl SC directly. Create a leash to manipulate later.
+ final SurfaceControl.Builder builder = new SurfaceControl.Builder(new SurfaceSession())
+ .setContainerLayer()
+ .setName(TAG)
+ .setHidden(true)
+ .setParent(mHostLeash)
+ .setCallsite("SplitDecorManager#attachToParentSurface");
+ mIconLeash = builder.build();
+ b.setParent(mIconLeash);
+ }
+
+ void inflate(Context context, SurfaceControl rootLeash, Rect rootBounds) {
+ if (mIconLeash != null && mViewHost != null) {
+ return;
+ }
+
+ context = context.createWindowContext(context.getDisplay(), TYPE_APPLICATION_OVERLAY,
+ null /* options */);
+ mHostLeash = rootLeash;
+ mViewHost = new SurfaceControlViewHost(context, context.getDisplay(), this);
+
+ final FrameLayout rootLayout = (FrameLayout) LayoutInflater.from(context)
+ .inflate(R.layout.split_decor, null);
+ mResizingIconView = rootLayout.findViewById(R.id.split_resizing_icon);
+
+ final WindowManager.LayoutParams lp = new WindowManager.LayoutParams(
+ 0 /* width */, 0 /* height */, TYPE_APPLICATION_OVERLAY,
+ FLAG_NOT_FOCUSABLE | FLAG_NOT_TOUCHABLE, PixelFormat.TRANSLUCENT);
+ lp.width = rootBounds.width();
+ lp.height = rootBounds.height();
+ lp.token = new Binder();
+ lp.setTitle(TAG);
+ lp.privateFlags |= PRIVATE_FLAG_NO_MOVE_ANIMATION | PRIVATE_FLAG_TRUSTED_OVERLAY;
+ // TODO(b/189839391): Set INPUT_FEATURE_NO_INPUT_CHANNEL after WM supports
+ // TRUSTED_OVERLAY for windowless window without input channel.
+ mViewHost.setView(rootLayout, lp);
+ }
+
+ void release(SurfaceControl.Transaction t) {
+ if (mViewHost != null) {
+ mViewHost.release();
+ mViewHost = null;
+ }
+ if (mIconLeash != null) {
+ t.remove(mIconLeash);
+ mIconLeash = null;
+ }
+ if (mBackgroundLeash != null) {
+ t.remove(mBackgroundLeash);
+ mBackgroundLeash = null;
+ }
+ mHostLeash = null;
+ mIcon = null;
+ mResizingIconView = null;
+ }
+
+ /** Showing resizing hint. */
+ void onResizing(ActivityManager.RunningTaskInfo resizingTask, Rect newBounds,
+ SurfaceControl.Transaction t) {
+ if (mResizingIconView == null) {
+ return;
+ }
+
+ if (mIcon == null) {
+ // TODO: add fade-in animation.
+ mBackgroundLeash = SurfaceUtils.makeColorLayer(mHostLeash,
+ RESIZING_BACKGROUND_SURFACE_NAME, mSurfaceSession);
+ t.setColor(mBackgroundLeash, getResizingBackgroundColor(resizingTask))
+ .setLayer(mBackgroundLeash, SPLIT_DIVIDER_LAYER - 1)
+ .show(mBackgroundLeash);
+
+ mIcon = mIconProvider.getIcon(resizingTask.topActivityInfo);
+ mResizingIconView.setImageDrawable(mIcon);
+ mResizingIconView.setVisibility(View.VISIBLE);
+
+ WindowManager.LayoutParams lp =
+ (WindowManager.LayoutParams) mViewHost.getView().getLayoutParams();
+ lp.width = mIcon.getIntrinsicWidth();
+ lp.height = mIcon.getIntrinsicHeight();
+ mViewHost.relayout(lp);
+ t.show(mIconLeash).setLayer(mIconLeash, SPLIT_DIVIDER_LAYER);
+ }
+
+ t.setPosition(mIconLeash,
+ newBounds.width() / 2 - mIcon.getIntrinsicWidth() / 2,
+ newBounds.height() / 2 - mIcon.getIntrinsicWidth() / 2);
+ }
+
+ /** Stops showing resizing hint. */
+ void onResized(Rect newBounds, SurfaceControl.Transaction t) {
+ if (mResizingIconView == null) {
+ return;
+ }
+
+ if (mIcon != null) {
+ mResizingIconView.setVisibility(View.GONE);
+ mResizingIconView.setImageDrawable(null);
+ t.remove(mBackgroundLeash).hide(mIconLeash);
+ mIcon = null;
+ mBackgroundLeash = null;
+ }
+ }
+
+ private static float[] getResizingBackgroundColor(ActivityManager.RunningTaskInfo taskInfo) {
+ final int taskBgColor = taskInfo.taskDescription.getBackgroundColor();
+ return Color.valueOf(taskBgColor == -1 ? Color.WHITE : taskBgColor).getComponents();
+ }
+}
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/SplitScreenController.java b/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/SplitScreenController.java
index 3b75bfb..36f1406 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/SplitScreenController.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/SplitScreenController.java
@@ -54,6 +54,7 @@
import com.android.internal.logging.InstanceId;
import com.android.internal.util.FrameworkStatsLog;
+import com.android.launcher3.icons.IconProvider;
import com.android.wm.shell.RootTaskDisplayAreaOrganizer;
import com.android.wm.shell.ShellTaskOrganizer;
import com.android.wm.shell.common.DisplayImeController;
@@ -78,6 +79,7 @@
/**
* Class manages split-screen multitasking mode and implements the main interface
* {@link SplitScreen}.
+ *
* @see StageCoordinator
*/
// TODO(b/198577848): Implement split screen flicker test to consolidate CUJ of split screen.
@@ -96,6 +98,7 @@
private final Transitions mTransitions;
private final TransactionPool mTransactionPool;
private final SplitscreenEventLogger mLogger;
+ private final IconProvider mIconProvider;
private final Provider<Optional<StageTaskUnfoldController>> mUnfoldControllerProvider;
private StageCoordinator mStageCoordinator;
@@ -105,7 +108,7 @@
RootTaskDisplayAreaOrganizer rootTDAOrganizer,
ShellExecutor mainExecutor, DisplayImeController displayImeController,
DisplayInsetsController displayInsetsController,
- Transitions transitions, TransactionPool transactionPool,
+ Transitions transitions, TransactionPool transactionPool, IconProvider iconProvider,
Provider<Optional<StageTaskUnfoldController>> unfoldControllerProvider) {
mTaskOrganizer = shellTaskOrganizer;
mSyncQueue = syncQueue;
@@ -118,6 +121,7 @@
mTransactionPool = transactionPool;
mUnfoldControllerProvider = unfoldControllerProvider;
mLogger = new SplitscreenEventLogger();
+ mIconProvider = iconProvider;
}
public SplitScreen asSplitScreen() {
@@ -140,7 +144,7 @@
mStageCoordinator = new StageCoordinator(mContext, DEFAULT_DISPLAY, mSyncQueue,
mRootTDAOrganizer, mTaskOrganizer, mDisplayImeController,
mDisplayInsetsController, mTransitions, mTransactionPool, mLogger,
- mUnfoldControllerProvider);
+ mIconProvider, mUnfoldControllerProvider);
}
}
@@ -165,10 +169,6 @@
return mStageCoordinator.removeFromSideStage(taskId);
}
- public void setSideStageOutline(boolean enable) {
- mStageCoordinator.setSideStageOutline(enable);
- }
-
public void setSideStagePosition(@SplitPosition int sideStagePosition) {
mStageCoordinator.setSideStagePosition(sideStagePosition, null /* wct */);
}
@@ -319,9 +319,7 @@
}
transaction.apply();
transaction.close();
- return new RemoteAnimationTarget[]{
- mStageCoordinator.getDividerBarLegacyTarget(),
- mStageCoordinator.getOutlineLegacyTarget()};
+ return new RemoteAnimationTarget[]{mStageCoordinator.getDividerBarLegacyTarget()};
}
/**
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 72d9880..7be199c 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
@@ -80,6 +80,7 @@
import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.logging.InstanceId;
import com.android.internal.protolog.common.ProtoLog;
+import com.android.launcher3.icons.IconProvider;
import com.android.wm.shell.RootTaskDisplayAreaOrganizer;
import com.android.wm.shell.ShellTaskOrganizer;
import com.android.wm.shell.common.DisplayImeController;
@@ -151,10 +152,12 @@
/** Whether the device is supporting legacy split or not. */
private boolean mUseLegacySplit;
- @SplitScreen.StageType private int mDismissTop = NO_DISMISS;
+ @SplitScreen.StageType
+ private int mDismissTop = NO_DISMISS;
/** The target stage to dismiss to when unlock after folded. */
- @SplitScreen.StageType private int mTopStageAfterFoldDismiss = STAGE_TYPE_UNDEFINED;
+ @SplitScreen.StageType
+ private int mTopStageAfterFoldDismiss = STAGE_TYPE_UNDEFINED;
private final Runnable mOnTransitionAnimationComplete = () -> {
// If still playing, let it finish.
@@ -169,22 +172,23 @@
private final SplitWindowManager.ParentContainerCallbacks mParentContainerCallbacks =
new SplitWindowManager.ParentContainerCallbacks() {
- @Override
- public void attachToParentSurface(SurfaceControl.Builder b) {
- mRootTDAOrganizer.attachToDisplayArea(mDisplayId, b);
- }
+ @Override
+ public void attachToParentSurface(SurfaceControl.Builder b) {
+ mRootTDAOrganizer.attachToDisplayArea(mDisplayId, b);
+ }
- @Override
- public void onLeashReady(SurfaceControl leash) {
- mSyncQueue.runInSync(t -> applyDividerVisibility(t));
- }
- };
+ @Override
+ public void onLeashReady(SurfaceControl leash) {
+ mSyncQueue.runInSync(t -> applyDividerVisibility(t));
+ }
+ };
StageCoordinator(Context context, int displayId, SyncTransactionQueue syncQueue,
RootTaskDisplayAreaOrganizer rootTDAOrganizer, ShellTaskOrganizer taskOrganizer,
DisplayImeController displayImeController,
DisplayInsetsController displayInsetsController, Transitions transitions,
TransactionPool transactionPool, SplitscreenEventLogger logger,
+ IconProvider iconProvider,
Provider<Optional<StageTaskUnfoldController>> unfoldControllerProvider) {
mContext = context;
mDisplayId = displayId;
@@ -196,11 +200,13 @@
mSideUnfoldController = unfoldControllerProvider.get().orElse(null);
mMainStage = new MainStage(
+ mContext,
mTaskOrganizer,
mDisplayId,
mMainStageListener,
mSyncQueue,
mSurfaceSession,
+ iconProvider,
mMainUnfoldController);
mSideStage = new SideStage(
mContext,
@@ -209,10 +215,10 @@
mSideStageListener,
mSyncQueue,
mSurfaceSession,
+ iconProvider,
mSideUnfoldController);
mDisplayImeController = displayImeController;
mDisplayInsetsController = displayInsetsController;
- mDisplayInsetsController.addInsetsChangedListener(mDisplayId, mSideStage);
mRootTDAOrganizer.registerListener(displayId, this);
final DeviceStateManager deviceStateManager =
mContext.getSystemService(DeviceStateManager.class);
@@ -262,11 +268,14 @@
boolean moveToSideStage(ActivityManager.RunningTaskInfo task,
@SplitPosition int sideStagePosition) {
final WindowContainerTransaction wct = new WindowContainerTransaction();
+ final WindowContainerTransaction evictWct = new WindowContainerTransaction();
setSideStagePosition(sideStagePosition, wct);
- mMainStage.activate(getMainStageBounds(), wct, true /* reparent */);
- mSideStage.addTask(task, getSideStageBounds(), wct);
- mSyncQueue.queue(wct);
- mSyncQueue.runInSync(t -> updateSurfaceBounds(null /* layout */, t));
+ mSideStage.evictAllChildren(evictWct);
+ mSideStage.addTask(task, wct);
+ if (!evictWct.isEmpty()) {
+ wct.merge(evictWct, true /* transfer */);
+ }
+ mTaskOrganizer.applyTransaction(wct);
return true;
}
@@ -284,10 +293,6 @@
return result;
}
- void setSideStageOutline(boolean enable) {
- mSideStage.enableOutline(enable);
- }
-
/** Starts 2 tasks in one transition. */
void startTasks(int mainTaskId, @Nullable Bundle mainOptions, int sideTaskId,
@Nullable Bundle sideOptions, @SplitPosition int sidePosition,
@@ -697,9 +702,10 @@
if (bothStageInvisible) {
if (mExitSplitScreenOnHide
- // Don't dismiss staged split when both stages are not visible due to sleeping display,
- // like the cases keyguard showing or screen off.
- || (!mMainStage.mRootTaskInfo.isSleeping && !mSideStage.mRootTaskInfo.isSleeping)) {
+ // Don't dismiss staged split when both stages are not visible due to sleeping
+ // display, like the cases keyguard showing or screen off.
+ || (!mMainStage.mRootTaskInfo.isSleeping
+ && !mSideStage.mRootTaskInfo.isSleeping)) {
exitSplitScreen(null /* childrenToTop */,
SPLITSCREEN_UICHANGED__EXIT_REASON__RETURN_HOME);
}
@@ -719,7 +725,6 @@
t.setVisibility(mSideStage.mRootLeash, bothStageVisible)
.setVisibility(mMainStage.mRootLeash, bothStageVisible);
applyDividerVisibility(t);
- applyOutlineVisibility(t);
}
});
}
@@ -741,19 +746,6 @@
}
}
- private void applyOutlineVisibility(SurfaceControl.Transaction t) {
- final SurfaceControl outlineLeash = mSideStage.getOutlineLeash();
- if (outlineLeash == null) {
- return;
- }
-
- if (mDividerVisible) {
- t.show(outlineLeash).setLayer(outlineLeash, SPLIT_DIVIDER_LAYER);
- } else {
- t.hide(outlineLeash);
- }
- }
-
private void onStageHasChildrenChanged(StageListenerImpl stageListener) {
final boolean hasChildren = stageListener.mHasChildren;
final boolean isSideStage = stageListener == mSideStageListener;
@@ -769,8 +761,9 @@
final WindowContainerTransaction wct = new WindowContainerTransaction();
// Make sure the main stage is active.
mMainStage.activate(getMainStageBounds(), wct, true /* reparent */);
- mSideStage.setBounds(getSideStageBounds(), wct);
- mTaskOrganizer.applyTransaction(wct);
+ mSideStage.moveToTop(getSideStageBounds(), wct);
+ mSyncQueue.queue(wct);
+ mSyncQueue.runInSync(t -> updateSurfaceBounds(mSplitLayout, t));
}
if (!mLogger.hasStartedSession() && mMainStageListener.mHasChildren
&& mSideStageListener.mHasChildren) {
@@ -817,8 +810,11 @@
@Override
public void onLayoutSizeChanging(SplitLayout layout) {
- mSyncQueue.runInSync(t -> updateSurfaceBounds(layout, t));
- mSideStage.setOutlineVisibility(false);
+ mSyncQueue.runInSync(t -> {
+ updateSurfaceBounds(layout, t);
+ mMainStage.onResizing(getMainStageBounds(), t);
+ mSideStage.onResizing(getSideStageBounds(), t);
+ });
}
@Override
@@ -827,8 +823,11 @@
updateWindowBounds(layout, wct);
updateUnfoldBounds();
mSyncQueue.queue(wct);
- mSyncQueue.runInSync(t -> updateSurfaceBounds(layout, t));
- mSideStage.setOutlineVisibility(true);
+ mSyncQueue.runInSync(t -> {
+ updateSurfaceBounds(layout, t);
+ mMainStage.onResized(getMainStageBounds(), t);
+ mSideStage.onResized(getSideStageBounds(), t);
+ });
mLogger.logResize(mSplitLayout.getDividerPositionAsFraction());
}
@@ -893,7 +892,7 @@
if (mSplitLayout == null) {
mSplitLayout = new SplitLayout(TAG + "SplitDivider", mContext,
mDisplayAreaInfo.configuration, this, mParentContainerCallbacks,
- mDisplayImeController, mTaskOrganizer);
+ mDisplayImeController, mTaskOrganizer, false /* applyDismissingParallax */);
mDisplayInsetsController.addInsetsChangedListener(mDisplayId, mSplitLayout);
if (mMainUnfoldController != null && mSideUnfoldController != null) {
@@ -1216,18 +1215,6 @@
null /* taskInfo */, false /* allowEnterPip */, TYPE_DOCK_DIVIDER);
}
- RemoteAnimationTarget getOutlineLegacyTarget() {
- final Rect bounds = mSideStage.mRootTaskInfo.configuration.windowConfiguration.getBounds();
- // Leverage TYPE_DOCK_DIVIDER type when wrapping outline remote animation target in order to
- // distinguish as a split auxiliary target in Launcher.
- return new RemoteAnimationTarget(-1 /* taskId */, -1 /* mode */,
- mSideStage.getOutlineLeash(), false /* isTranslucent */, null /* clipRect */,
- null /* contentInsets */, Integer.MAX_VALUE /* prefixOrderIndex */,
- new android.graphics.Point(0, 0) /* position */, bounds, bounds,
- new WindowConfiguration(), true, null /* startLeash */, null /* startBounds */,
- null /* taskInfo */, false /* allowEnterPip */, TYPE_DOCK_DIVIDER);
- }
-
@Override
public void dump(@NonNull PrintWriter pw, String prefix) {
final String innerPrefix = prefix + " ";
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/StageTaskListener.java b/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/StageTaskListener.java
index 6f1a09d..5100c56 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/StageTaskListener.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/StageTaskListener.java
@@ -26,6 +26,7 @@
import android.annotation.CallSuper;
import android.annotation.Nullable;
import android.app.ActivityManager;
+import android.content.Context;
import android.graphics.Point;
import android.graphics.Rect;
import android.util.SparseArray;
@@ -35,9 +36,11 @@
import androidx.annotation.NonNull;
+import com.android.launcher3.icons.IconProvider;
import com.android.wm.shell.ShellTaskOrganizer;
import com.android.wm.shell.common.SurfaceUtils;
import com.android.wm.shell.common.SyncTransactionQueue;
+import com.android.wm.shell.common.split.SplitDecorManager;
import java.io.PrintWriter;
@@ -72,25 +75,31 @@
void onNoLongerSupportMultiWindow();
}
+ private final Context mContext;
private final StageListenerCallbacks mCallbacks;
private final SurfaceSession mSurfaceSession;
- protected final SyncTransactionQueue mSyncQueue;
+ private final SyncTransactionQueue mSyncQueue;
+ private final IconProvider mIconProvider;
protected ActivityManager.RunningTaskInfo mRootTaskInfo;
protected SurfaceControl mRootLeash;
protected SurfaceControl mDimLayer;
protected SparseArray<ActivityManager.RunningTaskInfo> mChildrenTaskInfo = new SparseArray<>();
private final SparseArray<SurfaceControl> mChildrenLeashes = new SparseArray<>();
+ // TODO(b/204308910): Extracts SplitDecorManager related code to common package.
+ private SplitDecorManager mSplitDecorManager;
private final StageTaskUnfoldController mStageTaskUnfoldController;
- StageTaskListener(ShellTaskOrganizer taskOrganizer, int displayId,
+ StageTaskListener(Context context, ShellTaskOrganizer taskOrganizer, int displayId,
StageListenerCallbacks callbacks, SyncTransactionQueue syncQueue,
- SurfaceSession surfaceSession,
+ SurfaceSession surfaceSession, IconProvider iconProvider,
@Nullable StageTaskUnfoldController stageTaskUnfoldController) {
+ mContext = context;
mCallbacks = callbacks;
mSyncQueue = syncQueue;
mSurfaceSession = surfaceSession;
+ mIconProvider = iconProvider;
mStageTaskUnfoldController = stageTaskUnfoldController;
taskOrganizer.createRootTask(displayId, WINDOWING_MODE_MULTI_WINDOW, this);
}
@@ -142,13 +151,14 @@
if (mRootTaskInfo == null && !taskInfo.hasParentTask()) {
mRootLeash = leash;
mRootTaskInfo = taskInfo;
+ mSplitDecorManager = new SplitDecorManager(
+ mRootTaskInfo.configuration,
+ mIconProvider,
+ mSurfaceSession);
mCallbacks.onRootTaskAppeared();
sendStatusChanged();
- mSyncQueue.runInSync(t -> {
- t.hide(mRootLeash);
- mDimLayer =
- SurfaceUtils.makeDimLayer(t, mRootLeash, "Dim layer", mSurfaceSession);
- });
+ mSyncQueue.runInSync(t -> mDimLayer =
+ SurfaceUtils.makeDimLayer(t, mRootLeash, "Dim layer", mSurfaceSession));
} else if (taskInfo.parentTaskId == mRootTaskInfo.taskId) {
final int taskId = taskInfo.taskId;
mChildrenLeashes.put(taskId, leash);
@@ -179,6 +189,17 @@
return;
}
if (mRootTaskInfo.taskId == taskInfo.taskId) {
+ // Inflates split decor view only when the root task is visible.
+ if (mRootTaskInfo.isVisible != taskInfo.isVisible) {
+ mSyncQueue.runInSync(t -> {
+ if (taskInfo.isVisible) {
+ mSplitDecorManager.inflate(mContext, mRootLeash,
+ taskInfo.configuration.windowConfiguration.getBounds());
+ } else {
+ mSplitDecorManager.release(t);
+ }
+ });
+ }
mRootTaskInfo = taskInfo;
} else if (taskInfo.parentTaskId == mRootTaskInfo.taskId) {
mChildrenTaskInfo.put(taskInfo.taskId, taskInfo);
@@ -205,8 +226,11 @@
final int taskId = taskInfo.taskId;
if (mRootTaskInfo.taskId == taskId) {
mCallbacks.onRootTaskVanished();
- mSyncQueue.runInSync(t -> t.remove(mDimLayer));
mRootTaskInfo = null;
+ mSyncQueue.runInSync(t -> {
+ t.remove(mDimLayer);
+ mSplitDecorManager.release(t);
+ });
} else if (mChildrenTaskInfo.contains(taskId)) {
mChildrenTaskInfo.remove(taskId);
mChildrenLeashes.remove(taskId);
@@ -237,6 +261,18 @@
}
}
+ void onResizing(Rect newBounds, SurfaceControl.Transaction t) {
+ if (mSplitDecorManager != null && mRootTaskInfo != null) {
+ mSplitDecorManager.onResizing(mRootTaskInfo, newBounds, t);
+ }
+ }
+
+ void onResized(Rect newBounds, SurfaceControl.Transaction t) {
+ if (mSplitDecorManager != null) {
+ mSplitDecorManager.onResized(newBounds, t);
+ }
+ }
+
void setBounds(Rect bounds, WindowContainerTransaction wct) {
wct.setBounds(mRootTaskInfo.token, bounds);
}
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/stagesplit/StageCoordinator.java b/libs/WindowManager/Shell/src/com/android/wm/shell/stagesplit/StageCoordinator.java
index 574e379..60a6cd7 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/stagesplit/StageCoordinator.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/stagesplit/StageCoordinator.java
@@ -882,7 +882,7 @@
if (mSplitLayout == null) {
mSplitLayout = new SplitLayout(TAG + "SplitDivider", mContext,
mDisplayAreaInfo.configuration, this, mParentContainerCallbacks,
- mDisplayImeController, mTaskOrganizer);
+ mDisplayImeController, mTaskOrganizer, true /* applyDismissingParallax */);
mDisplayInsetsController.addInsetsChangedListener(mDisplayId, mSplitLayout);
if (mMainUnfoldController != null && mSideUnfoldController != null) {
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/startingsurface/SplashscreenIconDrawableFactory.java b/libs/WindowManager/Shell/src/com/android/wm/shell/startingsurface/SplashscreenIconDrawableFactory.java
index 38122ff..e2a72bd 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/startingsurface/SplashscreenIconDrawableFactory.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/startingsurface/SplashscreenIconDrawableFactory.java
@@ -314,7 +314,7 @@
@Override
public void stopAnimation() {
- if (mIconAnimator != null) {
+ if (mIconAnimator != null && mIconAnimator.isRunning()) {
mIconAnimator.end();
}
}
diff --git a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/CommonAssertions.kt b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/CommonAssertions.kt
index c07f0eb..c4be785 100644
--- a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/CommonAssertions.kt
+++ b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/CommonAssertions.kt
@@ -78,7 +78,7 @@
assertLayersEnd {
val dividerRegion = layer(APP_PAIR_SPLIT_DIVIDER_COMPONENT).visibleRegion.region
visibleRegion(primaryComponent)
- .coversExactly(getPrimaryRegion(dividerRegion, rotation))
+ .overlaps(getPrimaryRegion(dividerRegion, rotation))
}
}
@@ -89,7 +89,7 @@
assertLayersEnd {
val dividerRegion = layer(DOCKED_STACK_DIVIDER_COMPONENT).visibleRegion.region
visibleRegion(primaryComponent)
- .coversExactly(getPrimaryRegion(dividerRegion, rotation))
+ .overlaps(getPrimaryRegion(dividerRegion, rotation))
}
}
@@ -100,7 +100,7 @@
assertLayersEnd {
val dividerRegion = layer(APP_PAIR_SPLIT_DIVIDER_COMPONENT).visibleRegion.region
visibleRegion(secondaryComponent)
- .coversExactly(getSecondaryRegion(dividerRegion, rotation))
+ .overlaps(getSecondaryRegion(dividerRegion, rotation))
}
}
@@ -111,7 +111,7 @@
assertLayersEnd {
val dividerRegion = layer(DOCKED_STACK_DIVIDER_COMPONENT).visibleRegion.region
visibleRegion(secondaryComponent)
- .coversExactly(getSecondaryRegion(dividerRegion, rotation))
+ .overlaps(getSecondaryRegion(dividerRegion, rotation))
}
}
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 2614b4a..80acd3d 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,9 +18,9 @@
import android.content.Context
import android.graphics.Point
+import android.platform.test.annotations.Postsubmit
import android.util.DisplayMetrics
import android.view.WindowManager
-import androidx.test.filters.FlakyTest
import androidx.test.filters.RequiresDevice
import androidx.test.uiautomator.By
import androidx.test.uiautomator.Until
@@ -66,7 +66,7 @@
}
}
- @FlakyTest
+ @Postsubmit
@Test
fun testAppIsAlwaysVisible() {
testSpec.assertLayers {
diff --git a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/bubble/ExpandBubbleScreen.kt b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/bubble/ExpandBubbleScreen.kt
index 2679c10..66520d2 100644
--- a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/bubble/ExpandBubbleScreen.kt
+++ b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/bubble/ExpandBubbleScreen.kt
@@ -16,7 +16,7 @@
package com.android.wm.shell.flicker.bubble
-import androidx.test.filters.FlakyTest
+import android.platform.test.annotations.Postsubmit
import androidx.test.filters.RequiresDevice
import androidx.test.uiautomator.By
import androidx.test.uiautomator.Until
@@ -59,7 +59,7 @@
}
}
- @FlakyTest
+ @Postsubmit
@Test
fun testAppIsAlwaysVisible() {
testSpec.assertLayers {
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 7b25908..97c27c7 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,7 +16,7 @@
package com.android.wm.shell.flicker.bubble
-import androidx.test.filters.FlakyTest
+import android.platform.test.annotations.Postsubmit
import androidx.test.filters.RequiresDevice
import com.android.server.wm.flicker.FlickerParametersRunnerFactory
import com.android.server.wm.flicker.FlickerTestParameter
@@ -49,7 +49,7 @@
}
}
- @FlakyTest
+ @Postsubmit
@Test
fun testAppIsAlwaysVisible() {
testSpec.assertLayers {
diff --git a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/bubble/MultiBubblesScreen.kt b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/bubble/MultiBubblesScreen.kt
index 19edd6f..d92e047 100644
--- a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/bubble/MultiBubblesScreen.kt
+++ b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/bubble/MultiBubblesScreen.kt
@@ -17,7 +17,7 @@
package com.android.wm.shell.flicker.bubble
import android.os.SystemClock
-import androidx.test.filters.FlakyTest
+import android.platform.test.annotations.Postsubmit
import androidx.test.filters.RequiresDevice
import androidx.test.uiautomator.By
import androidx.test.uiautomator.Until
@@ -67,7 +67,7 @@
}
}
- @FlakyTest
+ @Postsubmit
@Test
fun testAppIsAlwaysVisible() {
testSpec.assertLayers {
diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/common/DisplayLayoutTest.java b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/common/DisplayLayoutTest.java
index 88e754c..0ffa5b3 100644
--- a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/common/DisplayLayoutTest.java
+++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/common/DisplayLayoutTest.java
@@ -21,9 +21,14 @@
import static android.view.Surface.ROTATION_270;
import static android.view.Surface.ROTATION_90;
+import static com.android.dx.mockito.inline.extended.ExtendedMockito.mockitoSession;
+
import static org.junit.Assert.assertEquals;
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.Mockito.doReturn;
import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.when;
import android.content.res.Configuration;
import android.content.res.Resources;
@@ -35,8 +40,12 @@
import androidx.test.filters.SmallTest;
import com.android.internal.R;
+import com.android.internal.policy.SystemBarUtils;
+import org.junit.After;
+import org.junit.Before;
import org.junit.Test;
+import org.mockito.MockitoSession;
/**
* Tests for {@link DisplayLayout}.
@@ -46,29 +55,48 @@
*/
@SmallTest
public class DisplayLayoutTest {
+ private MockitoSession mMockitoSession;
+
+ @Before
+ public void setup() {
+ mMockitoSession = mockitoSession()
+ .initMocks(this)
+ .mockStatic(SystemBarUtils.class)
+ .startMocking();
+ }
+
+ @After
+ public void tearDown() {
+ mMockitoSession.finishMocking();
+ }
@Test
public void testInsets() {
- Resources res = createResources(40, 50, false, 30, 40);
+ Resources res = createResources(40, 50, false);
// Test empty display, no bars or anything
DisplayInfo info = createDisplayInfo(1000, 1500, 0, ROTATION_0);
DisplayLayout dl = new DisplayLayout(info, res, false, false);
+ when(SystemBarUtils.getStatusBarHeight(eq(res), any())).thenReturn(40);
+ dl.recalcInsets(res);
assertEquals(new Rect(0, 0, 0, 0), dl.stableInsets());
assertEquals(new Rect(0, 0, 0, 0), dl.nonDecorInsets());
// Test with bars
dl = new DisplayLayout(info, res, true, true);
+ dl.recalcInsets(res);
assertEquals(new Rect(0, 40, 0, 50), dl.stableInsets());
assertEquals(new Rect(0, 0, 0, 50), dl.nonDecorInsets());
// Test just cutout
info = createDisplayInfo(1000, 1500, 60, ROTATION_0);
dl = new DisplayLayout(info, res, false, false);
+ dl.recalcInsets(res);
assertEquals(new Rect(0, 60, 0, 0), dl.stableInsets());
assertEquals(new Rect(0, 60, 0, 0), dl.nonDecorInsets());
// Test with bars and cutout
dl = new DisplayLayout(info, res, true, true);
+ dl.recalcInsets(res);
assertEquals(new Rect(0, 60, 0, 50), dl.stableInsets());
assertEquals(new Rect(0, 60, 0, 50), dl.nonDecorInsets());
}
@@ -76,27 +104,30 @@
@Test
public void testRotate() {
// Basic rotate utility
- Resources res = createResources(40, 50, false, 30, 40);
+ Resources res = createResources(40, 50, false);
DisplayInfo info = createDisplayInfo(1000, 1500, 60, ROTATION_0);
DisplayLayout dl = new DisplayLayout(info, res, true, true);
+ when(SystemBarUtils.getStatusBarHeight(eq(res), any())).thenReturn(40);
+ dl.recalcInsets(res);
assertEquals(new Rect(0, 60, 0, 50), dl.stableInsets());
assertEquals(new Rect(0, 60, 0, 50), dl.nonDecorInsets());
// Rotate to 90
+ when(SystemBarUtils.getStatusBarHeight(eq(res), any())).thenReturn(30);
dl.rotateTo(res, ROTATION_90);
assertEquals(new Rect(60, 30, 0, 40), dl.stableInsets());
assertEquals(new Rect(60, 0, 0, 40), dl.nonDecorInsets());
// Rotate with moving navbar
- res = createResources(40, 50, true, 30, 40);
+ res = createResources(40, 50, true);
dl = new DisplayLayout(info, res, true, true);
+ when(SystemBarUtils.getStatusBarHeight(eq(res), any())).thenReturn(30);
dl.rotateTo(res, ROTATION_270);
assertEquals(new Rect(40, 30, 60, 0), dl.stableInsets());
assertEquals(new Rect(40, 0, 60, 0), dl.nonDecorInsets());
}
- private Resources createResources(
- int navLand, int navPort, boolean navMoves, int statusLand, int statusPort) {
+ private Resources createResources(int navLand, int navPort, boolean navMoves) {
Configuration cfg = new Configuration();
cfg.uiMode = UI_MODE_TYPE_NORMAL;
Resources res = mock(Resources.class);
@@ -108,8 +139,6 @@
doReturn(navPort).when(res).getDimensionPixelSize(R.dimen.navigation_bar_height);
doReturn(navLand).when(res).getDimensionPixelSize(R.dimen.navigation_bar_width);
doReturn(navMoves).when(res).getBoolean(R.bool.config_navBarCanMove);
- doReturn(statusLand).when(res).getDimensionPixelSize(R.dimen.status_bar_height_landscape);
- doReturn(statusPort).when(res).getDimensionPixelSize(R.dimen.status_bar_height_portrait);
doReturn(cfg).when(res).getConfiguration();
return res;
}
diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/common/split/SplitLayoutTests.java b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/common/split/SplitLayoutTests.java
index b4caeb5..73eebad 100644
--- a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/common/split/SplitLayoutTests.java
+++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/common/split/SplitLayoutTests.java
@@ -68,7 +68,8 @@
mSplitLayoutHandler,
mCallbacks,
mDisplayImeController,
- mTaskOrganizer));
+ mTaskOrganizer,
+ false /* applyDismissingParallax */));
}
@Test
diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/hidedisplaycutout/HideDisplayCutoutOrganizerTest.java b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/hidedisplaycutout/HideDisplayCutoutOrganizerTest.java
index 3c124ba..078e2b6 100644
--- a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/hidedisplaycutout/HideDisplayCutoutOrganizerTest.java
+++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/hidedisplaycutout/HideDisplayCutoutOrganizerTest.java
@@ -48,7 +48,6 @@
import androidx.test.InstrumentationRegistry;
import androidx.test.filters.SmallTest;
-import com.android.internal.R;
import com.android.wm.shell.common.DisplayController;
import com.android.wm.shell.common.DisplayLayout;
import com.android.wm.shell.common.ShellExecutor;
@@ -124,6 +123,7 @@
@Test
public void testEnableHideDisplayCutout() {
+ doReturn(mFakeStatusBarHeightPortrait).when(mOrganizer).getStatusBarHeight();
mOrganizer.enableHideDisplayCutout();
verify(mOrganizer).registerOrganizer(DisplayAreaOrganizer.FEATURE_HIDE_DISPLAY_CUTOUT);
@@ -154,8 +154,7 @@
doReturn(mFakeDefaultBounds).when(mOrganizer).getDisplayBoundsOfNaturalOrientation();
doReturn(mFakeDefaultCutoutInsets).when(mOrganizer)
.getDisplayCutoutInsetsOfNaturalOrientation();
- mContext.getOrCreateTestableResources().addOverride(
- R.dimen.status_bar_height_portrait, mFakeStatusBarHeightPortrait);
+ doReturn(mFakeStatusBarHeightPortrait).when(mOrganizer).getStatusBarHeight();
doReturn(Surface.ROTATION_0).when(mDisplayLayout).rotation();
mOrganizer.enableHideDisplayCutout();
@@ -173,8 +172,7 @@
doReturn(mFakeDefaultBounds).when(mOrganizer).getDisplayBoundsOfNaturalOrientation();
doReturn(mFakeDefaultCutoutInsets).when(mOrganizer)
.getDisplayCutoutInsetsOfNaturalOrientation();
- mContext.getOrCreateTestableResources().addOverride(
- R.dimen.status_bar_height_landscape, mFakeStatusBarHeightLandscape);
+ doReturn(mFakeStatusBarHeightLandscape).when(mOrganizer).getStatusBarHeight();
doReturn(Surface.ROTATION_90).when(mDisplayLayout).rotation();
mOrganizer.enableHideDisplayCutout();
@@ -192,8 +190,7 @@
doReturn(mFakeDefaultBounds).when(mOrganizer).getDisplayBoundsOfNaturalOrientation();
doReturn(mFakeDefaultCutoutInsets).when(mOrganizer)
.getDisplayCutoutInsetsOfNaturalOrientation();
- mContext.getOrCreateTestableResources().addOverride(
- R.dimen.status_bar_height_landscape, mFakeStatusBarHeightLandscape);
+ doReturn(mFakeStatusBarHeightLandscape).when(mOrganizer).getStatusBarHeight();
doReturn(Surface.ROTATION_270).when(mDisplayLayout).rotation();
mOrganizer.enableHideDisplayCutout();
@@ -211,8 +208,7 @@
doReturn(mFakeDefaultBounds).when(mOrganizer).getDisplayBoundsOfNaturalOrientation();
doReturn(mFakeDefaultCutoutInsets).when(mOrganizer)
.getDisplayCutoutInsetsOfNaturalOrientation();
- mContext.getOrCreateTestableResources().addOverride(
- R.dimen.status_bar_height_portrait, mFakeStatusBarHeightPortrait);
+ doReturn(mFakeStatusBarHeightPortrait).when(mOrganizer).getStatusBarHeight();
mOrganizer.enableHideDisplayCutout();
// disable hide display cutout
@@ -230,8 +226,7 @@
doReturn(200).when(mDisplayLayout).height();
doReturn(mFakeDefaultCutoutInsets).when(mOrganizer)
.getDisplayCutoutInsetsOfNaturalOrientation();
- mContext.getOrCreateTestableResources().addOverride(
- R.dimen.status_bar_height_portrait, mFakeStatusBarHeightPortrait);
+ doReturn(mFakeStatusBarHeightPortrait).when(mOrganizer).getStatusBarHeight();
doReturn(Surface.ROTATION_0).when(mDisplayLayout).rotation();
mOrganizer.enableHideDisplayCutout();
assertThat(mOrganizer.mCurrentDisplayBounds).isEqualTo(new Rect(0, 15, 100, 200));
diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/splitscreen/MainStageTests.java b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/splitscreen/MainStageTests.java
index 2bcc45e..c972067 100644
--- a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/splitscreen/MainStageTests.java
+++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/splitscreen/MainStageTests.java
@@ -25,10 +25,13 @@
import android.view.SurfaceSession;
import android.window.WindowContainerTransaction;
+import androidx.test.annotation.UiThreadTest;
import androidx.test.ext.junit.runners.AndroidJUnit4;
import androidx.test.filters.SmallTest;
+import com.android.launcher3.icons.IconProvider;
import com.android.wm.shell.ShellTaskOrganizer;
+import com.android.wm.shell.ShellTestCase;
import com.android.wm.shell.TestRunningTaskInfoBuilder;
import com.android.wm.shell.common.SyncTransactionQueue;
@@ -41,22 +44,24 @@
/** Tests for {@link MainStage} */
@SmallTest
@RunWith(AndroidJUnit4.class)
-public class MainStageTests {
+public class MainStageTests extends ShellTestCase {
@Mock private ShellTaskOrganizer mTaskOrganizer;
@Mock private StageTaskListener.StageListenerCallbacks mCallbacks;
@Mock private SyncTransactionQueue mSyncQueue;
@Mock private ActivityManager.RunningTaskInfo mRootTaskInfo;
@Mock private SurfaceControl mRootLeash;
+ @Mock private IconProvider mIconProvider;
private WindowContainerTransaction mWct = new WindowContainerTransaction();
private SurfaceSession mSurfaceSession = new SurfaceSession();
private MainStage mMainStage;
@Before
+ @UiThreadTest
public void setup() {
MockitoAnnotations.initMocks(this);
mRootTaskInfo = new TestRunningTaskInfoBuilder().build();
- mMainStage = new MainStage(mTaskOrganizer, DEFAULT_DISPLAY, mCallbacks, mSyncQueue,
- mSurfaceSession, null);
+ mMainStage = new MainStage(mContext, mTaskOrganizer, DEFAULT_DISPLAY, mCallbacks,
+ mSyncQueue, mSurfaceSession, mIconProvider, null);
mMainStage.onTaskAppeared(mRootTaskInfo, mRootLeash);
}
diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/splitscreen/SideStageTests.java b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/splitscreen/SideStageTests.java
index 838aa81..a31aa58 100644
--- a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/splitscreen/SideStageTests.java
+++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/splitscreen/SideStageTests.java
@@ -33,6 +33,7 @@
import androidx.test.ext.junit.runners.AndroidJUnit4;
import androidx.test.filters.SmallTest;
+import com.android.launcher3.icons.IconProvider;
import com.android.wm.shell.ShellTaskOrganizer;
import com.android.wm.shell.ShellTestCase;
import com.android.wm.shell.TestRunningTaskInfoBuilder;
@@ -54,6 +55,7 @@
@Mock private SyncTransactionQueue mSyncQueue;
@Mock private ActivityManager.RunningTaskInfo mRootTask;
@Mock private SurfaceControl mRootLeash;
+ @Mock private IconProvider mIconProvider;
@Spy private WindowContainerTransaction mWct;
private SurfaceSession mSurfaceSession = new SurfaceSession();
private SideStage mSideStage;
@@ -64,7 +66,7 @@
MockitoAnnotations.initMocks(this);
mRootTask = new TestRunningTaskInfoBuilder().build();
mSideStage = new SideStage(mContext, mTaskOrganizer, DEFAULT_DISPLAY, mCallbacks,
- mSyncQueue, mSurfaceSession, null);
+ mSyncQueue, mSurfaceSession, mIconProvider, null);
mSideStage.onTaskAppeared(mRootTask, mRootLeash);
}
@@ -72,7 +74,7 @@
public void testAddTask() {
final ActivityManager.RunningTaskInfo task = new TestRunningTaskInfoBuilder().build();
- mSideStage.addTask(task, mRootTask.configuration.windowConfiguration.getBounds(), mWct);
+ mSideStage.addTask(task, mWct);
verify(mWct).reparent(eq(task.token), eq(mRootTask.token), eq(true));
}
diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/splitscreen/SplitTransitionTests.java b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/splitscreen/SplitTransitionTests.java
index 05496b0..d5dee82 100644
--- a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/splitscreen/SplitTransitionTests.java
+++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/splitscreen/SplitTransitionTests.java
@@ -55,6 +55,7 @@
import androidx.test.filters.SmallTest;
import androidx.test.runner.AndroidJUnit4;
+import com.android.launcher3.icons.IconProvider;
import com.android.wm.shell.RootTaskDisplayAreaOrganizer;
import com.android.wm.shell.ShellTaskOrganizer;
import com.android.wm.shell.ShellTestCase;
@@ -89,6 +90,7 @@
@Mock private Transitions mTransitions;
@Mock private SurfaceSession mSurfaceSession;
@Mock private SplitscreenEventLogger mLogger;
+ @Mock private IconProvider mIconProvider;
private SplitLayout mSplitLayout;
private MainStage mMainStage;
private SideStage mSideStage;
@@ -107,11 +109,13 @@
doReturn(mockExecutor).when(mTransitions).getAnimExecutor();
doReturn(mock(SurfaceControl.Transaction.class)).when(mTransactionPool).acquire();
mSplitLayout = SplitTestUtils.createMockSplitLayout();
- mMainStage = new MainStage(mTaskOrganizer, DEFAULT_DISPLAY, mock(
- StageTaskListener.StageListenerCallbacks.class), mSyncQueue, mSurfaceSession, null);
+ mMainStage = new MainStage(mContext, mTaskOrganizer, DEFAULT_DISPLAY, mock(
+ StageTaskListener.StageListenerCallbacks.class), mSyncQueue, mSurfaceSession,
+ mIconProvider, null);
mMainStage.onTaskAppeared(new TestRunningTaskInfoBuilder().build(), createMockSurface());
mSideStage = new SideStage(mContext, mTaskOrganizer, DEFAULT_DISPLAY, mock(
- StageTaskListener.StageListenerCallbacks.class), mSyncQueue, mSurfaceSession, null);
+ StageTaskListener.StageListenerCallbacks.class), mSyncQueue, mSurfaceSession,
+ mIconProvider, null);
mSideStage.onTaskAppeared(new TestRunningTaskInfoBuilder().build(), createMockSurface());
mStageCoordinator = new SplitTestUtils.TestStageCoordinator(mContext, DEFAULT_DISPLAY,
mSyncQueue, mRootTDAOrganizer, mTaskOrganizer, mMainStage, mSideStage,
diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/splitscreen/StageCoordinatorTests.java b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/splitscreen/StageCoordinatorTests.java
index cd29220..617e94a 100644
--- a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/splitscreen/StageCoordinatorTests.java
+++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/splitscreen/StageCoordinatorTests.java
@@ -113,10 +113,7 @@
mStageCoordinator.moveToSideStage(task, SPLIT_POSITION_BOTTOM_OR_RIGHT);
- verify(mMainStage).activate(any(Rect.class), any(WindowContainerTransaction.class),
- eq(true /* includingTopTask */));
- verify(mSideStage).addTask(eq(task), any(Rect.class),
- any(WindowContainerTransaction.class));
+ verify(mSideStage).addTask(eq(task), any(WindowContainerTransaction.class));
}
@Test
diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/splitscreen/StageTaskListenerTests.java b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/splitscreen/StageTaskListenerTests.java
index 3ed72e2..53d5076 100644
--- a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/splitscreen/StageTaskListenerTests.java
+++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/splitscreen/StageTaskListenerTests.java
@@ -35,10 +35,13 @@
import android.view.SurfaceSession;
import android.window.WindowContainerTransaction;
+import androidx.test.annotation.UiThreadTest;
import androidx.test.ext.junit.runners.AndroidJUnit4;
import androidx.test.filters.SmallTest;
+import com.android.launcher3.icons.IconProvider;
import com.android.wm.shell.ShellTaskOrganizer;
+import com.android.wm.shell.ShellTestCase;
import com.android.wm.shell.TestRunningTaskInfoBuilder;
import com.android.wm.shell.common.SyncTransactionQueue;
@@ -57,7 +60,7 @@
*/
@SmallTest
@RunWith(AndroidJUnit4.class)
-public final class StageTaskListenerTests {
+public final class StageTaskListenerTests extends ShellTestCase {
private static final boolean ENABLE_SHELL_TRANSITIONS =
SystemProperties.getBoolean("persist.debug.shell_transit", false);
@@ -68,6 +71,8 @@
@Mock
private SyncTransactionQueue mSyncQueue;
@Mock
+ private IconProvider mIconProvider;
+ @Mock
private StageTaskUnfoldController mStageTaskUnfoldController;
@Captor
private ArgumentCaptor<SyncTransactionQueue.TransactionRunnable> mRunnableCaptor;
@@ -77,14 +82,17 @@
private StageTaskListener mStageTaskListener;
@Before
+ @UiThreadTest
public void setup() {
MockitoAnnotations.initMocks(this);
mStageTaskListener = new StageTaskListener(
+ mContext,
mTaskOrganizer,
DEFAULT_DISPLAY,
mCallbacks,
mSyncQueue,
mSurfaceSession,
+ mIconProvider,
mStageTaskUnfoldController);
mRootTask = new TestRunningTaskInfoBuilder().build();
mRootTask.parentTaskId = INVALID_TASK_ID;
diff --git a/libs/hwui/tests/unit/RenderNodeDrawableTests.cpp b/libs/hwui/tests/unit/RenderNodeDrawableTests.cpp
index 423400e..ec949b8 100644
--- a/libs/hwui/tests/unit/RenderNodeDrawableTests.cpp
+++ b/libs/hwui/tests/unit/RenderNodeDrawableTests.cpp
@@ -469,7 +469,7 @@
}
SkCanvas* onNewCanvas() override { return new ProjectionTestCanvas(mDrawCounter); }
sk_sp<SkSurface> onNewSurface(const SkImageInfo&) override { return nullptr; }
- void onCopyOnWrite(ContentChangeMode) override {}
+ bool onCopyOnWrite(ContentChangeMode) override { return true; }
int* mDrawCounter;
void onWritePixels(const SkPixmap&, int x, int y) {}
};
diff --git a/libs/hwui/tests/unit/SkiaPipelineTests.cpp b/libs/hwui/tests/unit/SkiaPipelineTests.cpp
index 57a7fe3..60ae604 100644
--- a/libs/hwui/tests/unit/SkiaPipelineTests.cpp
+++ b/libs/hwui/tests/unit/SkiaPipelineTests.cpp
@@ -221,7 +221,7 @@
sk_sp<SkSurface> onNewSurface(const SkImageInfo&) override { return nullptr; }
sk_sp<SkImage> onNewImageSnapshot(const SkIRect* bounds) override { return nullptr; }
T* canvas() { return static_cast<T*>(getCanvas()); }
- void onCopyOnWrite(ContentChangeMode) override {}
+ bool onCopyOnWrite(ContentChangeMode) override { return true; }
void onWritePixels(const SkPixmap&, int x, int y) override {}
};
}
diff --git a/media/Android.bp b/media/Android.bp
index aa07c13..15b24b2 100644
--- a/media/Android.bp
+++ b/media/Android.bp
@@ -68,13 +68,17 @@
"aidl/android/media/audio/common/AudioGain.aidl",
"aidl/android/media/audio/common/AudioGainConfig.aidl",
"aidl/android/media/audio/common/AudioGainMode.aidl",
+ "aidl/android/media/audio/common/AudioInputFlags.aidl",
+ "aidl/android/media/audio/common/AudioIoFlags.aidl",
"aidl/android/media/audio/common/AudioMMapPolicy.aidl",
"aidl/android/media/audio/common/AudioMMapPolicyInfo.aidl",
"aidl/android/media/audio/common/AudioMMapPolicyType.aidl",
"aidl/android/media/audio/common/AudioMode.aidl",
"aidl/android/media/audio/common/AudioOffloadInfo.aidl",
+ "aidl/android/media/audio/common/AudioOutputFlags.aidl",
"aidl/android/media/audio/common/AudioPort.aidl",
"aidl/android/media/audio/common/AudioPortConfig.aidl",
+ "aidl/android/media/audio/common/AudioPortDeviceExt.aidl",
"aidl/android/media/audio/common/AudioPortExt.aidl",
"aidl/android/media/audio/common/AudioPortMixExt.aidl",
"aidl/android/media/audio/common/AudioPortMixExtUseCase.aidl",
diff --git a/media/aidl/android/media/audio/common/AudioGain.aidl b/media/aidl/android/media/audio/common/AudioGain.aidl
index 90fdeb6..dbfcd8c 100644
--- a/media/aidl/android/media/audio/common/AudioGain.aidl
+++ b/media/aidl/android/media/audio/common/AudioGain.aidl
@@ -43,4 +43,6 @@
int minRampMs;
/** Maximum ramp duration in milliseconds. */
int maxRampMs;
+ /** Indicates whether it is allowed to use this stage for volume control. */
+ boolean useForVolume;
}
diff --git a/media/aidl/android/media/audio/common/AudioInputFlags.aidl b/media/aidl/android/media/audio/common/AudioInputFlags.aidl
new file mode 100644
index 0000000..e4b6ec2
--- /dev/null
+++ b/media/aidl/android/media/audio/common/AudioInputFlags.aidl
@@ -0,0 +1,62 @@
+/*
+ * Copyright (C) 2021 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.media.audio.common;
+
+/**
+ * Specifies options applicable to audio input. These can be functional
+ * requests or performance requests. These flags apply both to audio ports and
+ * audio streams. Flags specified for an audio stream are usually used to find
+ * the best matching audio port for it.
+ *
+ * {@hide}
+ */
+@VintfStability
+@Backing(type="int")
+enum AudioInputFlags {
+ /**
+ * Input is optimized for decreasing audio latency.
+ */
+ FAST = 0,
+ /**
+ * Input is for capturing "hotword" audio commands.
+ */
+ HW_HOTWORD = 1,
+ /**
+ * Input stream should only have minimal signal processing applied.
+ */
+ RAW = 2,
+ /**
+ * Input stream needs to be synchronized with an output stream.
+ */
+ SYNC = 3,
+ /**
+ * Input uses MMAP no IRQ mode--direct memory mapping with the hardware.
+ */
+ MMAP_NOIRQ = 4,
+ /**
+ * Input is used for receiving VoIP audio.
+ */
+ VOIP_TX = 5,
+ /**
+ * Input stream contains AV synchronization markers embedded.
+ */
+ HW_AV_SYNC = 6,
+ /**
+ * Input contains an encoded audio stream.
+ */
+ DIRECT = 7,
+}
diff --git a/core/java/android/companion/Association.aidl b/media/aidl/android/media/audio/common/AudioIoFlags.aidl
similarity index 60%
copy from core/java/android/companion/Association.aidl
copy to media/aidl/android/media/audio/common/AudioIoFlags.aidl
index 2a28f1f..f978fb6 100644
--- a/core/java/android/companion/Association.aidl
+++ b/media/aidl/android/media/audio/common/AudioIoFlags.aidl
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2019 The Android Open Source Project
+ * Copyright (C) 2021 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.
@@ -13,6 +13,19 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-package android.companion;
-parcelable Association;
+package android.media.audio.common;
+
+/**
+ * Stores a bitmask of input or output flags.
+ *
+ * {@hide}
+ */
+@JavaDerive(equals=true, toString=true)
+@VintfStability
+union AudioIoFlags {
+ /** Bitmask indexed by AudioInputFlags. */
+ int input;
+ /** Bitmask indexed by AudioOutputFlags. */
+ int output;
+}
diff --git a/media/aidl/android/media/audio/common/AudioOutputFlags.aidl b/media/aidl/android/media/audio/common/AudioOutputFlags.aidl
new file mode 100644
index 0000000..0505036
--- /dev/null
+++ b/media/aidl/android/media/audio/common/AudioOutputFlags.aidl
@@ -0,0 +1,100 @@
+/*
+ * Copyright (C) 2021 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.media.audio.common;
+
+/**
+ * Specifies options applicable to audio output. These can be functional
+ * requests or performance requests. These flags apply both to audio ports and
+ * audio streams. Flags specified for an audio stream are usually used to find
+ * the best matching audio port for it.
+ *
+ * {@hide}
+ */
+@VintfStability
+@Backing(type="int")
+enum AudioOutputFlags {
+ /**
+ * Output must not be altered by the framework, it bypasses software mixers.
+ */
+ DIRECT = 0,
+ /**
+ * When used with audio ports, indicates the "main" (primary) port. This
+ * port is opened by default and receives routing, audio mode and volume
+ * controls related to voice calls.
+ */
+ PRIMARY = 1,
+ /**
+ * Output is optimized for decreasing audio latency.
+ */
+ FAST = 2,
+ /**
+ * Output is optimized for having the low power consumption.
+ */
+ DEEP_BUFFER = 3,
+ /**
+ * Output is compressed audio format, intended for hardware decoding.
+ */
+ COMPRESS_OFFLOAD = 4,
+ /**
+ * Write operations must return as fast as possible instead of
+ * being blocked until all provided data has been consumed.
+ */
+ NON_BLOCKING = 5,
+ /**
+ * Output stream contains AV synchronization markers embedded.
+ */
+ HW_AV_SYNC = 6,
+ /**
+ * Used to support ultrasonic communication with beacons.
+ * Note: "TTS" here means "Transmitted Through Speaker",
+ * not "Text-to-Speech".
+ */
+ TTS = 7,
+ /**
+ * Output stream should only have minimal signal processing applied.
+ */
+ RAW = 8,
+ /**
+ * Output stream needs to be synchronized with an input stream.
+ */
+ SYNC = 9,
+ /**
+ * Output stream is encoded according to IEC958.
+ */
+ IEC958_NONAUDIO = 10,
+ /**
+ * Output must not be altered by the framework and hardware.
+ */
+ DIRECT_PCM = 11,
+ /**
+ * Output uses MMAP no IRQ mode--direct memory mapping with the hardware.
+ */
+ MMAP_NOIRQ = 12,
+ /**
+ * Output is used for transmitting VoIP audio.
+ */
+ VOIP_RX = 13,
+ /**
+ * Output is used for music playback during telephony calls.
+ */
+ INCALL_MUSIC = 14,
+ /**
+ * The rendered must ignore any empty blocks between compressed audio
+ * tracks.
+ */
+ GAPLESS_OFFLOAD = 15,
+}
diff --git a/media/aidl/android/media/audio/common/AudioPort.aidl b/media/aidl/android/media/audio/common/AudioPort.aidl
index 19652bc..8e1c5af 100644
--- a/media/aidl/android/media/audio/common/AudioPort.aidl
+++ b/media/aidl/android/media/audio/common/AudioPort.aidl
@@ -17,6 +17,7 @@
package android.media.audio.common;
import android.media.audio.common.AudioGain;
+import android.media.audio.common.AudioIoFlags;
import android.media.audio.common.AudioPortConfig;
import android.media.audio.common.AudioPortExt;
import android.media.audio.common.AudioProfile;
@@ -45,6 +46,10 @@
*/
AudioProfile[] profiles;
/**
+ * I/O feature flags.
+ */
+ AudioIoFlags flags;
+ /**
* ExtraAudioDescriptors supported by this port. Used for formats not
* recognized by the platform. The audio capability is described by a
* hardware descriptor.
diff --git a/media/aidl/android/media/audio/common/AudioPortConfig.aidl b/media/aidl/android/media/audio/common/AudioPortConfig.aidl
index 44850f4..e3a9374 100644
--- a/media/aidl/android/media/audio/common/AudioPortConfig.aidl
+++ b/media/aidl/android/media/audio/common/AudioPortConfig.aidl
@@ -19,6 +19,7 @@
import android.media.audio.common.AudioChannelLayout;
import android.media.audio.common.AudioFormatDescription;
import android.media.audio.common.AudioGainConfig;
+import android.media.audio.common.AudioIoFlags;
import android.media.audio.common.AudioPortExt;
import android.media.audio.common.Int;
@@ -44,6 +45,8 @@
@nullable AudioFormatDescription format;
/** Gain to apply. Can be left unspecified. */
@nullable AudioGainConfig gain;
+ /** I/O feature flags. Can be left unspecified. */
+ @nullable AudioIoFlags flags;
/** Extra parameters depending on the port role. */
AudioPortExt ext;
}
diff --git a/media/aidl/android/media/audio/common/AudioPortDeviceExt.aidl b/media/aidl/android/media/audio/common/AudioPortDeviceExt.aidl
new file mode 100644
index 0000000..940566c
--- /dev/null
+++ b/media/aidl/android/media/audio/common/AudioPortDeviceExt.aidl
@@ -0,0 +1,38 @@
+/*
+ * Copyright (C) 2021 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.media.audio.common;
+
+import android.media.audio.common.AudioDevice;
+import android.media.audio.common.AudioFormatDescription;
+
+/**
+ * Extra parameters which are specified when the audio port is in the device role.
+ *
+ * {@hide}
+ */
+@JavaDerive(equals=true, toString=true)
+@VintfStability
+parcelable AudioPortDeviceExt {
+ /** Audio device specification. */
+ AudioDevice device;
+ /**
+ * List of supported encoded formats. Specified for ports that perform
+ * hardware-accelerated decoding or transcoding, or connected to external
+ * hardware.
+ */
+ AudioFormatDescription[] encodedFormats;
+}
diff --git a/media/aidl/android/media/audio/common/AudioPortExt.aidl b/media/aidl/android/media/audio/common/AudioPortExt.aidl
index 9b60c57..c4681cb 100644
--- a/media/aidl/android/media/audio/common/AudioPortExt.aidl
+++ b/media/aidl/android/media/audio/common/AudioPortExt.aidl
@@ -16,7 +16,7 @@
package android.media.audio.common;
-import android.media.audio.common.AudioDevice;
+import android.media.audio.common.AudioPortDeviceExt;
import android.media.audio.common.AudioPortMixExt;
/**
@@ -30,9 +30,9 @@
union AudioPortExt {
/** Represents an empty union. Value is ignored. */
boolean unspecified;
- /** Audio device specification. */
- AudioDevice device;
- /** Mix specific info. */
+ /** Information specific to device ports. */
+ AudioPortDeviceExt device;
+ /** Information specific to mix ports. */
AudioPortMixExt mix;
/** Audio session identifier. */
int session;
diff --git a/media/aidl/android/media/audio/common/AudioPortMixExt.aidl b/media/aidl/android/media/audio/common/AudioPortMixExt.aidl
index 54c5d8b..f3613a4 100644
--- a/media/aidl/android/media/audio/common/AudioPortMixExt.aidl
+++ b/media/aidl/android/media/audio/common/AudioPortMixExt.aidl
@@ -30,4 +30,16 @@
int handle;
/** Parameters specific to the mix use case. */
AudioPortMixExtUseCase usecase;
+ /**
+ * Maximum number of input or output streams that can be simultaneously
+ * opened for this port.
+ */
+ int maxOpenStreamCount;
+ /**
+ * Maximum number of input or output streams that can be simultaneously
+ * active for this port.
+ */
+ int maxActiveStreamCount;
+ /** Mute duration while changing device, when used for output. */
+ int recommendedMuteDurationMs;
}
diff --git a/media/aidl_api/android.media.audio.common.types/current/android/media/audio/common/AudioGain.aidl b/media/aidl_api/android.media.audio.common.types/current/android/media/audio/common/AudioGain.aidl
index 71891eb..adc5b672 100644
--- a/media/aidl_api/android.media.audio.common.types/current/android/media/audio/common/AudioGain.aidl
+++ b/media/aidl_api/android.media.audio.common.types/current/android/media/audio/common/AudioGain.aidl
@@ -43,4 +43,5 @@
int stepValue;
int minRampMs;
int maxRampMs;
+ boolean useForVolume;
}
diff --git a/media/aidl_api/android.media.audio.common.types/current/android/media/audio/common/AudioInputFlags.aidl b/media/aidl_api/android.media.audio.common.types/current/android/media/audio/common/AudioInputFlags.aidl
new file mode 100644
index 0000000..8a5dae0
--- /dev/null
+++ b/media/aidl_api/android.media.audio.common.types/current/android/media/audio/common/AudioInputFlags.aidl
@@ -0,0 +1,46 @@
+/*
+ * Copyright (C) 2021 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.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+// the interface (from the latest frozen version), the build system will
+// prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.media.audio.common;
+/* @hide */
+@Backing(type="int") @VintfStability
+enum AudioInputFlags {
+ FAST = 0,
+ HW_HOTWORD = 1,
+ RAW = 2,
+ SYNC = 3,
+ MMAP_NOIRQ = 4,
+ VOIP_TX = 5,
+ HW_AV_SYNC = 6,
+ DIRECT = 7,
+}
diff --git a/media/aidl_api/android.media.audio.common.types/current/android/media/audio/common/AudioIoFlags.aidl b/media/aidl_api/android.media.audio.common.types/current/android/media/audio/common/AudioIoFlags.aidl
new file mode 100644
index 0000000..4a46725
--- /dev/null
+++ b/media/aidl_api/android.media.audio.common.types/current/android/media/audio/common/AudioIoFlags.aidl
@@ -0,0 +1,40 @@
+/*
+ * Copyright (C) 2021 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.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+// the interface (from the latest frozen version), the build system will
+// prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.media.audio.common;
+/* @hide */
+@JavaDerive(equals=true, toString=true) @VintfStability
+union AudioIoFlags {
+ int input;
+ int output;
+}
diff --git a/media/aidl_api/android.media.audio.common.types/current/android/media/audio/common/AudioOutputFlags.aidl b/media/aidl_api/android.media.audio.common.types/current/android/media/audio/common/AudioOutputFlags.aidl
new file mode 100644
index 0000000..ed16d17
--- /dev/null
+++ b/media/aidl_api/android.media.audio.common.types/current/android/media/audio/common/AudioOutputFlags.aidl
@@ -0,0 +1,54 @@
+/*
+ * Copyright (C) 2021 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.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+// the interface (from the latest frozen version), the build system will
+// prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.media.audio.common;
+/* @hide */
+@Backing(type="int") @VintfStability
+enum AudioOutputFlags {
+ DIRECT = 0,
+ PRIMARY = 1,
+ FAST = 2,
+ DEEP_BUFFER = 3,
+ COMPRESS_OFFLOAD = 4,
+ NON_BLOCKING = 5,
+ HW_AV_SYNC = 6,
+ TTS = 7,
+ RAW = 8,
+ SYNC = 9,
+ IEC958_NONAUDIO = 10,
+ DIRECT_PCM = 11,
+ MMAP_NOIRQ = 12,
+ VOIP_RX = 13,
+ INCALL_MUSIC = 14,
+ GAPLESS_OFFLOAD = 15,
+}
diff --git a/media/aidl_api/android.media.audio.common.types/current/android/media/audio/common/AudioPort.aidl b/media/aidl_api/android.media.audio.common.types/current/android/media/audio/common/AudioPort.aidl
index ceb3774..8f563b3 100644
--- a/media/aidl_api/android.media.audio.common.types/current/android/media/audio/common/AudioPort.aidl
+++ b/media/aidl_api/android.media.audio.common.types/current/android/media/audio/common/AudioPort.aidl
@@ -38,6 +38,7 @@
int id;
@utf8InCpp String name;
android.media.audio.common.AudioProfile[] profiles;
+ android.media.audio.common.AudioIoFlags flags;
android.media.audio.common.ExtraAudioDescriptor[] extraAudioDescriptors;
android.media.audio.common.AudioGain[] gains;
android.media.audio.common.AudioPortConfig activeConfig;
diff --git a/media/aidl_api/android.media.audio.common.types/current/android/media/audio/common/AudioPortConfig.aidl b/media/aidl_api/android.media.audio.common.types/current/android/media/audio/common/AudioPortConfig.aidl
index fcc5458..78967b4 100644
--- a/media/aidl_api/android.media.audio.common.types/current/android/media/audio/common/AudioPortConfig.aidl
+++ b/media/aidl_api/android.media.audio.common.types/current/android/media/audio/common/AudioPortConfig.aidl
@@ -40,5 +40,6 @@
@nullable android.media.audio.common.AudioChannelLayout channelMask;
@nullable android.media.audio.common.AudioFormatDescription format;
@nullable android.media.audio.common.AudioGainConfig gain;
+ @nullable android.media.audio.common.AudioIoFlags flags;
android.media.audio.common.AudioPortExt ext;
}
diff --git a/media/aidl_api/android.media.audio.common.types/current/android/media/audio/common/AudioPortDeviceExt.aidl b/media/aidl_api/android.media.audio.common.types/current/android/media/audio/common/AudioPortDeviceExt.aidl
new file mode 100644
index 0000000..2e8124a
--- /dev/null
+++ b/media/aidl_api/android.media.audio.common.types/current/android/media/audio/common/AudioPortDeviceExt.aidl
@@ -0,0 +1,40 @@
+/*
+ * Copyright (C) 2021 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.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+// the interface (from the latest frozen version), the build system will
+// prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.media.audio.common;
+/* @hide */
+@JavaDerive(equals=true, toString=true) @VintfStability
+parcelable AudioPortDeviceExt {
+ android.media.audio.common.AudioDevice device;
+ android.media.audio.common.AudioFormatDescription[] encodedFormats;
+}
diff --git a/media/aidl_api/android.media.audio.common.types/current/android/media/audio/common/AudioPortExt.aidl b/media/aidl_api/android.media.audio.common.types/current/android/media/audio/common/AudioPortExt.aidl
index 241e4e6..af9d9c4 100644
--- a/media/aidl_api/android.media.audio.common.types/current/android/media/audio/common/AudioPortExt.aidl
+++ b/media/aidl_api/android.media.audio.common.types/current/android/media/audio/common/AudioPortExt.aidl
@@ -36,7 +36,7 @@
@JavaDerive(equals=true, toString=true) @VintfStability
union AudioPortExt {
boolean unspecified;
- android.media.audio.common.AudioDevice device;
+ android.media.audio.common.AudioPortDeviceExt device;
android.media.audio.common.AudioPortMixExt mix;
int session;
}
diff --git a/media/aidl_api/android.media.audio.common.types/current/android/media/audio/common/AudioPortMixExt.aidl b/media/aidl_api/android.media.audio.common.types/current/android/media/audio/common/AudioPortMixExt.aidl
index 547396c..5b74c0d 100644
--- a/media/aidl_api/android.media.audio.common.types/current/android/media/audio/common/AudioPortMixExt.aidl
+++ b/media/aidl_api/android.media.audio.common.types/current/android/media/audio/common/AudioPortMixExt.aidl
@@ -37,4 +37,7 @@
parcelable AudioPortMixExt {
int handle;
android.media.audio.common.AudioPortMixExtUseCase usecase;
+ int maxOpenStreamCount;
+ int maxActiveStreamCount;
+ int recommendedMuteDurationMs;
}
diff --git a/media/java/android/media/AudioManager.java b/media/java/android/media/AudioManager.java
index d061bd3..a6c6fe6 100644
--- a/media/java/android/media/AudioManager.java
+++ b/media/java/android/media/AudioManager.java
@@ -96,8 +96,6 @@
private Context mOriginalContext;
private Context mApplicationContext;
private long mVolumeKeyUpTime;
- private boolean mUseFixedVolumeInitialized;
- private boolean mUseFixedVolume;
private static final String TAG = "AudioManager";
private static final boolean DEBUG = false;
private static final AudioPortEventHandler sAudioPortEventHandler = new AudioPortEventHandler();
@@ -893,19 +891,13 @@
* </ul>
*/
public boolean isVolumeFixed() {
- synchronized (this) {
- try {
- if (!mUseFixedVolumeInitialized) {
- mUseFixedVolume = getContext().getResources().getBoolean(
- com.android.internal.R.bool.config_useFixedVolume);
- }
- } catch (Exception e) {
- } finally {
- // only ever try once, so always consider initialized even if query failed
- mUseFixedVolumeInitialized = true;
- }
+ boolean res = false;
+ try {
+ res = getService().isVolumeFixed();
+ } catch (RemoteException e) {
+ Log.e(TAG, "Error querying isVolumeFixed", e);
}
- return mUseFixedVolume;
+ return res;
}
/**
diff --git a/media/java/android/media/IAudioService.aidl b/media/java/android/media/IAudioService.aidl
index 5b05cd3..d736c25 100755
--- a/media/java/android/media/IAudioService.aidl
+++ b/media/java/android/media/IAudioService.aidl
@@ -454,4 +454,6 @@
void registerSpatializerOutputCallback(in ISpatializerOutputCallback cb);
void unregisterSpatializerOutputCallback(in ISpatializerOutputCallback cb);
+
+ boolean isVolumeFixed();
}
diff --git a/media/java/android/media/MediaCodecInfo.java b/media/java/android/media/MediaCodecInfo.java
index 49477b9..374cc75 100644
--- a/media/java/android/media/MediaCodecInfo.java
+++ b/media/java/android/media/MediaCodecInfo.java
@@ -182,10 +182,15 @@
public String mName;
public int mValue;
public boolean mDefault;
+ public boolean mInternal;
public Feature(String name, int value, boolean def) {
+ this(name, value, def, false /* internal */);
+ }
+ public Feature(String name, int value, boolean def, boolean internal) {
mName = name;
mValue = value;
mDefault = def;
+ mInternal = internal;
}
}
@@ -579,6 +584,11 @@
public static final String FEATURE_LowLatency = "low-latency";
/**
+ * Do not include in REGULAR_CODECS list in MediaCodecList.
+ */
+ private static final String FEATURE_SpecialCodec = "special-codec";
+
+ /**
* <b>video encoder only</b>: codec supports quantization parameter bounds.
* @see MediaFormat#KEY_VIDEO_QP_MAX
* @see MediaFormat#KEY_VIDEO_QP_MIN
@@ -616,6 +626,8 @@
new Feature(FEATURE_MultipleFrames, (1 << 5), false),
new Feature(FEATURE_DynamicTimestamp, (1 << 6), false),
new Feature(FEATURE_LowLatency, (1 << 7), true),
+ // feature to exclude codec from REGULAR codec list
+ new Feature(FEATURE_SpecialCodec, (1 << 30), false, true),
};
private static final Feature[] encoderFeatures = {
@@ -623,6 +635,8 @@
new Feature(FEATURE_MultipleFrames, (1 << 1), false),
new Feature(FEATURE_DynamicTimestamp, (1 << 2), false),
new Feature(FEATURE_QpBounds, (1 << 3), false),
+ // feature to exclude codec from REGULAR codec list
+ new Feature(FEATURE_SpecialCodec, (1 << 30), false, true),
};
/** @hide */
@@ -630,7 +644,9 @@
Feature[] features = getValidFeatures();
String[] res = new String[features.length];
for (int i = 0; i < res.length; i++) {
- res[i] = features[i].mName;
+ if (!features[i].mInternal) {
+ res[i] = features[i].mName;
+ }
}
return res;
}
@@ -778,6 +794,10 @@
// check feature support
for (Feature feat: getValidFeatures()) {
+ if (feat.mInternal) {
+ continue;
+ }
+
Integer yesNo = (Integer)map.get(MediaFormat.KEY_FEATURE_ + feat.mName);
if (yesNo == null) {
continue;
@@ -1091,7 +1111,9 @@
mFlagsRequired |= feat.mValue;
}
mFlagsSupported |= feat.mValue;
- mDefaultFormat.setInteger(key, 1);
+ if (!feat.mInternal) {
+ mDefaultFormat.setInteger(key, 1);
+ }
// TODO restrict features by mFlagsVerified once all codecs reliably verify them
}
}
diff --git a/media/java/android/media/MediaFormat.java b/media/java/android/media/MediaFormat.java
index 08a648a..4891d74 100644
--- a/media/java/android/media/MediaFormat.java
+++ b/media/java/android/media/MediaFormat.java
@@ -754,7 +754,7 @@
* <p>This key is only used during decoding.
*/
public static final String KEY_MAX_OUTPUT_CHANNEL_COUNT =
- "max-output-channel_count";
+ "max-output-channel-count";
/**
* A key describing the number of frames to trim from the start of the decoded audio stream.
diff --git a/media/java/android/media/tv/interactive/TvIAppManager.java b/media/java/android/media/tv/interactive/TvIAppManager.java
index 8b8c8c9..f656534 100644
--- a/media/java/android/media/tv/interactive/TvIAppManager.java
+++ b/media/java/android/media/tv/interactive/TvIAppManager.java
@@ -19,6 +19,7 @@
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.annotation.SystemService;
+import android.content.Context;
import android.os.Handler;
import android.os.IBinder;
import android.os.RemoteException;
@@ -30,10 +31,10 @@
/**
* Central system API to the overall TV interactive application framework (TIAF) architecture, which
* arbitrates interaction between applications and interactive apps.
- * @hide
*/
-@SystemService("tv_interactive_app")
+@SystemService(Context.TV_IAPP_SERVICE)
public final class TvIAppManager {
+ // TODO: cleanup and unhide public APIs
private static final String TAG = "TvIAppManager";
private final ITvIAppManager mService;
@@ -49,6 +50,7 @@
private final ITvIAppClient mClient;
+ /** @hide */
public TvIAppManager(ITvIAppManager service, int userId) {
mService = service;
mUserId = userId;
@@ -125,6 +127,7 @@
/**
* The Session provides the per-session functionality of interactive app.
+ * @hide
*/
public static final class Session {
private final ITvIAppManager mService;
diff --git a/media/java/android/media/tv/tuner/Tuner.java b/media/java/android/media/tv/tuner/Tuner.java
index 9dc4949..c484309 100644
--- a/media/java/android/media/tv/tuner/Tuner.java
+++ b/media/java/android/media/tv/tuner/Tuner.java
@@ -25,6 +25,7 @@
import android.annotation.SuppressLint;
import android.annotation.SystemApi;
import android.content.Context;
+import android.content.pm.PackageManager;
import android.hardware.tv.tuner.Constant;
import android.hardware.tv.tuner.Constant64Bit;
import android.hardware.tv.tuner.FrontendScanType;
@@ -37,6 +38,8 @@
import android.media.tv.tuner.filter.Filter.Subtype;
import android.media.tv.tuner.filter.Filter.Type;
import android.media.tv.tuner.filter.FilterCallback;
+import android.media.tv.tuner.filter.SharedFilter;
+import android.media.tv.tuner.filter.SharedFilterCallback;
import android.media.tv.tuner.filter.TimeFilter;
import android.media.tv.tuner.frontend.Atsc3PlpInfo;
import android.media.tv.tuner.frontend.FrontendInfo;
@@ -445,6 +448,7 @@
* and the API would only process nice value setting in that case.
* @param niceValue the nice value.
*/
+ @RequiresPermission(android.Manifest.permission.TUNER_RESOURCE_ACCESS)
public void updateResourcePriority(int priority, int niceValue) {
mTunerResourceManager.updateClientPriority(mClientId, priority, niceValue);
}
@@ -455,6 +459,7 @@
* @param frontendType {@link android.media.tv.tuner.frontend.FrontendSettings.Type} for the
* query to be done for.
*/
+ @RequiresPermission(android.Manifest.permission.TUNER_RESOURCE_ACCESS)
public boolean hasUnusedFrontend(int frontendType) {
return mTunerResourceManager.hasUnusedFrontend(frontendType);
}
@@ -620,6 +625,7 @@
private native int nativeCloseFrontend(int handle);
private native int nativeClose();
+ private static native SharedFilter nativeOpenSharedFilter(String token);
/**
* Listener for resource lost.
@@ -751,8 +757,13 @@
*/
@Result
public int tune(@NonNull FrontendSettings settings) {
- Log.d(TAG, "Tune to " + settings.getFrequency());
- mFrontendType = settings.getType();
+ final int type = settings.getType();
+ if (mFrontendHandle != null && type != mFrontendType) {
+ Log.e(TAG, "Frontend was opened with type " + mFrontendType + ", new type is " + type);
+ return RESULT_INVALID_STATE;
+ }
+ Log.d(TAG, "Tune to " + settings.getFrequencyLong());
+ mFrontendType = type;
if (mFrontendType == FrontendSettings.TYPE_DTMB) {
if (!TunerVersionChecker.checkHigherOrEqualVersionTo(
TunerVersionChecker.TUNER_VERSION_1_1, "Tuner with DTMB Frontend")) {
@@ -1565,6 +1576,37 @@
return dvr;
}
+ /**
+ * Open a shared filter instance.
+ *
+ * @param context the context of the caller.
+ * @param sharedFilterToken the token of the shared filter being opened.
+ * @param executor the executor on which callback will be invoked.
+ * @param cb the listener to receive notifications from shared filter.
+ * @return the opened shared filter object. {@code null} if the operation failed.
+ */
+ @RequiresPermission(android.Manifest.permission.ACCESS_TV_SHARED_FILTER)
+ @Nullable
+ static public SharedFilter openSharedFilter(@NonNull Context context,
+ @NonNull String sharedFilterToken, @CallbackExecutor @NonNull Executor executor,
+ @NonNull SharedFilterCallback cb) {
+ Objects.requireNonNull(sharedFilterToken, "sharedFilterToken must not be null");
+ Objects.requireNonNull(executor, "executor must not be null");
+ Objects.requireNonNull(cb, "SharedFilterCallback must not be null");
+
+ if (context.checkCallingOrSelfPermission(
+ android.Manifest.permission.ACCESS_TV_SHARED_FILTER)
+ != PackageManager.PERMISSION_GRANTED) {
+ throw new SecurityException("Caller must have ACCESS_TV_SHAREDFILTER permission.");
+ }
+
+ SharedFilter filter = nativeOpenSharedFilter(sharedFilterToken);
+ if (filter != null) {
+ filter.setCallback(cb, executor);
+ }
+ return filter;
+ }
+
private boolean requestDemux() {
int[] demuxHandle = new int[1];
TunerDemuxRequest request = new TunerDemuxRequest();
diff --git a/media/java/android/media/tv/tuner/TunerUtils.java b/media/java/android/media/tv/tuner/TunerUtils.java
index 3a15daf..5541508 100644
--- a/media/java/android/media/tv/tuner/TunerUtils.java
+++ b/media/java/android/media/tv/tuner/TunerUtils.java
@@ -172,5 +172,16 @@
}
}
+ /**
+ * Checks the accessibility of a resource instance.
+ *
+ * @throws IllegalStateException if the resource has already been inaccessible.
+ */
+ public static void checkResourceAccessible(String name, boolean accessible) {
+ if (!accessible) {
+ throw new IllegalStateException(name + " is inaccessible");
+ }
+ }
+
private TunerUtils() {}
}
diff --git a/media/java/android/media/tv/tuner/filter/Filter.java b/media/java/android/media/tv/tuner/filter/Filter.java
index bd860d9..ae271120 100644
--- a/media/java/android/media/tv/tuner/filter/Filter.java
+++ b/media/java/android/media/tv/tuner/filter/Filter.java
@@ -28,6 +28,7 @@
import android.media.tv.tuner.Tuner.Result;
import android.media.tv.tuner.TunerUtils;
import android.media.tv.tuner.TunerVersionChecker;
+import android.util.Log;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
@@ -235,6 +236,8 @@
private Filter mSource;
private boolean mStarted;
private boolean mIsClosed = false;
+ private boolean mIsStarted = false;
+ private boolean mIsShared = false;
private final Object mLock = new Object();
private native int nativeConfigureFilter(
@@ -248,6 +251,8 @@
private native int nativeFlushFilter();
private native int nativeRead(byte[] buffer, long offset, long size);
private native int nativeClose();
+ private native String nativeCreateSharedFilter();
+ private native void nativeReleaseSharedFilter(String token);
// Called by JNI
private Filter(long id) {
@@ -312,6 +317,8 @@
* coming events until it receives {@link RestartEvent} through {@link FilterCallback} to avoid
* using the events from the previous configuration.
*
+ * <p>If this filter is shared, do nothing and just return {@link Tuner#RESULT_INVALID_STATE}.
+ *
* @param config the configuration of the filter.
* @return result status of the operation.
*/
@@ -319,6 +326,9 @@
public int configure(@NonNull FilterConfiguration config) {
synchronized (mLock) {
TunerUtils.checkResourceState(TAG, mIsClosed);
+ if (mIsShared) {
+ return Tuner.RESULT_INVALID_STATE;
+ }
Settings s = config.getSettings();
int subType = (s == null) ? mSubtype : s.getType();
if (mMainType != config.getType() || mSubtype != subType) {
@@ -374,6 +384,8 @@
* will cause no-op. Use {@link TunerVersionChecker#getTunerVersion()} to get the version
* information.
*
+ * <p>If this filter is shared, do nothing and just return {@link Tuner#RESULT_INVALID_STATE}.
+ *
* @param monitorEventMask Types of event to be monitored. Set corresponding bit to
* monitor it. Reset to stop monitoring.
* @return result status of the operation.
@@ -382,6 +394,9 @@
public int setMonitorEventMask(@MonitorEventMask int monitorEventMask) {
synchronized (mLock) {
TunerUtils.checkResourceState(TAG, mIsClosed);
+ if (mIsShared) {
+ return Tuner.RESULT_INVALID_STATE;
+ }
if (!TunerVersionChecker.checkHigherOrEqualVersionTo(
TunerVersionChecker.TUNER_VERSION_1_1, "setMonitorEventMask")) {
return Tuner.RESULT_UNAVAILABLE;
@@ -398,6 +413,8 @@
* extract all protocols' header. Then a filter's data source can be output
* from another filter.
*
+ * <p>If this filter is shared, do nothing and just return {@link Tuner#RESULT_INVALID_STATE}.
+ *
* @param source the filter instance which provides data input. Switch to
* use demux as data source if the filter instance is NULL.
* @return result status of the operation.
@@ -407,6 +424,9 @@
public int setDataSource(@Nullable Filter source) {
synchronized (mLock) {
TunerUtils.checkResourceState(TAG, mIsClosed);
+ if (mIsShared) {
+ return Tuner.RESULT_INVALID_STATE;
+ }
if (mSource != null) {
throw new IllegalStateException("Data source is existing");
}
@@ -427,17 +447,25 @@
* coming events until it receives {@link RestartEvent} through {@link FilterCallback} to avoid
* using the events from the previous configuration.
*
+ * <p>If this filter is shared, do nothing and just return {@link Tuner#RESULT_INVALID_STATE}.
+ *
* @return result status of the operation.
*/
@Result
public int start() {
synchronized (mLock) {
TunerUtils.checkResourceState(TAG, mIsClosed);
- return nativeStartFilter();
+ if (mIsShared) {
+ return Tuner.RESULT_INVALID_STATE;
+ }
+ int res = nativeStartFilter();
+ if (res == Tuner.RESULT_SUCCESS) {
+ mIsStarted = true;
+ }
+ return res;
}
}
-
/**
* Stops filtering data.
*
@@ -449,13 +477,22 @@
* coming events until it receives {@link RestartEvent} through {@link FilterCallback} to avoid
* using the events from the previous configuration.
*
+ * <p>If this filter is shared, do nothing and just return {@link Tuner#RESULT_INVALID_STATE}.
+ *
* @return result status of the operation.
*/
@Result
public int stop() {
synchronized (mLock) {
TunerUtils.checkResourceState(TAG, mIsClosed);
- return nativeStopFilter();
+ if (mIsShared) {
+ return Tuner.RESULT_INVALID_STATE;
+ }
+ int res = nativeStopFilter();
+ if (res == Tuner.RESULT_SUCCESS) {
+ mIsStarted = false;
+ }
+ return res;
}
}
@@ -465,12 +502,17 @@
* <p>The data which is already produced by filter but not consumed yet will
* be cleared.
*
+ * <p>If this filter is shared, do nothing and just return {@link Tuner#RESULT_INVALID_STATE}.
+ *
* @return result status of the operation.
*/
@Result
public int flush() {
synchronized (mLock) {
TunerUtils.checkResourceState(TAG, mIsClosed);
+ if (mIsShared) {
+ return Tuner.RESULT_INVALID_STATE;
+ }
return nativeFlushFilter();
}
}
@@ -478,6 +520,8 @@
/**
* Copies filtered data from filter output to the given byte array.
*
+ * <p>If this filter is shared, do nothing and just return {@link Tuner#RESULT_INVALID_STATE}.
+ *
* @param buffer the buffer to store the filtered data.
* @param offset the index of the first byte in {@code buffer} to write.
* @param size the maximum number of bytes to read.
@@ -486,6 +530,9 @@
public int read(@NonNull byte[] buffer, @BytesLong long offset, @BytesLong long size) {
synchronized (mLock) {
TunerUtils.checkResourceState(TAG, mIsClosed);
+ if (mIsShared) {
+ return 0;
+ }
size = Math.min(size, buffer.length - offset);
return nativeRead(buffer, offset, size);
}
@@ -493,6 +540,10 @@
/**
* Stops filtering data and releases the Filter instance.
+ *
+ * <p>If this filter is shared, this filter will be closed and a
+ * {@link SharedFilterCallback#STATUS_INACCESSIBLE} event will be sent to shared filter before
+ * closing.
*/
@Override
public void close() {
@@ -504,8 +555,47 @@
if (res != Tuner.RESULT_SUCCESS) {
TunerUtils.throwExceptionForResult(res, "Failed to close filter.");
} else {
+ mIsStarted = false;
mIsClosed = true;
}
}
}
+
+ /**
+ * Creates a shared filter.
+ *
+ * @return a string shared filter token.
+ */
+ @Nullable
+ public String createSharedFilter() {
+ synchronized (mLock) {
+ TunerUtils.checkResourceState(TAG, mIsClosed);
+ if (mIsStarted || mIsShared) {
+ Log.d(TAG, "Create shared filter in a wrong state, started: " +
+ mIsStarted + "shared: " + mIsShared);
+ return null;
+ }
+ String token = nativeCreateSharedFilter();
+ if (token != null) {
+ mIsShared = true;
+ }
+ return token;
+ }
+ }
+
+ /**
+ * Releases a shared filter.
+ *
+ * @param filterToken the token of the shared filter being released.
+ */
+ public void releaseSharedFilter(@NonNull String filterToken) {
+ synchronized (mLock) {
+ TunerUtils.checkResourceState(TAG, mIsClosed);
+ if (!mIsShared) {
+ return;
+ }
+ nativeReleaseSharedFilter(filterToken);
+ mIsShared = false;
+ }
+ }
}
diff --git a/media/java/android/media/tv/tuner/filter/SharedFilter.java b/media/java/android/media/tv/tuner/filter/SharedFilter.java
new file mode 100644
index 0000000..f86ad11
--- /dev/null
+++ b/media/java/android/media/tv/tuner/filter/SharedFilter.java
@@ -0,0 +1,194 @@
+/*
+ * Copyright 2021 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.media.tv.tuner.filter;
+
+import android.annotation.BytesLong;
+import android.annotation.IntDef;
+import android.annotation.NonNull;
+import android.annotation.Nullable;
+import android.annotation.SystemApi;
+import android.media.tv.tuner.Tuner;
+import android.media.tv.tuner.Tuner.Result;
+import android.media.tv.tuner.TunerUtils;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.util.concurrent.Executor;
+
+/**
+ * Tuner shared data filter.
+ *
+ * <p>This class is used to filter wanted data in a different process.
+ *
+ * @hide
+ */
+@SystemApi
+public final class SharedFilter implements AutoCloseable {
+ /** @hide */
+ @IntDef(flag = true, prefix = "STATUS_", value = {STATUS_INACCESSIBLE})
+ @Retention(RetentionPolicy.SOURCE)
+ public @interface Status {}
+
+ /**
+ * The status of a shared filter that its data becomes inaccessible.
+ */
+ public static final int STATUS_INACCESSIBLE = 1 << 7;
+
+ private static final String TAG = "SharedFilter";
+
+ private long mNativeContext;
+ private SharedFilterCallback mCallback;
+ private Executor mExecutor;
+ private final Object mCallbackLock = new Object();
+ private boolean mIsClosed = false;
+ private boolean mIsAccessible = true;
+ private final Object mLock = new Object();
+
+ private native int nativeStartSharedFilter();
+ private native int nativeStopSharedFilter();
+ private native int nativeFlushSharedFilter();
+ private native int nativeSharedRead(byte[] buffer, long offset, long size);
+ private native int nativeSharedClose();
+
+ // Called by JNI
+ private SharedFilter() {}
+
+ private void onFilterStatus(int status) {
+ synchronized (mLock) {
+ if (status == STATUS_INACCESSIBLE) {
+ mIsAccessible = false;
+ }
+ }
+ synchronized (mCallbackLock) {
+ if (mCallback != null && mExecutor != null) {
+ mExecutor.execute(() -> {
+ synchronized (mCallbackLock) {
+ if (mCallback != null) {
+ mCallback.onFilterStatusChanged(this, status);
+ }
+ }
+ });
+ }
+ }
+ }
+
+ private void onFilterEvent(FilterEvent[] events) {
+ synchronized (mCallbackLock) {
+ if (mCallback != null && mExecutor != null) {
+ mExecutor.execute(() -> {
+ synchronized (mCallbackLock) {
+ if (mCallback != null) {
+ mCallback.onFilterEvent(this, events);
+ }
+ }
+ });
+ }
+ }
+ }
+
+ /** @hide */
+ public void setCallback(SharedFilterCallback cb, Executor executor) {
+ synchronized (mCallbackLock) {
+ mCallback = cb;
+ mExecutor = executor;
+ }
+ }
+
+ /** @hide */
+ public SharedFilterCallback getCallback() {
+ synchronized (mCallbackLock) { return mCallback; }
+ }
+
+ /**
+ * Starts filtering data.
+ *
+ * <p>Does nothing if the filter is already started.
+ *
+ * @return result status of the operation.
+ */
+ @Result
+ public int start() {
+ synchronized (mLock) {
+ TunerUtils.checkResourceAccessible(TAG, mIsAccessible);
+ TunerUtils.checkResourceState(TAG, mIsClosed);
+ return nativeStartSharedFilter();
+ }
+ }
+
+ /**
+ * Stops filtering data.
+ *
+ * <p>Does nothing if the filter is stopped or not started.
+ *
+ * @return result status of the operation.
+ */
+ @Result
+ public int stop() {
+ synchronized (mLock) {
+ TunerUtils.checkResourceAccessible(TAG, mIsAccessible);
+ TunerUtils.checkResourceState(TAG, mIsClosed);
+ return nativeStopSharedFilter();
+ }
+ }
+
+ /**
+ * Flushes the filter.
+ *
+ * <p>The data which is already produced by filter but not consumed yet will
+ * be cleared.
+ *
+ * @return result status of the operation.
+ */
+ @Result
+ public int flush() {
+ synchronized (mLock) {
+ TunerUtils.checkResourceAccessible(TAG, mIsAccessible);
+ TunerUtils.checkResourceState(TAG, mIsClosed);
+ return nativeFlushSharedFilter();
+ }
+ }
+
+ /**
+ * Copies filtered data from filter output to the given byte array.
+ *
+ * @param buffer the buffer to store the filtered data.
+ * @param offset the index of the first byte in {@code buffer} to write.
+ * @param size the maximum number of bytes to read.
+ * @return the number of bytes read.
+ */
+ public int read(@NonNull byte[] buffer, @BytesLong long offset, @BytesLong long size) {
+ synchronized (mLock) {
+ TunerUtils.checkResourceAccessible(TAG, mIsAccessible);
+ TunerUtils.checkResourceState(TAG, mIsClosed);
+ size = Math.min(size, buffer.length - offset);
+ return nativeSharedRead(buffer, offset, size);
+ }
+ }
+
+ /**
+ * Stops filtering data and releases the Filter instance.
+ */
+ @Override
+ public void close() {
+ synchronized (mLock) {
+ if (mIsClosed) {
+ return;
+ }
+ nativeSharedClose();
+ mIsClosed = true;
+ }
+ }
+}
diff --git a/media/java/android/media/tv/tuner/filter/SharedFilterCallback.java b/media/java/android/media/tv/tuner/filter/SharedFilterCallback.java
new file mode 100644
index 0000000..86a4c1a
--- /dev/null
+++ b/media/java/android/media/tv/tuner/filter/SharedFilterCallback.java
@@ -0,0 +1,45 @@
+/*
+ * Copyright 2021 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.media.tv.tuner.filter;
+
+import android.annotation.NonNull;
+import android.annotation.SuppressLint;
+import android.annotation.SystemApi;
+
+/**
+ * Callback interface for receiving information from the corresponding shared filters.
+ *
+ * @hide
+ */
+@SystemApi
+public interface SharedFilterCallback {
+ /**
+ * Invoked when there are filter events.
+ *
+ * @param sharedfilter the corresponding shared filter which sent the events.
+ * @param events the filter events sent from the filter.
+ */
+ void onFilterEvent(@NonNull SharedFilter sharedfilter,
+ @SuppressLint("ArrayReturn") @NonNull FilterEvent[] events);
+ /**
+ * Invoked when filter status changed.
+ *
+ * @param sharedfilter the corresponding shared filter whose status is changed.
+ * @param status the new status of the filter.
+ */
+ void onFilterStatusChanged(@NonNull SharedFilter sharedfilter, @Filter.Status int status);
+}
diff --git a/media/java/android/media/tv/tuner/frontend/DtmbFrontendSettings.java b/media/java/android/media/tv/tuner/frontend/DtmbFrontendSettings.java
index 91102d4..6b5d6ca 100644
--- a/media/java/android/media/tv/tuner/frontend/DtmbFrontendSettings.java
+++ b/media/java/android/media/tv/tuner/frontend/DtmbFrontendSettings.java
@@ -269,7 +269,7 @@
/**
* Gets Code Rate.
*/
- @Modulation
+ @CodeRate
public int getCodeRate() {
return mCodeRate;
}
@@ -277,7 +277,7 @@
/**
* Gets Transmission Mode.
*/
- @Modulation
+ @TransmissionMode
public int getTransmissionMode() {
return mTransmissionMode;
}
@@ -285,7 +285,7 @@
/**
* Gets Bandwidth.
*/
- @Modulation
+ @Bandwidth
public int getBandwidth() {
return mBandwidth;
}
@@ -293,16 +293,15 @@
/**
* Gets Time Interleave Mode.
*/
- @Modulation
+ @TimeInterleaveMode
public int getTimeInterleaveMode() {
return mTimeInterleaveMode;
}
-
/**
* Gets Guard Interval.
*/
- @Modulation
+ @GuardInterval
public int getGuardInterval() {
return mGuardInterval;
}
diff --git a/media/jni/android_media_tv_Tuner.cpp b/media/jni/android_media_tv_Tuner.cpp
index 4bee485..35f18751 100644
--- a/media/jni/android_media_tv_Tuner.cpp
+++ b/media/jni/android_media_tv_Tuner.cpp
@@ -298,6 +298,7 @@
jfieldID dvrRecorderContext;
jfieldID dvrPlaybackContext;
jfieldID mediaEventContext;
+ jfieldID sharedFilterContext;
jmethodID frontendInitID;
jmethodID filterInitID;
jmethodID timeFilterInitID;
@@ -314,6 +315,9 @@
jmethodID descramblerInitID;
jmethodID linearBlockInitID;
jmethodID linearBlockSetInternalStateID;
+ jmethodID sharedFilterInitID;
+ jmethodID onSharedFilterStatusID;
+ jmethodID onSharedFilterEventID;
};
static fields_t gFields;
@@ -884,10 +888,11 @@
}
jobject filter(env->NewLocalRef(mFilterObj));
if (!env->IsSameObject(filter, nullptr)) {
- env->CallVoidMethod(
- filter,
- gFields.onFilterEventID,
- array);
+ jmethodID methodID = gFields.onFilterEventID;
+ if (mSharedFilter) {
+ methodID = gFields.onSharedFilterEventID;
+ }
+ env->CallVoidMethod(filter, methodID, array);
} else {
ALOGE("FilterClientCallbackImpl::onFilterEvent:"
"Filter object has been freed. Ignoring callback.");
@@ -899,13 +904,14 @@
JNIEnv *env = AndroidRuntime::getJNIEnv();
jobject filter(env->NewLocalRef(mFilterObj));
if (!env->IsSameObject(filter, nullptr)) {
- env->CallVoidMethod(
- filter,
- gFields.onFilterStatusID,
- (jint)status);
+ jmethodID methodID = gFields.onFilterStatusID;
+ if (mSharedFilter) {
+ methodID = gFields.onSharedFilterStatusID;
+ }
+ env->CallVoidMethod(filter, methodID, (jint)static_cast<uint8_t>(status));
} else {
ALOGE("FilterClientCallbackImpl::onFilterStatus:"
- "Filter object has been freed. Ignoring callback.");
+ "Filter object has been freed. Ignoring callback.");
}
}
@@ -914,6 +920,15 @@
// Java Object
mFilterObj = filterObj;
mFilterClient = filterClient;
+ mSharedFilter = false;
+}
+
+void FilterClientCallbackImpl::setSharedFilter(jweak filterObj, sp<FilterClient> filterClient) {
+ ALOGV("FilterClientCallbackImpl::setFilter");
+ // Java Object
+ mFilterObj = filterObj;
+ mFilterClient = filterClient;
+ mSharedFilter = true;
}
FilterClientCallbackImpl::~FilterClientCallbackImpl() {
@@ -2974,6 +2989,10 @@
return (FilterClient *)env->GetLongField(filter, gFields.filterContext);
}
+static sp<FilterClient> getSharedFilterClient(JNIEnv *env, jobject filter) {
+ return (FilterClient *)env->GetLongField(filter, gFields.sharedFilterContext);
+}
+
static sp<LnbClient> getLnbClient(JNIEnv *env, jobject lnb) {
return (LnbClient *)env->GetLongField(lnb, gFields.lnbContext);
}
@@ -3049,6 +3068,14 @@
env->GetMethodID(filterClazz, "onFilterEvent",
"([Landroid/media/tv/tuner/filter/FilterEvent;)V");
+ jclass sharedFilterClazz = env->FindClass("android/media/tv/tuner/filter/SharedFilter");
+ gFields.sharedFilterContext = env->GetFieldID(filterClazz, "mNativeContext", "J");
+ gFields.sharedFilterInitID = env->GetMethodID(sharedFilterClazz, "<init>", "()V");
+ gFields.onSharedFilterStatusID = env->GetMethodID(sharedFilterClazz, "onFilterStatus", "(I)V");
+ gFields.onSharedFilterEventID =
+ env->GetMethodID(sharedFilterClazz, "onFilterEvent",
+ "([Landroid/media/tv/tuner/filter/FilterEvent;)V");
+
jclass timeFilterClazz = env->FindClass("android/media/tv/tuner/filter/TimeFilter");
gFields.timeFilterContext = env->GetFieldID(timeFilterClazz, "mNativeContext", "J");
gFields.timeFilterInitID = env->GetMethodID(timeFilterClazz, "<init>", "()V");
@@ -3718,7 +3745,12 @@
}
static jint android_media_tv_Tuner_start_filter(JNIEnv *env, jobject filter) {
- sp<FilterClient> filterClient = getFilterClient(env, filter);
+ sp<FilterClient> filterClient = nullptr;
+ if (env->IsInstanceOf(filter, env->FindClass("android/media/tv/tuner/filter/SharedFilter"))) {
+ filterClient = getSharedFilterClient(env, filter);
+ } else {
+ filterClient = getFilterClient(env, filter);
+ }
if (filterClient == nullptr) {
ALOGD("Failed to start filter: filter client not found");
return (int)Result::NOT_INITIALIZED;
@@ -3727,7 +3759,12 @@
}
static jint android_media_tv_Tuner_stop_filter(JNIEnv *env, jobject filter) {
- sp<FilterClient> filterClient = getFilterClient(env, filter);
+ sp<FilterClient> filterClient = nullptr;
+ if (env->IsInstanceOf(filter, env->FindClass("android/media/tv/tuner/filter/SharedFilter"))) {
+ filterClient = getSharedFilterClient(env, filter);
+ } else {
+ filterClient = getFilterClient(env, filter);
+ }
if (filterClient == nullptr) {
ALOGD("Failed to stop filter: filter client not found");
return (int)Result::NOT_INITIALIZED;
@@ -3736,17 +3773,27 @@
}
static jint android_media_tv_Tuner_flush_filter(JNIEnv *env, jobject filter) {
- sp<FilterClient> filterClient = getFilterClient(env, filter);
+ sp<FilterClient> filterClient = nullptr;
+ if (env->IsInstanceOf(filter, env->FindClass("android/media/tv/tuner/filter/SharedFilter"))) {
+ filterClient = getSharedFilterClient(env, filter);
+ } else {
+ filterClient = getFilterClient(env, filter);
+ }
if (filterClient == nullptr) {
ALOGD("Failed to flush filter: filter client not found");
- return (int)Result::NOT_INITIALIZED;
+ return (jint)Result::NOT_INITIALIZED;
}
return (jint)filterClient->flush();
}
static jint android_media_tv_Tuner_read_filter_fmq(
JNIEnv *env, jobject filter, jbyteArray buffer, jlong offset, jlong size) {
- sp<FilterClient> filterClient = getFilterClient(env, filter);
+ sp<FilterClient> filterClient = nullptr;
+ if (env->IsInstanceOf(filter, env->FindClass("android/media/tv/tuner/filter/SharedFilter"))) {
+ filterClient = getSharedFilterClient(env, filter);
+ } else {
+ filterClient = getFilterClient(env, filter);
+ }
if (filterClient == nullptr) {
jniThrowException(env, "java/lang/IllegalStateException",
"Failed to read filter FMQ: filter client not found");
@@ -3766,14 +3813,57 @@
}
static jint android_media_tv_Tuner_close_filter(JNIEnv *env, jobject filter) {
- sp<FilterClient> filterClient = getFilterClient(env, filter);
+ sp<FilterClient> filterClient = nullptr;
+ bool shared = env->IsInstanceOf(
+ filter, env->FindClass("android/media/tv/tuner/filter/SharedFilter"));
+ if (shared) {
+ filterClient = getSharedFilterClient(env, filter);
+ } else {
+ filterClient = getFilterClient(env, filter);
+ }
if (filterClient == nullptr) {
jniThrowException(env, "java/lang/IllegalStateException",
"Failed to close filter: filter client not found");
return 0;
}
- return (jint)filterClient->close();
+ Result r = filterClient->close();
+ filterClient->decStrong(filter);
+ env->SetLongField(filter, gFields.sharedFilterContext, 0);
+ if (shared) {
+ } else {
+ env->SetLongField(filter, gFields.filterContext, 0);
+ }
+
+ return (jint)r;
+}
+
+static jstring android_media_tv_Tuner_create_shared_filter(JNIEnv *env, jobject filter) {
+ sp<FilterClient> filterClient = getFilterClient(env, filter);
+ if (filterClient == nullptr) {
+ jniThrowException(env, "java/lang/IllegalStateException",
+ "Failed to create shared filter: filter client not found");
+ return nullptr;
+ }
+
+ string token = filterClient->createSharedFilter();
+ if (token.empty()) {
+ return nullptr;
+ }
+ return env->NewStringUTF(token.data());
+}
+
+static void android_media_tv_Tuner_release_shared_filter(
+ JNIEnv *env, jobject filter, jstring token) {
+ sp<FilterClient> filterClient = getFilterClient(env, filter);
+ if (filterClient == nullptr) {
+ jniThrowException(env, "java/lang/IllegalStateException",
+ "Failed to release shared filter: filter client not found");
+ return;
+ }
+
+ std::string filterToken(env->GetStringUTFChars(token, nullptr));
+ filterClient->releaseSharedFilter(filterToken);
}
static sp<TimeFilterClient> getTimeFilterClient(JNIEnv *env, jobject filter) {
@@ -3843,10 +3933,8 @@
}
Result r = timeFilterClient->close();
- if (r == Result::SUCCESS) {
- timeFilterClient->decStrong(filter);
- env->SetLongField(filter, gFields.timeFilterContext, 0);
- }
+ timeFilterClient->decStrong(filter);
+ env->SetLongField(filter, gFields.timeFilterContext, 0);
return (int)r;
}
@@ -3896,9 +3984,8 @@
return (jint)Result::NOT_INITIALIZED;
}
Result r = descramblerClient->close();
- if (r == Result::SUCCESS) {
- descramblerClient->decStrong(descrambler);
- }
+ descramblerClient->decStrong(descrambler);
+ env->SetLongField(descrambler, gFields.descramblerContext, 0);
return (jint)r;
}
@@ -3935,6 +4022,29 @@
return tuner->closeDemux();
}
+static jobject android_media_tv_Tuner_open_shared_filter(
+ JNIEnv* env, jobject /* thiz */, jstring token) {
+
+ sp<TunerClient> tunerClient = new TunerClient();
+ std::string filterToken(env->GetStringUTFChars(token, nullptr));
+ sp<FilterClient> filterClient;
+ sp<FilterClientCallbackImpl> callback = new FilterClientCallbackImpl();
+ filterClient = tunerClient->openSharedFilter(filterToken, callback);
+ if (filterClient == nullptr) {
+ ALOGD("Failed to open shared filter %s", filterToken.c_str());
+ return nullptr;
+ }
+
+ jobject filterObj = env->NewObject(env->FindClass("android/media/tv/tuner/filter/SharedFilter"),
+ gFields.sharedFilterInitID);
+
+ filterClient->incStrong(filterObj);
+ env->SetLongField(filterObj, gFields.sharedFilterContext, (jlong)filterClient.get());
+ callback->setSharedFilter(env->NewWeakGlobalRef(filterObj), filterClient);
+
+ return filterObj;
+}
+
static jint android_media_tv_Tuner_close_frontend(JNIEnv* env, jobject thiz, jint /* handle */) {
sp<JTuner> tuner = getTuner(env, thiz);
return tuner->closeFrontend();
@@ -4014,7 +4124,14 @@
ALOGD("Failed to close dvr: dvr client not found");
return (jint)Result::NOT_INITIALIZED;
}
- return (jint)dvrClient->close();
+ Result r = dvrClient->close();
+ bool isRecorder =
+ env->IsInstanceOf(dvr, env->FindClass("android/media/tv/tuner/dvr/DvrRecorder"));
+ jfieldID fieldId =
+ isRecorder ? gFields.dvrRecorderContext : gFields.dvrPlaybackContext;
+ dvrClient->decStrong(dvr);
+ env->SetLongField(dvr, fieldId, 0);
+ return (jint)r;
}
static jint android_media_tv_Tuner_lnb_set_voltage(JNIEnv* env, jobject lnb, jint voltage) {
@@ -4043,10 +4160,8 @@
static int android_media_tv_Tuner_close_lnb(JNIEnv* env, jobject lnb) {
sp<LnbClient> lnbClient = getLnbClient(env, lnb);
Result r = lnbClient->close();
- if (r == Result::SUCCESS) {
- lnbClient->decStrong(lnb);
- env->SetLongField(lnb, gFields.lnbContext, 0);
- }
+ lnbClient->decStrong(lnb);
+ env->SetLongField(lnb, gFields.lnbContext, 0);
return (jint)r;
}
@@ -4221,6 +4336,9 @@
{ "nativeClose", "()I", (void *)android_media_tv_Tuner_close_tuner },
{ "nativeCloseFrontend", "(I)I", (void *)android_media_tv_Tuner_close_frontend },
{ "nativeCloseDemux", "(I)I", (void *)android_media_tv_Tuner_close_demux },
+ {"nativeOpenSharedFilter",
+ "(Ljava/lang/String;)Landroid/media/tv/tuner/filter/SharedFilter;",
+ (void *)android_media_tv_Tuner_open_shared_filter},
};
static const JNINativeMethod gFilterMethods[] = {
@@ -4238,6 +4356,18 @@
{ "nativeFlushFilter", "()I", (void *)android_media_tv_Tuner_flush_filter },
{ "nativeRead", "([BJJ)I", (void *)android_media_tv_Tuner_read_filter_fmq },
{ "nativeClose", "()I", (void *)android_media_tv_Tuner_close_filter },
+ {"nativeCreateSharedFilter", "()Ljava/lang/String;",
+ (void *)android_media_tv_Tuner_create_shared_filter},
+ {"nativeReleaseSharedFilter", "(Ljava/lang/String;)V",
+ (void *)android_media_tv_Tuner_release_shared_filter},
+};
+
+static const JNINativeMethod gSharedFilterMethods[] = {
+ {"nativeStartSharedFilter", "()I", (void *)android_media_tv_Tuner_start_filter},
+ {"nativeStopSharedFilter", "()I", (void *)android_media_tv_Tuner_stop_filter},
+ {"nativeFlushSharedFilter", "()I", (void *)android_media_tv_Tuner_flush_filter},
+ {"nativeSharedRead", "([BJJ)I", (void *)android_media_tv_Tuner_read_filter_fmq},
+ {"nativeSharedClose", "()I", (void *)android_media_tv_Tuner_close_filter},
};
static const JNINativeMethod gTimeFilterMethods[] = {
@@ -4322,6 +4452,13 @@
return false;
}
if (AndroidRuntime::registerNativeMethods(
+ env, "android/media/tv/tuner/filter/SharedFilter",
+ gSharedFilterMethods,
+ NELEM(gSharedFilterMethods)) != JNI_OK) {
+ ALOGE("Failed to register shared filter native methods");
+ return false;
+ }
+ if (AndroidRuntime::registerNativeMethods(
env, "android/media/tv/tuner/filter/TimeFilter",
gTimeFilterMethods,
NELEM(gTimeFilterMethods)) != JNI_OK) {
diff --git a/media/jni/android_media_tv_Tuner.h b/media/jni/android_media_tv_Tuner.h
index 5401ddd..31d24ee 100644
--- a/media/jni/android_media_tv_Tuner.h
+++ b/media/jni/android_media_tv_Tuner.h
@@ -130,9 +130,12 @@
virtual void onFilterStatus(const DemuxFilterStatus status);
void setFilter(jweak filterObj, sp<FilterClient> filterClient);
+ void setSharedFilter(jweak filterObj, sp<FilterClient> filterClient);
+
private:
jweak mFilterObj;
sp<FilterClient> mFilterClient;
+ bool mSharedFilter;
void getSectionEvent(jobjectArray& arr, const int size, const DemuxFilterEvent& event);
void getMediaEvent(jobjectArray& arr, const int size, const DemuxFilterEvent& event);
void getPesEvent(jobjectArray& arr, const int size, const DemuxFilterEvent& event);
diff --git a/media/jni/tuner/FilterClient.cpp b/media/jni/tuner/FilterClient.cpp
index d4d8837..fe746fa 100644
--- a/media/jni/tuner/FilterClient.cpp
+++ b/media/jni/tuner/FilterClient.cpp
@@ -193,8 +193,27 @@
return Result::INVALID_STATE;
}
-/////////////// TunerFilterCallback ///////////////////////
+string FilterClient::createSharedFilter() {
+ if (mTunerFilter != nullptr) {
+ string filterToken;
+ if (mTunerFilter->createSharedFilter(&filterToken).isOk()) {
+ return filterToken;
+ }
+ }
+ return "";
+}
+
+Result FilterClient::releaseSharedFilter(const string& filterToken) {
+ if (mTunerFilter != nullptr) {
+ Status s = mTunerFilter->releaseSharedFilter(filterToken);
+ return ClientHelper::getServiceSpecificErrorCode(s);
+ }
+
+ return Result::INVALID_STATE;
+}
+
+/////////////// TunerFilterCallback ///////////////////////
TunerFilterCallback::TunerFilterCallback(sp<FilterClientCallback> filterClientCallback)
: mFilterClientCallback(filterClientCallback) {}
@@ -215,14 +234,14 @@
}
Result FilterClient::getFilterMq() {
- if (mFilterMQ != NULL) {
+ if (mFilterMQ != nullptr) {
return Result::SUCCESS;
}
AidlMQDesc aidlMqDesc;
Result res = Result::UNAVAILABLE;
- if (mTunerFilter != NULL) {
+ if (mTunerFilter != nullptr) {
Status s = mTunerFilter->getQueueDesc(&aidlMqDesc);
if (s.isOk()) {
mFilterMQ = new (nothrow) AidlMQ(aidlMqDesc, false/*resetPointer*/);
diff --git a/media/jni/tuner/FilterClient.h b/media/jni/tuner/FilterClient.h
index 136d1f5..c031b2a 100644
--- a/media/jni/tuner/FilterClient.h
+++ b/media/jni/tuner/FilterClient.h
@@ -142,6 +142,16 @@
*/
Result close();
+ /**
+ * Create a new SharedFiler.
+ */
+ string createSharedFilter();
+
+ /**
+ * Release SharedFiler.
+ */
+ Result releaseSharedFilter(const string& filterToken);
+
private:
Result getFilterMq();
int64_t copyData(int8_t* buffer, int64_t size);
diff --git a/media/jni/tuner/TunerClient.cpp b/media/jni/tuner/TunerClient.cpp
index d19ee0d4..861d78d 100644
--- a/media/jni/tuner/TunerClient.cpp
+++ b/media/jni/tuner/TunerClient.cpp
@@ -33,8 +33,10 @@
/////////////// TunerClient ///////////////////////
TunerClient::TunerClient() {
- ::ndk::SpAIBinder binder(AServiceManager_getService("media.tuner"));
- mTunerService = ITunerService::fromBinder(binder);
+ if (mTunerService == nullptr) {
+ ::ndk::SpAIBinder binder(AServiceManager_getService("media.tuner"));
+ mTunerService = ITunerService::fromBinder(binder);
+ }
if (mTunerService == nullptr) {
ALOGE("Failed to get tuner service");
} else {
@@ -43,8 +45,6 @@
}
TunerClient::~TunerClient() {
- mTunerVersion = 0;
- mTunerService = nullptr;
}
vector<int32_t> TunerClient::getFrontendIds() {
@@ -163,4 +163,26 @@
return nullptr;
}
+sp<FilterClient> TunerClient::openSharedFilter(const string& filterToken,
+ sp<FilterClientCallback> cb) {
+ if (cb == nullptr) {
+ return nullptr;
+ }
+
+ if (mTunerService != nullptr) {
+ shared_ptr<ITunerFilter> tunerFilter;
+ shared_ptr<TunerFilterCallback> callback =
+ ::ndk::SharedRefBase::make<TunerFilterCallback>(cb);
+ Status s = mTunerService->openSharedFilter(filterToken, callback, &tunerFilter);
+ if (!s.isOk()) {
+ return nullptr;
+ }
+ DemuxFilterType type;
+ tunerFilter->getFilterType(&type);
+ return new FilterClient(type, tunerFilter);
+ }
+
+ return nullptr;
+}
+
} // namespace android
diff --git a/media/jni/tuner/TunerClient.h b/media/jni/tuner/TunerClient.h
index 641f106..3e59e26 100644
--- a/media/jni/tuner/TunerClient.h
+++ b/media/jni/tuner/TunerClient.h
@@ -20,10 +20,12 @@
#include <aidl/android/media/tv/tuner/ITunerService.h>
#include <android/binder_parcel_utils.h>
-#include "DemuxClient.h"
#include "ClientHelper.h"
-#include "FrontendClient.h"
+#include "DemuxClient.h"
#include "DescramblerClient.h"
+#include "FilterClient.h"
+#include "FilterClientCallback.h"
+#include "FrontendClient.h"
#include "LnbClient.h"
using Status = ::ndk::ScopedAStatus;
@@ -116,6 +118,15 @@
*/
int32_t getHalTunerVersion() { return mTunerVersion; }
+ /**
+ * Open a new shared filter client.
+ *
+ * @param filterToken the shared filter token created by FilterClient.
+ * @param cb the FilterClientCallback to receive filter events.
+ * @return a newly created TunerFilter interface.
+ */
+ sp<FilterClient> openSharedFilter(const string& filterToken, sp<FilterClientCallback> cb);
+
private:
/**
* An AIDL Tuner Service Singleton assigned at the first time the Tuner Client
diff --git a/packages/CompanionDeviceManager/src/com/android/companiondevicemanager/CompanionDeviceActivity.java b/packages/CompanionDeviceManager/src/com/android/companiondevicemanager/CompanionDeviceActivity.java
index b4cafd8..edbfd2a 100644
--- a/packages/CompanionDeviceManager/src/com/android/companiondevicemanager/CompanionDeviceActivity.java
+++ b/packages/CompanionDeviceManager/src/com/android/companiondevicemanager/CompanionDeviceActivity.java
@@ -254,8 +254,14 @@
Log.i(LOG_TAG, "onDeviceConfirmed(selectedDevice = " + selectedDevice + ")");
getService().onDeviceSelected(
getCallingPackage(), getDeviceMacAddress(selectedDevice.device));
+ }
+
+ void setResultAndFinish() {
+ Log.i(LOG_TAG, "setResultAndFinish(selectedDevice = "
+ + getService().mSelectedDevice.device + ")");
setResult(RESULT_OK,
- new Intent().putExtra(CompanionDeviceManager.EXTRA_DEVICE, selectedDevice.device));
+ new Intent().putExtra(
+ CompanionDeviceManager.EXTRA_DEVICE, getService().mSelectedDevice.device));
finish();
}
diff --git a/packages/CompanionDeviceManager/src/com/android/companiondevicemanager/CompanionDeviceDiscoveryService.java b/packages/CompanionDeviceManager/src/com/android/companiondevicemanager/CompanionDeviceDiscoveryService.java
index 3636f8f..4ac217a 100644
--- a/packages/CompanionDeviceManager/src/com/android/companiondevicemanager/CompanionDeviceDiscoveryService.java
+++ b/packages/CompanionDeviceManager/src/com/android/companiondevicemanager/CompanionDeviceDiscoveryService.java
@@ -116,6 +116,11 @@
CompanionDeviceDiscoveryService::startDiscovery,
CompanionDeviceDiscoveryService.this, request));
}
+
+ @Override
+ public void onAssociationCreated() {
+ Handler.getMain().post(CompanionDeviceDiscoveryService.this::onAssociationCreated);
+ }
};
private ScanCallback mBLEScanCallback;
@@ -221,6 +226,11 @@
SCAN_TIMEOUT);
}
+ @MainThread
+ private void onAssociationCreated() {
+ mActivity.setResultAndFinish();
+ }
+
private boolean shouldScan(List<? extends DeviceFilter> mediumSpecificFilters) {
return !isEmpty(mediumSpecificFilters) || isEmpty(mFilters);
}
diff --git a/packages/PackageInstaller/OWNERS b/packages/PackageInstaller/OWNERS
index c633113..2736870 100644
--- a/packages/PackageInstaller/OWNERS
+++ b/packages/PackageInstaller/OWNERS
@@ -1,7 +1,5 @@
svetoslavganov@google.com
-toddke@google.com
-patb@google.com
-suprabh@google.com
+include /PACKAGE_MANAGER_OWNERS
# For automotive related changes
rogerxue@google.com
diff --git a/packages/PackageInstaller/res/values-as/strings.xml b/packages/PackageInstaller/res/values-as/strings.xml
index c050d39..5224101 100644
--- a/packages/PackageInstaller/res/values-as/strings.xml
+++ b/packages/PackageInstaller/res/values-as/strings.xml
@@ -56,7 +56,7 @@
<string name="uninstall_application_text" msgid="3816830743706143980">"আপুনি এই এপটো আনইনষ্টল কৰিব বিচাৰেনে?"</string>
<string name="uninstall_application_text_all_users" msgid="575491774380227119">"আপুনি "<b>"সকলো"</b>" ব্যৱহাৰকাৰীৰ বাবে এই এপটো আনইনষ্টল কৰিব বিচাৰেনে? এপ্লিকেশ্বন আৰু ইয়াৰ ডেটা ডিভাইচটোত থকা "<b>"সকলো"</b>" ব্যৱহাৰকাৰীৰ পৰা আঁতৰোৱা হ\'ব৷"</string>
<string name="uninstall_application_text_user" msgid="498072714173920526">"আপুনি ব্যৱহাৰকাৰীৰ <xliff:g id="USERNAME">%1$s</xliff:g> বাবে এই এপটো আনইনষ্টল কৰিব বিচাৰেনে?"</string>
- <string name="uninstall_update_text" msgid="863648314632448705">"এই এপটোৰ ফেক্টৰী সংস্কৰণ ব্যৱহাৰ কৰিব বিচাৰেনে? সকলো ডেটা মচা হ\'ব।"</string>
+ <string name="uninstall_update_text" msgid="863648314632448705">"এই এপ্টোৰ ফেক্টৰী সংস্কৰণ ব্যৱহাৰ কৰিব বিচাৰেনে? আটাইবোৰ ডেটা মচা হ\'ব।"</string>
<string name="uninstall_update_text_multiuser" msgid="8992883151333057227">"এই এপটোৰ ফেক্টৰী সংস্কৰণ ব্যৱহাৰ কৰিব বিচাৰেনে? সকলো ডেটা মচা হ\'ব। কর্মস্থানৰ প্ৰফাইল থকা ব্যৱহাৰকাৰীৰ লগতে ডিভাইচটোৰ সকলো ব্যৱহাৰকাৰীৰ ওপৰত ইয়াৰ প্ৰভাৱ পৰিব।"</string>
<string name="uninstall_keep_data" msgid="7002379587465487550">"এপৰ ডেটাৰ <xliff:g id="SIZE">%1$s</xliff:g> ৰাখক"</string>
<string name="uninstalling_notification_channel" msgid="840153394325714653">"আনইনষ্টল কৰি থকা হৈছে"</string>
diff --git a/packages/PrintSpooler/res/values-as/strings.xml b/packages/PrintSpooler/res/values-as/strings.xml
index a93fceb..020eac7 100644
--- a/packages/PrintSpooler/res/values-as/strings.xml
+++ b/packages/PrintSpooler/res/values-as/strings.xml
@@ -28,7 +28,7 @@
<string name="label_orientation" msgid="2853142581990496477">"দিশ"</string>
<string name="label_pages" msgid="7768589729282182230">"পৃষ্ঠাসমূহ"</string>
<string name="destination_default_text" msgid="5422708056807065710">"প্ৰিণ্টাৰ বাছনি কৰক"</string>
- <string name="template_all_pages" msgid="3322235982020148762">"সকলো <xliff:g id="PAGE_COUNT">%1$s</xliff:g>"</string>
+ <string name="template_all_pages" msgid="3322235982020148762">"আটাইবোৰ <xliff:g id="PAGE_COUNT">%1$s</xliff:g>"</string>
<string name="template_page_range" msgid="428638530038286328">"<xliff:g id="PAGE_COUNT">%1$s</xliff:g>ৰ পৰিসৰ"</string>
<string name="pages_range_example" msgid="8558694453556945172">"যেনে: ১—৫, ৮, ১১—১৩"</string>
<string name="print_preview" msgid="8010217796057763343">"প্ৰিণ্টৰ পূৰ্বদৰ্শন"</string>
@@ -36,7 +36,7 @@
<string name="printing_app_crashed" msgid="854477616686566398">"প্ৰিণ্টিং এপ্ ক্ৰেশ্ব হৈছে"</string>
<string name="generating_print_job" msgid="3119608742651698916">"প্ৰিণ্টিং প্ৰস্তুত কৰি আছে"</string>
<string name="save_as_pdf" msgid="5718454119847596853">"PDF ৰূপে ছেভ কৰক"</string>
- <string name="all_printers" msgid="5018829726861876202">"সকলো প্ৰিণ্টাৰ…"</string>
+ <string name="all_printers" msgid="5018829726861876202">"আটাইবোৰ প্ৰিণ্টাৰ…"</string>
<string name="print_dialog" msgid="32628687461331979">"প্ৰিণ্ট সংবাদ"</string>
<string name="current_page_template" msgid="5145005201131935302">"<xliff:g id="CURRENT_PAGE">%1$d</xliff:g> /<xliff:g id="PAGE_COUNT">%2$d</xliff:g>"</string>
<string name="page_description_template" msgid="6831239682256197161">"পৃষ্ঠা <xliff:g id="PAGE_COUNT">%2$d</xliff:g>ৰ <xliff:g id="CURRENT_PAGE">%1$d</xliff:g>"</string>
@@ -48,7 +48,7 @@
<string name="print_options_expanded" msgid="6944679157471691859">"প্ৰিণ্ট বিকল্পসমূহ বিস্তাৰ কৰা হ’ল"</string>
<string name="print_options_collapsed" msgid="7455930445670414332">"প্ৰিণ্ট বিকল্পসমূহ সংকুচিত কৰা হ’ল"</string>
<string name="search" msgid="5421724265322228497">"সন্ধান কৰক"</string>
- <string name="all_printers_label" msgid="3178848870161526399">"সকলো প্ৰিণ্টাৰ"</string>
+ <string name="all_printers_label" msgid="3178848870161526399">"আটাইবোৰ প্ৰিণ্টাৰ"</string>
<string name="add_print_service_label" msgid="5356702546188981940">"সেৱা যোগ কৰক"</string>
<string name="print_search_box_shown_utterance" msgid="7967404953901376090">"সন্ধান বাকচটো দেখুওৱা হ’ল"</string>
<string name="print_search_box_hidden_utterance" msgid="5727755169343113351">"সন্ধান বাকচটো ঢাক খাই আছে"</string>
@@ -74,7 +74,7 @@
<string name="enabled_services_title" msgid="7036986099096582296">"সক্ষম কৰা সেৱাসমূহ"</string>
<string name="recommended_services_title" msgid="3799434882937956924">"অনুমোদিত সেৱাসমূহ"</string>
<string name="disabled_services_title" msgid="7313253167968363211">"অক্ষম কৰা সেৱাসমূহ"</string>
- <string name="all_services_title" msgid="5578662754874906455">"সকলো সেৱা"</string>
+ <string name="all_services_title" msgid="5578662754874906455">"আটাইবোৰ সেৱা"</string>
<plurals name="print_services_recommendation_subtitle" formatted="false" msgid="5678487708807185138">
<item quantity="one"><xliff:g id="COUNT_1">%1$s</xliff:g>টা প্ৰিণ্টাৰ বিচাৰিবলৈ ইনষ্টল কৰক</item>
<item quantity="other"><xliff:g id="COUNT_1">%1$s</xliff:g>টা প্ৰিণ্টাৰ বিচাৰিবলৈ ইনষ্টল কৰক</item>
diff --git a/packages/SettingsLib/res/values-az/strings.xml b/packages/SettingsLib/res/values-az/strings.xml
index 335e982e..979c957 100644
--- a/packages/SettingsLib/res/values-az/strings.xml
+++ b/packages/SettingsLib/res/values-az/strings.xml
@@ -122,11 +122,9 @@
<string name="bluetooth_profile_a2dp_high_quality" msgid="4739440941324792775">"HD audio: <xliff:g id="CODEC_NAME">%1$s</xliff:g>"</string>
<string name="bluetooth_profile_a2dp_high_quality_unknown_codec" msgid="2477639096903834374">"HD audio"</string>
<string name="bluetooth_profile_hearing_aid" msgid="58154575573984914">"Eşitmə cihazları"</string>
- <!-- no translation found for bluetooth_profile_le_audio (5158149987518342036) -->
- <skip />
+ <string name="bluetooth_profile_le_audio" msgid="5158149987518342036">"LE_AUDIO"</string>
<string name="bluetooth_hearing_aid_profile_summary_connected" msgid="8191273236809964030">"Eşitmə Aparatlarına qoşuldu"</string>
- <!-- no translation found for bluetooth_le_audio_profile_summary_connected (3162538609379333442) -->
- <skip />
+ <string name="bluetooth_le_audio_profile_summary_connected" msgid="3162538609379333442">"LE_AUDIO audiosuna qoşulub"</string>
<string name="bluetooth_a2dp_profile_summary_connected" msgid="7422607970115444153">"Media audioya birləşdirilib"</string>
<string name="bluetooth_headset_profile_summary_connected" msgid="2420981566026949688">"Telefon audiosuna qoşulu"</string>
<string name="bluetooth_opp_profile_summary_connected" msgid="2393521801478157362">"Fayl transfer serverinə qoşulu"</string>
@@ -144,8 +142,7 @@
<string name="bluetooth_opp_profile_summary_use_for" msgid="461981154387015457">"Fayl transferi üçün istifadə edin"</string>
<string name="bluetooth_hid_profile_summary_use_for" msgid="4289460627406490952">"Daxiletmə üçün istifadə edin"</string>
<string name="bluetooth_hearing_aid_profile_summary_use_for" msgid="7689393730163320483">"Eşitmə Aparatları üçün istifadə edin"</string>
- <!-- no translation found for bluetooth_le_audio_profile_summary_use_for (2778318636027348572) -->
- <skip />
+ <string name="bluetooth_le_audio_profile_summary_use_for" msgid="2778318636027348572">"LE_AUDIO üçün istifadə edin"</string>
<string name="bluetooth_pairing_accept" msgid="2054232610815498004">"Qoşulsun"</string>
<string name="bluetooth_pairing_accept_all_caps" msgid="2734383073450506220">"QOŞULSUN"</string>
<string name="bluetooth_pairing_decline" msgid="6483118841204885890">"Ləğv edin"</string>
diff --git a/packages/SettingsLib/res/values-bn/strings.xml b/packages/SettingsLib/res/values-bn/strings.xml
index 2e614fa..89fcbd3 100644
--- a/packages/SettingsLib/res/values-bn/strings.xml
+++ b/packages/SettingsLib/res/values-bn/strings.xml
@@ -122,11 +122,9 @@
<string name="bluetooth_profile_a2dp_high_quality" msgid="4739440941324792775">"HD অডিও: <xliff:g id="CODEC_NAME">%1$s</xliff:g>"</string>
<string name="bluetooth_profile_a2dp_high_quality_unknown_codec" msgid="2477639096903834374">"HD অডিও"</string>
<string name="bluetooth_profile_hearing_aid" msgid="58154575573984914">"হিয়ারিং এড"</string>
- <!-- no translation found for bluetooth_profile_le_audio (5158149987518342036) -->
- <skip />
+ <string name="bluetooth_profile_le_audio" msgid="5158149987518342036">"LE_AUDIO"</string>
<string name="bluetooth_hearing_aid_profile_summary_connected" msgid="8191273236809964030">"হিয়ারিং এডের সাথে কানেক্ট করা হয়েছে"</string>
- <!-- no translation found for bluetooth_le_audio_profile_summary_connected (3162538609379333442) -->
- <skip />
+ <string name="bluetooth_le_audio_profile_summary_connected" msgid="3162538609379333442">"LE_AUDIO-এ কানেক্ট করা হয়েছে"</string>
<string name="bluetooth_a2dp_profile_summary_connected" msgid="7422607970115444153">"মিডিয়া অডিওতে কানেক্ট রয়েছে"</string>
<string name="bluetooth_headset_profile_summary_connected" msgid="2420981566026949688">"ফোন অডিওতে কানেক্ট"</string>
<string name="bluetooth_opp_profile_summary_connected" msgid="2393521801478157362">"ফাইল স্থানান্তর সার্ভারের সঙ্গে কানেক্ট"</string>
@@ -144,8 +142,7 @@
<string name="bluetooth_opp_profile_summary_use_for" msgid="461981154387015457">"ফাইল স্থানান্তরের জন্য ব্যবহার করুন"</string>
<string name="bluetooth_hid_profile_summary_use_for" msgid="4289460627406490952">"ইনপুটের জন্য ব্যবহার করুন"</string>
<string name="bluetooth_hearing_aid_profile_summary_use_for" msgid="7689393730163320483">"হিয়ারিং এডের জন্য ব্যবহার করুন"</string>
- <!-- no translation found for bluetooth_le_audio_profile_summary_use_for (2778318636027348572) -->
- <skip />
+ <string name="bluetooth_le_audio_profile_summary_use_for" msgid="2778318636027348572">"LE_AUDIO-এর জন্য ব্যবহার করুন"</string>
<string name="bluetooth_pairing_accept" msgid="2054232610815498004">"যুক্ত করুন"</string>
<string name="bluetooth_pairing_accept_all_caps" msgid="2734383073450506220">"যুক্ত করুন"</string>
<string name="bluetooth_pairing_decline" msgid="6483118841204885890">"বাতিল করুন"</string>
diff --git a/packages/SettingsLib/res/values-de/strings.xml b/packages/SettingsLib/res/values-de/strings.xml
index a75d19b..defc223 100644
--- a/packages/SettingsLib/res/values-de/strings.xml
+++ b/packages/SettingsLib/res/values-de/strings.xml
@@ -122,11 +122,9 @@
<string name="bluetooth_profile_a2dp_high_quality" msgid="4739440941324792775">"HD-Audio: <xliff:g id="CODEC_NAME">%1$s</xliff:g>"</string>
<string name="bluetooth_profile_a2dp_high_quality_unknown_codec" msgid="2477639096903834374">"HD-Audio"</string>
<string name="bluetooth_profile_hearing_aid" msgid="58154575573984914">"Hörhilfen"</string>
- <!-- no translation found for bluetooth_profile_le_audio (5158149987518342036) -->
- <skip />
+ <string name="bluetooth_profile_le_audio" msgid="5158149987518342036">"LE_AUDIO"</string>
<string name="bluetooth_hearing_aid_profile_summary_connected" msgid="8191273236809964030">"Mit Hörhilfen verbunden"</string>
- <!-- no translation found for bluetooth_le_audio_profile_summary_connected (3162538609379333442) -->
- <skip />
+ <string name="bluetooth_le_audio_profile_summary_connected" msgid="3162538609379333442">"Verbinden mit LE_AUDIO"</string>
<string name="bluetooth_a2dp_profile_summary_connected" msgid="7422607970115444153">"Verbunden mit Medien-Audio"</string>
<string name="bluetooth_headset_profile_summary_connected" msgid="2420981566026949688">"Verbunden mit Telefon-Audio"</string>
<string name="bluetooth_opp_profile_summary_connected" msgid="2393521801478157362">"Mit Dateiübertragungsserver verbunden"</string>
@@ -144,8 +142,7 @@
<string name="bluetooth_opp_profile_summary_use_for" msgid="461981154387015457">"Für Dateiübertragung verwenden"</string>
<string name="bluetooth_hid_profile_summary_use_for" msgid="4289460627406490952">"Für Eingabe verwenden"</string>
<string name="bluetooth_hearing_aid_profile_summary_use_for" msgid="7689393730163320483">"Für Hörhilfen verwenden"</string>
- <!-- no translation found for bluetooth_le_audio_profile_summary_use_for (2778318636027348572) -->
- <skip />
+ <string name="bluetooth_le_audio_profile_summary_use_for" msgid="2778318636027348572">"Für LE_AUDIO verwenden"</string>
<string name="bluetooth_pairing_accept" msgid="2054232610815498004">"Koppeln"</string>
<string name="bluetooth_pairing_accept_all_caps" msgid="2734383073450506220">"KOPPELN"</string>
<string name="bluetooth_pairing_decline" msgid="6483118841204885890">"Abbrechen"</string>
diff --git a/packages/SettingsLib/res/values-fa/strings.xml b/packages/SettingsLib/res/values-fa/strings.xml
index a5a11eb..3dce25d 100644
--- a/packages/SettingsLib/res/values-fa/strings.xml
+++ b/packages/SettingsLib/res/values-fa/strings.xml
@@ -314,7 +314,7 @@
<string name="wifi_display_certification_summary" msgid="8111151348106907513">"نمایش گزینهها برای گواهینامه نمایش بیسیم"</string>
<string name="wifi_verbose_logging_summary" msgid="4993823188807767892">"افزایش سطح گزارشگیری Wi‑Fi، نمایش به ازای SSID RSSI در انتخابکننده Wi‑Fi"</string>
<string name="wifi_scan_throttling_summary" msgid="2577105472017362814">"تخلیه باتری راکاهش میدهد و عملکرد شبکه را بهبود میبخشد"</string>
- <string name="wifi_non_persistent_mac_randomization_summary" msgid="2159794543105053930">"اگر این حالت فعال باشد، هر بار این دستگاه به شبکهای متصل شود که تصادفیسازی MAC در آن فعال است، ممکن است نشانی MAC آن تغییر کند."</string>
+ <string name="wifi_non_persistent_mac_randomization_summary" msgid="2159794543105053930">"اگر این حالت فعال باشد، هر بار این دستگاه به شبکهای متصل شود که تصادفیسازی «واپایش دسترسی رسانه» در آن فعال است، ممکن است «نشانی واد» آن تغییر کند."</string>
<string name="wifi_metered_label" msgid="8737187690304098638">"محدودشده"</string>
<string name="wifi_unmetered_label" msgid="6174142840934095093">"محدودنشده"</string>
<string name="select_logd_size_title" msgid="1604578195914595173">"اندازههای حافظه موقت ثبتکننده"</string>
diff --git a/packages/SettingsLib/res/values-fr-rCA/strings.xml b/packages/SettingsLib/res/values-fr-rCA/strings.xml
index b00ea16..73fadf7 100644
--- a/packages/SettingsLib/res/values-fr-rCA/strings.xml
+++ b/packages/SettingsLib/res/values-fr-rCA/strings.xml
@@ -122,11 +122,9 @@
<string name="bluetooth_profile_a2dp_high_quality" msgid="4739440941324792775">"Audio HD : <xliff:g id="CODEC_NAME">%1$s</xliff:g>"</string>
<string name="bluetooth_profile_a2dp_high_quality_unknown_codec" msgid="2477639096903834374">"Audio HD"</string>
<string name="bluetooth_profile_hearing_aid" msgid="58154575573984914">"Prothèses auditives"</string>
- <!-- no translation found for bluetooth_profile_le_audio (5158149987518342036) -->
- <skip />
+ <string name="bluetooth_profile_le_audio" msgid="5158149987518342036">"LE_AUDIO"</string>
<string name="bluetooth_hearing_aid_profile_summary_connected" msgid="8191273236809964030">"Connecté aux prothèses auditives"</string>
- <!-- no translation found for bluetooth_le_audio_profile_summary_connected (3162538609379333442) -->
- <skip />
+ <string name="bluetooth_le_audio_profile_summary_connected" msgid="3162538609379333442">"Connecté à LE_AUDIO"</string>
<string name="bluetooth_a2dp_profile_summary_connected" msgid="7422607970115444153">"Connecté aux paramètres audio du média"</string>
<string name="bluetooth_headset_profile_summary_connected" msgid="2420981566026949688">"Connecté à l\'audio du téléphone"</string>
<string name="bluetooth_opp_profile_summary_connected" msgid="2393521801478157362">"Connexion au serveur de transfert de fichiers"</string>
@@ -144,8 +142,7 @@
<string name="bluetooth_opp_profile_summary_use_for" msgid="461981154387015457">"Utiliser pour le transfert de fichiers"</string>
<string name="bluetooth_hid_profile_summary_use_for" msgid="4289460627406490952">"Utiliser comme entrée"</string>
<string name="bluetooth_hearing_aid_profile_summary_use_for" msgid="7689393730163320483">"Utiliser avec les prothèses auditives"</string>
- <!-- no translation found for bluetooth_le_audio_profile_summary_use_for (2778318636027348572) -->
- <skip />
+ <string name="bluetooth_le_audio_profile_summary_use_for" msgid="2778318636027348572">"Utiliser pour LE_AUDIO"</string>
<string name="bluetooth_pairing_accept" msgid="2054232610815498004">"Associer"</string>
<string name="bluetooth_pairing_accept_all_caps" msgid="2734383073450506220">"ASSOCIER"</string>
<string name="bluetooth_pairing_decline" msgid="6483118841204885890">"Annuler"</string>
diff --git a/packages/SettingsLib/res/values-gl/strings.xml b/packages/SettingsLib/res/values-gl/strings.xml
index 109cdc6..cb33a51 100644
--- a/packages/SettingsLib/res/values-gl/strings.xml
+++ b/packages/SettingsLib/res/values-gl/strings.xml
@@ -122,11 +122,9 @@
<string name="bluetooth_profile_a2dp_high_quality" msgid="4739440941324792775">"Audio en HD: <xliff:g id="CODEC_NAME">%1$s</xliff:g>"</string>
<string name="bluetooth_profile_a2dp_high_quality_unknown_codec" msgid="2477639096903834374">"Audio en HD"</string>
<string name="bluetooth_profile_hearing_aid" msgid="58154575573984914">"Audiófonos"</string>
- <!-- no translation found for bluetooth_profile_le_audio (5158149987518342036) -->
- <skip />
+ <string name="bluetooth_profile_le_audio" msgid="5158149987518342036">"LE_AUDIO"</string>
<string name="bluetooth_hearing_aid_profile_summary_connected" msgid="8191273236809964030">"Conectado a audiófonos"</string>
- <!-- no translation found for bluetooth_le_audio_profile_summary_connected (3162538609379333442) -->
- <skip />
+ <string name="bluetooth_le_audio_profile_summary_connected" msgid="3162538609379333442">"Conexión establecida con LE_AUDIO"</string>
<string name="bluetooth_a2dp_profile_summary_connected" msgid="7422607970115444153">"Conectado ao audio multimedia"</string>
<string name="bluetooth_headset_profile_summary_connected" msgid="2420981566026949688">"Conectado ao audio do teléfono"</string>
<string name="bluetooth_opp_profile_summary_connected" msgid="2393521801478157362">"Conectado ao servidor de transferencia de ficheiros"</string>
@@ -144,8 +142,7 @@
<string name="bluetooth_opp_profile_summary_use_for" msgid="461981154387015457">"Utilízase para a transferencia de ficheiros"</string>
<string name="bluetooth_hid_profile_summary_use_for" msgid="4289460627406490952">"Utilízase para a entrada"</string>
<string name="bluetooth_hearing_aid_profile_summary_use_for" msgid="7689393730163320483">"Utilizar para audiófonos"</string>
- <!-- no translation found for bluetooth_le_audio_profile_summary_use_for (2778318636027348572) -->
- <skip />
+ <string name="bluetooth_le_audio_profile_summary_use_for" msgid="2778318636027348572">"Usa esta opción para LE_AUDIO"</string>
<string name="bluetooth_pairing_accept" msgid="2054232610815498004">"Vincular"</string>
<string name="bluetooth_pairing_accept_all_caps" msgid="2734383073450506220">"VINCULAR"</string>
<string name="bluetooth_pairing_decline" msgid="6483118841204885890">"Cancelar"</string>
diff --git a/packages/SettingsLib/res/values-gu/strings.xml b/packages/SettingsLib/res/values-gu/strings.xml
index 5bb68b7..f2e3604 100644
--- a/packages/SettingsLib/res/values-gu/strings.xml
+++ b/packages/SettingsLib/res/values-gu/strings.xml
@@ -122,11 +122,9 @@
<string name="bluetooth_profile_a2dp_high_quality" msgid="4739440941324792775">"HD ઑડિયો: <xliff:g id="CODEC_NAME">%1$s</xliff:g>"</string>
<string name="bluetooth_profile_a2dp_high_quality_unknown_codec" msgid="2477639096903834374">"HD ઑડિયો"</string>
<string name="bluetooth_profile_hearing_aid" msgid="58154575573984914">"શ્રવણ યંત્રો"</string>
- <!-- no translation found for bluetooth_profile_le_audio (5158149987518342036) -->
- <skip />
+ <string name="bluetooth_profile_le_audio" msgid="5158149987518342036">"LE_AUDIO"</string>
<string name="bluetooth_hearing_aid_profile_summary_connected" msgid="8191273236809964030">"શ્રવણ યંત્રો સાથે કનેક્ટ કરેલું છે"</string>
- <!-- no translation found for bluetooth_le_audio_profile_summary_connected (3162538609379333442) -->
- <skip />
+ <string name="bluetooth_le_audio_profile_summary_connected" msgid="3162538609379333442">"LE_AUDIO સાથે કનેક્ટેડ છે"</string>
<string name="bluetooth_a2dp_profile_summary_connected" msgid="7422607970115444153">"મીડિયા ઑડિઓ સાથે કનેક્ટ કર્યુ"</string>
<string name="bluetooth_headset_profile_summary_connected" msgid="2420981566026949688">"ફોન ઑડિઓ સાથે કનેક્ટ થયાં"</string>
<string name="bluetooth_opp_profile_summary_connected" msgid="2393521801478157362">"ફાઇલ સ્થાનાંતરણ સેવાથી કનેક્ટ થયાં"</string>
@@ -144,8 +142,7 @@
<string name="bluetooth_opp_profile_summary_use_for" msgid="461981154387015457">"ફાઇલ સ્થાનાંતર માટે ઉપયોગ કરો"</string>
<string name="bluetooth_hid_profile_summary_use_for" msgid="4289460627406490952">"ઇનપુટ માટે ઉપયોગ કરો"</string>
<string name="bluetooth_hearing_aid_profile_summary_use_for" msgid="7689393730163320483">"શ્રવણ યંત્રો માટે ઉપયોગ કરો"</string>
- <!-- no translation found for bluetooth_le_audio_profile_summary_use_for (2778318636027348572) -->
- <skip />
+ <string name="bluetooth_le_audio_profile_summary_use_for" msgid="2778318636027348572">"LE_AUDIO માટે ઉપયોગ કરો"</string>
<string name="bluetooth_pairing_accept" msgid="2054232610815498004">"જોડી"</string>
<string name="bluetooth_pairing_accept_all_caps" msgid="2734383073450506220">"જોડી કરો"</string>
<string name="bluetooth_pairing_decline" msgid="6483118841204885890">"રદ કરો"</string>
diff --git a/packages/SettingsLib/res/values-iw/strings.xml b/packages/SettingsLib/res/values-iw/strings.xml
index f969f45..e7f83c6 100644
--- a/packages/SettingsLib/res/values-iw/strings.xml
+++ b/packages/SettingsLib/res/values-iw/strings.xml
@@ -554,7 +554,7 @@
<string name="zen_mode_duration_always_prompt_title" msgid="3212996860498119555">"יש לשאול בכל פעם"</string>
<string name="zen_mode_forever" msgid="3339224497605461291">"עד הכיבוי"</string>
<string name="time_unit_just_now" msgid="3006134267292728099">"הרגע"</string>
- <string name="media_transfer_this_device_name" msgid="2716555073132169240">"רמקול של הטלפון"</string>
+ <string name="media_transfer_this_device_name" msgid="2716555073132169240">"הרמקול של הטלפון"</string>
<string name="media_transfer_this_phone" msgid="7194341457812151531">"הטלפון הזה"</string>
<string name="profile_connect_timeout_subtext" msgid="4043408193005851761">"יש בעיה בחיבור. עליך לכבות את המכשיר ולהפעיל אותו מחדש"</string>
<string name="media_transfer_wired_device_name" msgid="4447880899964056007">"התקן אודיו חוטי"</string>
diff --git a/packages/SettingsLib/res/values-kk/strings.xml b/packages/SettingsLib/res/values-kk/strings.xml
index 28675ac..6305891 100644
--- a/packages/SettingsLib/res/values-kk/strings.xml
+++ b/packages/SettingsLib/res/values-kk/strings.xml
@@ -122,11 +122,9 @@
<string name="bluetooth_profile_a2dp_high_quality" msgid="4739440941324792775">"HD форматты аудио: <xliff:g id="CODEC_NAME">%1$s</xliff:g>"</string>
<string name="bluetooth_profile_a2dp_high_quality_unknown_codec" msgid="2477639096903834374">"HD форматты аудио"</string>
<string name="bluetooth_profile_hearing_aid" msgid="58154575573984914">"Есту аппараттары"</string>
- <!-- no translation found for bluetooth_profile_le_audio (5158149987518342036) -->
- <skip />
+ <string name="bluetooth_profile_le_audio" msgid="5158149987518342036">"LE_AUDIO"</string>
<string name="bluetooth_hearing_aid_profile_summary_connected" msgid="8191273236809964030">"Есту аппараттарына жалғанған"</string>
- <!-- no translation found for bluetooth_le_audio_profile_summary_connected (3162538609379333442) -->
- <skip />
+ <string name="bluetooth_le_audio_profile_summary_connected" msgid="3162538609379333442">"LE_AUDIO құрылғысына жалғанды."</string>
<string name="bluetooth_a2dp_profile_summary_connected" msgid="7422607970115444153">"Медиа аудиосына жалғанған"</string>
<string name="bluetooth_headset_profile_summary_connected" msgid="2420981566026949688">"Телефон аудиосына қосылған"</string>
<string name="bluetooth_opp_profile_summary_connected" msgid="2393521801478157362">"Файл жіберу серверіне жалғанған"</string>
@@ -144,8 +142,7 @@
<string name="bluetooth_opp_profile_summary_use_for" msgid="461981154387015457">"Файлды жіберу үшін қолдану"</string>
<string name="bluetooth_hid_profile_summary_use_for" msgid="4289460627406490952">"Кіріс үшін қолдану"</string>
<string name="bluetooth_hearing_aid_profile_summary_use_for" msgid="7689393730163320483">"Есту аппараттары үшін пайдалану"</string>
- <!-- no translation found for bluetooth_le_audio_profile_summary_use_for (2778318636027348572) -->
- <skip />
+ <string name="bluetooth_le_audio_profile_summary_use_for" msgid="2778318636027348572">"LE_AUDIO үшін пайдалану"</string>
<string name="bluetooth_pairing_accept" msgid="2054232610815498004">"Жұптау"</string>
<string name="bluetooth_pairing_accept_all_caps" msgid="2734383073450506220">"ЖҰПТАУ"</string>
<string name="bluetooth_pairing_decline" msgid="6483118841204885890">"Бас тарту"</string>
diff --git a/packages/SettingsLib/res/values-ms/strings.xml b/packages/SettingsLib/res/values-ms/strings.xml
index 0841328..7011aec 100644
--- a/packages/SettingsLib/res/values-ms/strings.xml
+++ b/packages/SettingsLib/res/values-ms/strings.xml
@@ -484,7 +484,7 @@
<string name="power_charging" msgid="6727132649743436802">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="STATE">%2$s</xliff:g>"</string>
<string name="power_remaining_charging_duration_only" msgid="8085099012811384899">"<xliff:g id="TIME">%1$s</xliff:g> lagi hingga penuh"</string>
<string name="power_charging_duration" msgid="6127154952524919719">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> lagi hingga penuh"</string>
- <string name="power_charging_limited" msgid="7956120998372505295">"<xliff:g id="LEVEL">%1$s</xliff:g> - Pengecasan terhad buat sementara waktu"</string>
+ <string name="power_charging_limited" msgid="7956120998372505295">"<xliff:g id="LEVEL">%1$s</xliff:g> - Pengecasan terhad sementara"</string>
<string name="battery_info_status_unknown" msgid="268625384868401114">"Tidak diketahui"</string>
<string name="battery_info_status_charging" msgid="4279958015430387405">"Mengecas"</string>
<string name="battery_info_status_charging_fast" msgid="8027559755902954885">"Mengecas dgn cepat"</string>
diff --git a/packages/SettingsLib/res/values-my/strings.xml b/packages/SettingsLib/res/values-my/strings.xml
index d5fbdaf..3de8cf9 100644
--- a/packages/SettingsLib/res/values-my/strings.xml
+++ b/packages/SettingsLib/res/values-my/strings.xml
@@ -199,7 +199,7 @@
<string name="tts_play_example_summary" msgid="634044730710636383">"အသံပေါင်းစပ်ခြင်းအတွက် တိုတောင်းသောသရုပ်ပြမှုကို ပြခြင်း"</string>
<string name="tts_install_data_title" msgid="1829942496472751703">"အသံဒေတာများကို ထည့်သွင်းခြင်း"</string>
<string name="tts_install_data_summary" msgid="3608874324992243851">"စကားသံပေါင်းစပ်မှုအတွက်လိုအပ်သောအသံဒေတာအား ထည့်သွင်းမည်"</string>
- <string name="tts_engine_security_warning" msgid="3372432853837988146">"ဤစကားသံပေါင်းစပ်အင်ဂျင်အားအသုံးပြုရာရာတွင် သင့်ကိုယ်ရေးအချက်အလက်များဖြစ်သော စကားဝှက်များနှင့် ကရက်ဒစ်ကဒ်နံပါတ်စသည်တို့အပါအဝင် သင်ပြောဆိုသောစာသားများအားလုံးကို ရယူသွားမည်ဖြစ်သည်။ <xliff:g id="TTS_PLUGIN_ENGINE_NAME">%s</xliff:g>အင်ဂျင်မှ လာပါသည်။ ဤစကားသံပေါင်းစပ်အင်ဂျင်ကို အသုံးပြုမည်လား?"</string>
+ <string name="tts_engine_security_warning" msgid="3372432853837988146">"ဤစကားသံပေါင်းစပ်စနစ်အားအသုံးပြုရာရာတွင် သင့်ကိုယ်ရေးအချက်အလက်များဖြစ်သော စကားဝှက်များနှင့် ကရက်ဒစ်ကတ်နံပါတ်စသည်တို့အပါအဝင် သင်ပြောဆိုသောစာသားများအားလုံးကို ရယူသွားမည်ဖြစ်သည်။ ဤစနစ်သည် <xliff:g id="TTS_PLUGIN_ENGINE_NAME">%s</xliff:g> မှ လာပါသည်။ ဤစကားသံပေါင်းစပ်စနစ်ကို အသုံးပြုမလား။"</string>
<string name="tts_engine_network_required" msgid="8722087649733906851">"ဤဘာသာစကားသည် စာသားမှ အသံထွက်ရန် အလုပ်လုပ်သော ကွန်ရက်ချိတ်ဆက်မှု လိုအပ်သည်။"</string>
<string name="tts_default_sample_string" msgid="6388016028292967973">"ဤသည်မှာ အသံတုလုပ်ခြင်း ၏ နမူနာတစ်ခုဖြစ်သည်။"</string>
<string name="tts_status_title" msgid="8190784181389278640">"လက်ရှိဘာသာစကားအခြေအနေ"</string>
@@ -519,7 +519,7 @@
<string name="active_input_method_subtypes" msgid="4232680535471633046">"ရနိုင်သောထည့်သွင်းရန်နည်းလမ်းများ"</string>
<string name="use_system_language_to_select_input_method_subtypes" msgid="4865195835541387040">"သတ်မှတ် ဘာသာစကားများကို သုံးပါ"</string>
<string name="failed_to_open_app_settings_toast" msgid="764897252657692092">"<xliff:g id="SPELL_APPLICATION_NAME">%1$s</xliff:g>အတွက် ဆက်တင်းများဖွင့်ရန် မအောင်မြင်ပါ။"</string>
- <string name="ime_security_warning" msgid="6547562217880551450">"ဤထည့်သွင်းမှုနည်းလမ်းမှာ သင့်ကိုယ်ရေးအချက်အလက်များဖြစ်သော စကားဝှက်များနှင့် ကရက်ဒစ်ကဒ်နံပါတ်စသည်တို့ကို ရယူသွားမည်ဖြစ်သည်။ <xliff:g id="IME_APPLICATION_NAME">%1$s</xliff:g>အပလီကေးရှင်းမှလာပါသည်။ ဤထည့်သွင်းမှုနည်းလမ်းကို အသုံးပြုမည်လား?"</string>
+ <string name="ime_security_warning" msgid="6547562217880551450">"ဤထည့်သွင်းမှုနည်းလမ်းမှာ သင့်ကိုယ်ရေးအချက်အလက်များဖြစ်သော စကားဝှက်များနှင့် ခရက်ဒစ်ကတ်နံပါတ်စသည်တို့ကို ရယူသွားမည်ဖြစ်သည်။ ဤ <xliff:g id="IME_APPLICATION_NAME">%1$s</xliff:g> အပလီကေးရှင်းမှလာပါသည်။ ဤထည့်သွင်းမှုနည်းလမ်းကို အသုံးပြုမလား။"</string>
<string name="direct_boot_unaware_dialog_message" msgid="7845398276735021548">"မှတ်ချက် − ပြန်လည်စတင်ပြီးနောက် သင့်ဖုန်းကိုလော့ခ်မဖွင့်မချင်း ဤအက်ပ်ကို အသုံးပြု၍မရပါ"</string>
<string name="ims_reg_title" msgid="8197592958123671062">"IMS မှတ်ပုံတင်ခြင်း အခြေအနေ"</string>
<string name="ims_reg_status_registered" msgid="884916398194885457">"မှတ်ပုံတင်ထားသည်"</string>
diff --git a/packages/SettingsLib/res/values-or/strings.xml b/packages/SettingsLib/res/values-or/strings.xml
index 2200567..49018be 100644
--- a/packages/SettingsLib/res/values-or/strings.xml
+++ b/packages/SettingsLib/res/values-or/strings.xml
@@ -122,11 +122,9 @@
<string name="bluetooth_profile_a2dp_high_quality" msgid="4739440941324792775">"HD ଅଡିଓ: <xliff:g id="CODEC_NAME">%1$s</xliff:g>"</string>
<string name="bluetooth_profile_a2dp_high_quality_unknown_codec" msgid="2477639096903834374">"HD ଅଡିଓ"</string>
<string name="bluetooth_profile_hearing_aid" msgid="58154575573984914">"ଶ୍ରବଣ ଯନ୍ତ୍ର"</string>
- <!-- no translation found for bluetooth_profile_le_audio (5158149987518342036) -->
- <skip />
+ <string name="bluetooth_profile_le_audio" msgid="5158149987518342036">"LE_AUDIO"</string>
<string name="bluetooth_hearing_aid_profile_summary_connected" msgid="8191273236809964030">"ଶ୍ରବଣ ଯନ୍ତ୍ରକୁ ସଂଯୋଗ ହୋଇଛି"</string>
- <!-- no translation found for bluetooth_le_audio_profile_summary_connected (3162538609379333442) -->
- <skip />
+ <string name="bluetooth_le_audio_profile_summary_connected" msgid="3162538609379333442">"LE_AUDIO ସହ ସଂଯୋଗ କରାଯାଇଛି"</string>
<string name="bluetooth_a2dp_profile_summary_connected" msgid="7422607970115444153">"ମିଡିଆ ଅଡିଓ ସହ ସଂଯୁକ୍ତ"</string>
<string name="bluetooth_headset_profile_summary_connected" msgid="2420981566026949688">"ଫୋନ୍ ଅଡିଓ ସହିତ ସଂଯୁକ୍ତ"</string>
<string name="bluetooth_opp_profile_summary_connected" msgid="2393521801478157362">"ଫାଇଲ୍ ଟ୍ରାନ୍ସଫର୍ ସର୍ଭର୍ ସହ ସଂଯୁକ୍ତ"</string>
@@ -144,8 +142,7 @@
<string name="bluetooth_opp_profile_summary_use_for" msgid="461981154387015457">"ଫାଇଲ୍ ଟ୍ରାନ୍ସଫର୍ ପାଇଁ ବ୍ୟବହାର କରନ୍ତୁ"</string>
<string name="bluetooth_hid_profile_summary_use_for" msgid="4289460627406490952">"ଇନ୍ପୁଟ୍ ପାଇଁ ବ୍ୟବହାର କରନ୍ତୁ"</string>
<string name="bluetooth_hearing_aid_profile_summary_use_for" msgid="7689393730163320483">"ଶ୍ରବଣ ଯନ୍ତ୍ର ପାଇଁ ବ୍ୟବହାର କରନ୍ତୁ"</string>
- <!-- no translation found for bluetooth_le_audio_profile_summary_use_for (2778318636027348572) -->
- <skip />
+ <string name="bluetooth_le_audio_profile_summary_use_for" msgid="2778318636027348572">"LE_AUDIO ପାଇଁ ବ୍ୟବହାର କରନ୍ତୁ"</string>
<string name="bluetooth_pairing_accept" msgid="2054232610815498004">"ପେୟାର୍"</string>
<string name="bluetooth_pairing_accept_all_caps" msgid="2734383073450506220">"ପେୟାର୍"</string>
<string name="bluetooth_pairing_decline" msgid="6483118841204885890">"ବାତିଲ୍ କରନ୍ତୁ"</string>
diff --git a/packages/SettingsLib/res/values-pa/strings.xml b/packages/SettingsLib/res/values-pa/strings.xml
index 3c1cfcb..9efc4c4 100644
--- a/packages/SettingsLib/res/values-pa/strings.xml
+++ b/packages/SettingsLib/res/values-pa/strings.xml
@@ -122,11 +122,9 @@
<string name="bluetooth_profile_a2dp_high_quality" msgid="4739440941324792775">"HD ਆਡੀਓ: <xliff:g id="CODEC_NAME">%1$s</xliff:g>"</string>
<string name="bluetooth_profile_a2dp_high_quality_unknown_codec" msgid="2477639096903834374">"HD ਆਡੀਓ"</string>
<string name="bluetooth_profile_hearing_aid" msgid="58154575573984914">"ਸੁਣਨ ਦੇ ਸਾਧਨ"</string>
- <!-- no translation found for bluetooth_profile_le_audio (5158149987518342036) -->
- <skip />
+ <string name="bluetooth_profile_le_audio" msgid="5158149987518342036">"LE_AUDIO"</string>
<string name="bluetooth_hearing_aid_profile_summary_connected" msgid="8191273236809964030">"ਸੁਣਨ ਦੇ ਸਾਧਨਾਂ ਨਾਲ ਕਨੈਕਟ ਕੀਤਾ ਗਿਆ"</string>
- <!-- no translation found for bluetooth_le_audio_profile_summary_connected (3162538609379333442) -->
- <skip />
+ <string name="bluetooth_le_audio_profile_summary_connected" msgid="3162538609379333442">"LE_AUDIO ਨਾਲ ਕਨੈਕਟ ਕੀਤਾ"</string>
<string name="bluetooth_a2dp_profile_summary_connected" msgid="7422607970115444153">"ਮੀਡੀਆ ਆਡੀਓ ਨਾਲ ਕਨੈਕਟ ਕੀਤਾ"</string>
<string name="bluetooth_headset_profile_summary_connected" msgid="2420981566026949688">"ਫ਼ੋਨ ਔਡੀਓ ਨਾਲ ਕਨੈਕਟ ਕੀਤਾ"</string>
<string name="bluetooth_opp_profile_summary_connected" msgid="2393521801478157362">"ਫਾਈਲ ਟ੍ਰਾਂਸਫ਼ਰ ਸਰਵਰ ਨਾਲ ਕਨੈਕਟ ਕੀਤਾ"</string>
@@ -144,8 +142,7 @@
<string name="bluetooth_opp_profile_summary_use_for" msgid="461981154387015457">"ਫਾਈਲ ਟ੍ਰਾਂਸਫਰ ਲਈ ਵਰਤੋ"</string>
<string name="bluetooth_hid_profile_summary_use_for" msgid="4289460627406490952">"ਇਨਪੁਟ ਲਈ ਵਰਤੋ"</string>
<string name="bluetooth_hearing_aid_profile_summary_use_for" msgid="7689393730163320483">"ਸੁਣਨ ਦੇ ਸਾਧਨਾਂ ਲਈ ਵਰਤੋ"</string>
- <!-- no translation found for bluetooth_le_audio_profile_summary_use_for (2778318636027348572) -->
- <skip />
+ <string name="bluetooth_le_audio_profile_summary_use_for" msgid="2778318636027348572">"LE_AUDIO ਲਈ ਵਰਤੋ"</string>
<string name="bluetooth_pairing_accept" msgid="2054232610815498004">"ਜੋੜਾਬੱਧ ਕਰੋ"</string>
<string name="bluetooth_pairing_accept_all_caps" msgid="2734383073450506220">"ਜੋੜਾਬੱਧ ਕਰੋ"</string>
<string name="bluetooth_pairing_decline" msgid="6483118841204885890">"ਰੱਦ ਕਰੋ"</string>
diff --git a/packages/SettingsLib/res/values-ru/strings.xml b/packages/SettingsLib/res/values-ru/strings.xml
index c158a14..14db225 100644
--- a/packages/SettingsLib/res/values-ru/strings.xml
+++ b/packages/SettingsLib/res/values-ru/strings.xml
@@ -554,7 +554,7 @@
<string name="zen_mode_duration_always_prompt_title" msgid="3212996860498119555">"Всегда спрашивать"</string>
<string name="zen_mode_forever" msgid="3339224497605461291">"Пока вы не отключите"</string>
<string name="time_unit_just_now" msgid="3006134267292728099">"Только что"</string>
- <string name="media_transfer_this_device_name" msgid="2716555073132169240">"Встроенный динамик"</string>
+ <string name="media_transfer_this_device_name" msgid="2716555073132169240">"Встроен. динамик"</string>
<string name="media_transfer_this_phone" msgid="7194341457812151531">"Этот смартфон"</string>
<string name="profile_connect_timeout_subtext" msgid="4043408193005851761">"Ошибка подключения. Выключите и снова включите устройство."</string>
<string name="media_transfer_wired_device_name" msgid="4447880899964056007">"Проводное аудиоустройство"</string>
diff --git a/packages/SettingsLib/res/values-vi/strings.xml b/packages/SettingsLib/res/values-vi/strings.xml
index 9eebd02..bd97cc5 100644
--- a/packages/SettingsLib/res/values-vi/strings.xml
+++ b/packages/SettingsLib/res/values-vi/strings.xml
@@ -582,7 +582,7 @@
<string name="user_setup_dialog_message" msgid="269931619868102841">"Đảm bảo người dùng có mặt để tự thiết lập không gian của mình trên thiết bị"</string>
<string name="user_setup_profile_dialog_message" msgid="4788197052296962620">"Thiết lập tiểu sử ngay bây giờ?"</string>
<string name="user_setup_button_setup_now" msgid="1708269547187760639">"Thiết lập ngay"</string>
- <string name="user_setup_button_setup_later" msgid="8712980133555493516">"Không phải bây giờ"</string>
+ <string name="user_setup_button_setup_later" msgid="8712980133555493516">"Để sau"</string>
<string name="user_add_user_type_title" msgid="551279664052914497">"Thêm"</string>
<string name="user_new_user_name" msgid="60979820612818840">"Người dùng mới"</string>
<string name="user_new_profile_name" msgid="2405500423304678841">"Tiểu sử mới"</string>
diff --git a/packages/SettingsLib/res/values-zh-rTW/strings.xml b/packages/SettingsLib/res/values-zh-rTW/strings.xml
index 5b74ab0..1a50189 100644
--- a/packages/SettingsLib/res/values-zh-rTW/strings.xml
+++ b/packages/SettingsLib/res/values-zh-rTW/strings.xml
@@ -122,11 +122,9 @@
<string name="bluetooth_profile_a2dp_high_quality" msgid="4739440941324792775">"HD 高解析音訊:<xliff:g id="CODEC_NAME">%1$s</xliff:g>"</string>
<string name="bluetooth_profile_a2dp_high_quality_unknown_codec" msgid="2477639096903834374">"HD 高解析音訊"</string>
<string name="bluetooth_profile_hearing_aid" msgid="58154575573984914">"助聽器"</string>
- <!-- no translation found for bluetooth_profile_le_audio (5158149987518342036) -->
- <skip />
+ <string name="bluetooth_profile_le_audio" msgid="5158149987518342036">"LE_AUDIO"</string>
<string name="bluetooth_hearing_aid_profile_summary_connected" msgid="8191273236809964030">"已連接到助聽器"</string>
- <!-- no translation found for bluetooth_le_audio_profile_summary_connected (3162538609379333442) -->
- <skip />
+ <string name="bluetooth_le_audio_profile_summary_connected" msgid="3162538609379333442">"已連上 LE_AUDIO"</string>
<string name="bluetooth_a2dp_profile_summary_connected" msgid="7422607970115444153">"連接至媒體音訊"</string>
<string name="bluetooth_headset_profile_summary_connected" msgid="2420981566026949688">"連接至電話音訊"</string>
<string name="bluetooth_opp_profile_summary_connected" msgid="2393521801478157362">"已連線到檔案傳輸伺服器"</string>
@@ -144,8 +142,7 @@
<string name="bluetooth_opp_profile_summary_use_for" msgid="461981154387015457">"用於傳輸檔案"</string>
<string name="bluetooth_hid_profile_summary_use_for" msgid="4289460627406490952">"用於輸入"</string>
<string name="bluetooth_hearing_aid_profile_summary_use_for" msgid="7689393730163320483">"用於助聽器"</string>
- <!-- no translation found for bluetooth_le_audio_profile_summary_use_for (2778318636027348572) -->
- <skip />
+ <string name="bluetooth_le_audio_profile_summary_use_for" msgid="2778318636027348572">"用於 LE_AUDIO"</string>
<string name="bluetooth_pairing_accept" msgid="2054232610815498004">"配對"</string>
<string name="bluetooth_pairing_accept_all_caps" msgid="2734383073450506220">"配對"</string>
<string name="bluetooth_pairing_decline" msgid="6483118841204885890">"取消"</string>
diff --git a/packages/SettingsLib/src/com/android/settingslib/bluetooth/CsipDeviceManager.java b/packages/SettingsLib/src/com/android/settingslib/bluetooth/CsipDeviceManager.java
index 1d29966..ed12e83 100644
--- a/packages/SettingsLib/src/com/android/settingslib/bluetooth/CsipDeviceManager.java
+++ b/packages/SettingsLib/src/com/android/settingslib/bluetooth/CsipDeviceManager.java
@@ -68,7 +68,7 @@
}
for (Map.Entry<Integer, ParcelUuid> entry: groupIdMap.entrySet()) {
- if (entry.getValue().equals(BluetoothUuid.BASE_UUID)) {
+ if (entry.getValue().equals(BluetoothUuid.CAP)) {
return entry.getKey();
}
}
diff --git a/packages/SettingsLib/src/com/android/settingslib/bluetooth/LocalBluetoothProfileManager.java b/packages/SettingsLib/src/com/android/settingslib/bluetooth/LocalBluetoothProfileManager.java
index 3347920..5e2f310 100644
--- a/packages/SettingsLib/src/com/android/settingslib/bluetooth/LocalBluetoothProfileManager.java
+++ b/packages/SettingsLib/src/com/android/settingslib/bluetooth/LocalBluetoothProfileManager.java
@@ -338,7 +338,7 @@
.getGroupUuidMapByDevice(cachedDevice.getDevice());
if (groupIdMap != null) {
for (Map.Entry<Integer, ParcelUuid> entry: groupIdMap.entrySet()) {
- if (entry.getValue().equals(BluetoothUuid.BASE_UUID)) {
+ if (entry.getValue().equals(BluetoothUuid.CAP)) {
cachedDevice.setGroupId(entry.getKey());
break;
}
diff --git a/packages/SettingsLib/src/com/android/settingslib/drawable/UserIconDrawable.java b/packages/SettingsLib/src/com/android/settingslib/drawable/UserIconDrawable.java
index 274696b..71bf9f6 100644
--- a/packages/SettingsLib/src/com/android/settingslib/drawable/UserIconDrawable.java
+++ b/packages/SettingsLib/src/com/android/settingslib/drawable/UserIconDrawable.java
@@ -40,6 +40,8 @@
import android.graphics.drawable.Drawable;
import android.os.UserHandle;
+import androidx.annotation.VisibleForTesting;
+
import com.android.settingslib.R;
/**
@@ -183,6 +185,20 @@
return setBadge(badge);
}
+ /**
+ * Sets the managed badge to this user icon if the device has a device owner.
+ */
+ public UserIconDrawable setBadgeIfManagedDevice(Context context) {
+ Drawable badge = null;
+ boolean deviceOwnerExists = context.getSystemService(DevicePolicyManager.class)
+ .getDeviceOwnerComponentOnAnyUser() != null;
+ if (deviceOwnerExists) {
+ badge = getDrawableForDisplayDensity(
+ context, com.android.internal.R.drawable.ic_corp_badge_case);
+ }
+ return setBadge(badge);
+ }
+
public void setBadgeRadius(float radius) {
mBadgeRadius = radius;
onBoundsChange(getBounds());
@@ -452,4 +468,24 @@
public void unscheduleDrawable(@NonNull Drawable who, @NonNull Runnable what) {
unscheduleSelf(what);
}
+
+ @VisibleForTesting
+ public Drawable getUserDrawable() {
+ return mUserDrawable;
+ }
+
+ @VisibleForTesting
+ public Bitmap getUserIcon() {
+ return mUserIcon;
+ }
+
+ @VisibleForTesting
+ public boolean isInvalidated() {
+ return mInvalidated;
+ }
+
+ @VisibleForTesting
+ public Drawable getBadge() {
+ return mBadge;
+ }
}
diff --git a/packages/SettingsLib/src/com/android/settingslib/inputmethod/OWNERS b/packages/SettingsLib/src/com/android/settingslib/inputmethod/OWNERS
index a0e28ba..e3e28cb 100644
--- a/packages/SettingsLib/src/com/android/settingslib/inputmethod/OWNERS
+++ b/packages/SettingsLib/src/com/android/settingslib/inputmethod/OWNERS
@@ -1,5 +1,3 @@
-# Default reviewers for this and subdirectories.
-takaoka@google.com
-yukawa@google.com
+# Bug component: 34867
-# Emergency approvers in case the above are not available
\ No newline at end of file
+include platform/frameworks/base:/services/core/java/com/android/server/inputmethod/OWNERS
\ No newline at end of file
diff --git a/packages/SettingsProvider/OWNERS b/packages/SettingsProvider/OWNERS
index 6c61d4b9..5ade971 100644
--- a/packages/SettingsProvider/OWNERS
+++ b/packages/SettingsProvider/OWNERS
@@ -2,6 +2,4 @@
hackbod@google.com
narayan@google.com
svetoslavganov@google.com
-schfan@google.com
-toddke@google.com
-patb@google.com
+include /PACKAGE_MANAGER_OWNERS
diff --git a/packages/Shell/AndroidManifest.xml b/packages/Shell/AndroidManifest.xml
index 41193e6a..ddf0289 100644
--- a/packages/Shell/AndroidManifest.xml
+++ b/packages/Shell/AndroidManifest.xml
@@ -424,6 +424,7 @@
<!-- Permissions required for CTS test - TunerTest -->
<uses-permission android:name="android.permission.ACCESS_TV_DESCRAMBLER" />
+ <uses-permission android:name="android.permission.ACCESS_TV_SHARED_FILTER" />
<uses-permission android:name="android.permission.ACCESS_TV_TUNER" />
<uses-permission android:name="android.permission.TUNER_RESOURCE_ACCESS" />
@@ -482,6 +483,7 @@
<!-- Permissions required for CTS test - CtsContactsProviderTestCases -->
<uses-permission android:name="android.contacts.permission.MANAGE_SIM_ACCOUNTS" />
+ <uses-permission android:name="android.permission.SET_DEFAULT_ACCOUNT_FOR_CONTACTS" />
<!-- Permissions required for CTS test - CarrierMessagingServiceWrapprTest -->
<uses-permission android:name="android.permission.BIND_CARRIER_SERVICES" />
diff --git a/packages/SystemUI/Android.bp b/packages/SystemUI/Android.bp
index 9569cf9..ae8439f 100644
--- a/packages/SystemUI/Android.bp
+++ b/packages/SystemUI/Android.bp
@@ -52,12 +52,18 @@
filegroup {
name: "ReleaseJavaFiles",
- srcs: ["src/com/android/systemui/flags/FeatureFlagManager.java"],
+ srcs: [
+ "src-release/**/*.kt",
+ "src-release/**/*.java",
+ ],
}
filegroup {
name: "DebugJavaFiles",
- srcs: ["src-debug/com/android/systemui/flags/FeatureFlagManager.java"],
+ srcs: [
+ "src-debug/**/*.kt",
+ "src-debug/**/*.java",
+ ],
}
android_library {
@@ -66,6 +72,8 @@
"src/**/*.kt",
"src/**/*.java",
"src/**/I*.aidl",
+ "src-release/**/*.kt",
+ "src-release/**/*.java",
],
product_variables: {
debuggable: {
@@ -171,6 +179,8 @@
"src/**/*.kt",
"src/**/*.java",
"src/**/I*.aidl",
+ "src-release/**/*.kt",
+ "src-release/**/*.java",
],
static_libs: [
"WifiTrackerLib",
diff --git a/packages/SystemUI/AndroidManifest.xml b/packages/SystemUI/AndroidManifest.xml
index 95ce423..c87ba65 100644
--- a/packages/SystemUI/AndroidManifest.xml
+++ b/packages/SystemUI/AndroidManifest.xml
@@ -217,7 +217,6 @@
<!-- notifications & DND access -->
<uses-permission android:name="android.permission.MANAGE_NOTIFICATIONS" />
- <uses-permission android:name="android.permission.GRANT_RUNTIME_PERMISSIONS" />
<uses-permission android:name="android.permission.REVOKE_RUNTIME_PERMISSIONS" />
<uses-permission android:name="android.permission.GET_RUNTIME_PERMISSIONS" />
@@ -612,21 +611,6 @@
</intent-filter>
</activity>
- <activity android:name=".egg.MLandActivity"
- android:theme="@android:style/Theme.Material.NoActionBar"
- android:exported="true"
- android:icon="@drawable/icon"
- android:label="@string/mland"
- android:launchMode="singleInstance"
- android:screenOrientation="locked"
- android:process=":sweetsweetdesserts"
- android:excludeFromRecents="true">
- <intent-filter>
- <action android:name="android.intent.action.MAIN"/>
- <category android:name="android.intent.category.DEFAULT" />
- </intent-filter>
- </activity>
-
<!-- People Space UI Screen -->
<activity android:name=".people.PeopleSpaceActivity"
android:label="@string/people_tile_title"
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 c2b3608..669a054 100644
--- a/packages/SystemUI/animation/src/com/android/systemui/animation/DialogLaunchAnimator.kt
+++ b/packages/SystemUI/animation/src/com/android/systemui/animation/DialogLaunchAnimator.kt
@@ -21,11 +21,16 @@
import android.graphics.Color
import android.os.Looper
import android.util.Log
+import android.view.GhostView
import android.view.Gravity
import android.view.View
import android.view.ViewGroup
-import android.view.ViewTreeObserver
+import android.view.ViewTreeObserver.OnPreDrawListener
+import android.view.WindowInsets
import android.view.WindowManager
+import android.view.WindowManager.LayoutParams.FLAG_LAYOUT_INSET_DECOR
+import android.view.WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN
+import android.view.WindowManagerPolicyConstants
import android.widget.FrameLayout
private const val TAG = "DialogLaunchAnimator"
@@ -221,10 +226,12 @@
private var isDismissing = false
private var dismissRequested = false
- private var drawHostDialog = false
var ignoreNextCallToHide = false
var exitAnimationDisabled = false
+ private var isTouchSurfaceGhostDrawn = false
+ private var isOriginalDialogViewLaidOut = false
+
fun start() {
// Show the host (fullscreen) dialog, to which we will add the stolen dialog view.
hostDialog.show()
@@ -252,19 +259,76 @@
WindowManager.LayoutParams.MATCH_PARENT
)
- // Prevent the host dialog from drawing until the animation starts.
- hostDialogRoot.viewTreeObserver.addOnPreDrawListener(
- object : ViewTreeObserver.OnPreDrawListener {
- override fun onPreDraw(): Boolean {
- if (drawHostDialog) {
- hostDialogRoot.viewTreeObserver.removeOnPreDrawListener(this)
- return true
- }
+ // If we are using gesture navigation, then we can overlay the navigation/task bars with
+ // the host dialog.
+ val navigationMode = context.resources.getInteger(
+ com.android.internal.R.integer.config_navBarInteractionMode)
+ if (navigationMode == WindowManagerPolicyConstants.NAV_BAR_MODE_GESTURAL) {
+ window.attributes.fitInsetsTypes = window.attributes.fitInsetsTypes and
+ WindowInsets.Type.navigationBars().inv()
+ window.addFlags(FLAG_LAYOUT_IN_SCREEN or FLAG_LAYOUT_INSET_DECOR)
+ window.setDecorFitsSystemWindows(false)
+ }
- return false
- }
+ // Disable the dim. We will enable it once we start the animation.
+ window.clearFlags(WindowManager.LayoutParams.FLAG_DIM_BEHIND)
+
+ // Add a temporary touch surface ghost as soon as the window is ready to draw. This
+ // temporary ghost will be drawn together with the touch surface, but in the host dialog
+ // window. Once it is drawn, we will make the touch surface invisible, and then start the
+ // animation. We do all this synchronization to avoid flicker that would occur if we made
+ // the touch surface invisible too early (before its ghost is drawn), leading to one or more
+ // frames with a hole instead of the touch surface (or its ghost).
+ hostDialogRoot.viewTreeObserver.addOnPreDrawListener(object : OnPreDrawListener {
+ override fun onPreDraw(): Boolean {
+ hostDialogRoot.viewTreeObserver.removeOnPreDrawListener(this)
+ addTemporaryTouchSurfaceGhost()
+ return true
}
- )
+ })
+ hostDialogRoot.invalidate()
+ }
+
+ private fun addTemporaryTouchSurfaceGhost() {
+ // Create a ghost of the touch surface (which will make the touch surface invisible) and add
+ // it to the host dialog. We will wait for this ghost to be drawn before starting the
+ // animation.
+ val ghost = GhostView.addGhost(touchSurface, hostDialogRoot)
+
+ // The ghost of the touch surface was just created, so the touch surface was made invisible.
+ // We make it visible again until the ghost is actually drawn.
+ touchSurface.visibility = View.VISIBLE
+
+ // Wait for the ghost to be drawn before continuing.
+ ghost.viewTreeObserver.addOnPreDrawListener(object : OnPreDrawListener {
+ override fun onPreDraw(): Boolean {
+ ghost.viewTreeObserver.removeOnPreDrawListener(this)
+ onTouchSurfaceGhostDrawn()
+ return true
+ }
+ })
+ ghost.invalidate()
+ }
+
+ private fun onTouchSurfaceGhostDrawn() {
+ // Make the touch surface invisible and make sure that it stays invisible as long as the
+ // dialog is shown or animating.
+ touchSurface.visibility = View.INVISIBLE
+ if (touchSurface is LaunchableView) {
+ touchSurface.setShouldBlockVisibilityChanges(true)
+ }
+
+ // Add a pre draw listener to (maybe) start the animation once the touch surface is
+ // actually invisible.
+ touchSurface.viewTreeObserver.addOnPreDrawListener(object : OnPreDrawListener {
+ override fun onPreDraw(): Boolean {
+ touchSurface.viewTreeObserver.removeOnPreDrawListener(this)
+ isTouchSurfaceGhostDrawn = true
+ maybeStartLaunchAnimation()
+ return true
+ }
+ })
+ touchSurface.invalidate()
}
/** Get the content view of [originalDialog] and pass it to [then]. */
@@ -276,7 +340,7 @@
?: throw IllegalStateException("Dialog does not have any android.R.id.content view")
androidContent.viewTreeObserver.addOnPreDrawListener(
- object : ViewTreeObserver.OnPreDrawListener {
+ object : OnPreDrawListener {
override fun onPreDraw(): Boolean {
if (androidContent.childCount == 1) {
androidContent.viewTreeObserver.removeOnPreDrawListener(this)
@@ -354,32 +418,47 @@
oldBottom: Int
) {
dialogView.removeOnLayoutChangeListener(this)
- startAnimation(
- isLaunching = true,
- onLaunchAnimationStart = { drawHostDialog = true },
- onLaunchAnimationEnd = {
- touchSurface.setTag(R.id.launch_animation_running, null)
- // We hide the touch surface when the dialog is showing. We will make this
- // view visible again when dismissing the dialog.
- // TODO(b/193634619): Provide an easy way for views to check if they should
- // be hidden because of a dialog launch so that they don't override this
- // visibility when updating/refreshing itself.
- touchSurface.visibility = View.INVISIBLE
-
- isLaunching = false
-
- // dismiss was called during the animation, dismiss again now to actually
- // dismiss.
- if (dismissRequested) {
- hostDialog.dismiss()
- }
- }
- )
+ isOriginalDialogViewLaidOut = true
+ maybeStartLaunchAnimation()
}
})
}
+ private fun maybeStartLaunchAnimation() {
+ if (!isTouchSurfaceGhostDrawn || !isOriginalDialogViewLaidOut) {
+ return
+ }
+
+ // Show the background dim.
+ hostDialog.window.addFlags(WindowManager.LayoutParams.FLAG_DIM_BEHIND)
+
+ startAnimation(
+ isLaunching = true,
+ onLaunchAnimationStart = {
+ // Remove the temporary ghost. Another ghost (that ghosts only the touch surface
+ // content, and not its background) will be added right after this and will be
+ // animated.
+ GhostView.removeGhost(touchSurface)
+ },
+ onLaunchAnimationEnd = {
+ touchSurface.setTag(R.id.launch_animation_running, null)
+
+ // We hide the touch surface when the dialog is showing. We will make this
+ // view visible again when dismissing the dialog.
+ touchSurface.visibility = View.INVISIBLE
+
+ isLaunching = false
+
+ // dismiss was called during the animation, dismiss again now to actually
+ // dismiss.
+ if (dismissRequested) {
+ hostDialog.dismiss()
+ }
+ }
+ )
+ }
+
private fun onHostDialogDismissed(actualDismiss: () -> Unit) {
if (Looper.myLooper() != Looper.getMainLooper()) {
context.mainExecutor.execute { onHostDialogDismissed(actualDismiss) }
@@ -417,6 +496,11 @@
if (!shouldAnimateDialogIntoView()) {
Log.i(TAG, "Skipping animation of dialog into the touch surface")
+ // Make sure we allow the touch surface to change its visibility again.
+ if (touchSurface is LaunchableView) {
+ touchSurface.setShouldBlockVisibilityChanges(false)
+ }
+
// If the view is invisible it's probably because of us, so we make it visible again.
if (touchSurface.visibility == View.INVISIBLE) {
touchSurface.visibility = View.VISIBLE
@@ -434,10 +518,33 @@
hostDialog.window.clearFlags(WindowManager.LayoutParams.FLAG_DIM_BEHIND)
},
onLaunchAnimationEnd = {
+ // Make sure we allow the touch surface to change its visibility again.
+ if (touchSurface is LaunchableView) {
+ touchSurface.setShouldBlockVisibilityChanges(false)
+ }
+
touchSurface.visibility = View.VISIBLE
originalDialogView!!.visibility = View.INVISIBLE
- dismissDialogs(true /* instantDismiss */)
- onDialogDismissed(this@DialogLaunchAnimation)
+
+ // The animated ghost was just removed. We create a temporary ghost that will be
+ // removed only once we draw the touch surface, to avoid flickering that would
+ // happen when removing the ghost too early (before the touch surface is drawn).
+ GhostView.addGhost(touchSurface, hostDialogRoot)
+
+ touchSurface.viewTreeObserver.addOnPreDrawListener(object : OnPreDrawListener {
+ override fun onPreDraw(): Boolean {
+ touchSurface.viewTreeObserver.removeOnPreDrawListener(this)
+
+ // Now that the touch surface was drawn, we can remove the temporary ghost
+ // and instantly dismiss the dialog.
+ GhostView.removeGhost(touchSurface)
+ dismissDialogs(true /* instantDismiss */)
+ onDialogDismissed(this@DialogLaunchAnimation)
+
+ return true
+ }
+ })
+ touchSurface.invalidate()
}
)
}
@@ -472,10 +579,13 @@
}
override fun onLaunchAnimationStart(isExpandingFullyAbove: Boolean) {
+ // During launch, onLaunchAnimationStart will be used to remove the temporary touch
+ // surface ghost so it is important to call this before calling
+ // onLaunchAnimationStart on the controller (which will create its own ghost).
+ onLaunchAnimationStart()
+
startViewController.onLaunchAnimationStart(isExpandingFullyAbove)
endViewController.onLaunchAnimationStart(isExpandingFullyAbove)
-
- onLaunchAnimationStart()
}
override fun onLaunchAnimationEnd(isExpandingFullyAbove: Boolean) {
diff --git a/packages/SystemUI/animation/src/com/android/systemui/animation/LaunchableView.kt b/packages/SystemUI/animation/src/com/android/systemui/animation/LaunchableView.kt
new file mode 100644
index 0000000..80a3eb8
--- /dev/null
+++ b/packages/SystemUI/animation/src/com/android/systemui/animation/LaunchableView.kt
@@ -0,0 +1,30 @@
+/*
+ * Copyright (C) 2021 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.animation
+
+/** A view that can expand/launch into an app or a dialog. */
+interface LaunchableView {
+ /**
+ * Set whether this view should block/prevent all visibility changes. This ensures that this
+ * view remains invisible during the launch animation given that it is ghosted and already drawn
+ * somewhere else.
+ *
+ * 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.
+ */
+ fun setShouldBlockVisibilityChanges(block: Boolean)
+}
\ No newline at end of file
diff --git a/packages/SystemUI/plugin/bcsmartspace/src/com/android/systemui/plugins/BcSmartspaceDataPlugin.java b/packages/SystemUI/plugin/bcsmartspace/src/com/android/systemui/plugins/BcSmartspaceDataPlugin.java
index 989010e..a16f5cd 100644
--- a/packages/SystemUI/plugin/bcsmartspace/src/com/android/systemui/plugins/BcSmartspaceDataPlugin.java
+++ b/packages/SystemUI/plugin/bcsmartspace/src/com/android/systemui/plugins/BcSmartspaceDataPlugin.java
@@ -123,18 +123,18 @@
/** Interface for launching Intents, which can differ on the lockscreen */
interface IntentStarter {
- default void startFromAction(SmartspaceAction action, View v) {
+ default void startFromAction(SmartspaceAction action, View v, boolean showOnLockscreen) {
if (action.getIntent() != null) {
- startIntent(v, action.getIntent());
+ startIntent(v, action.getIntent(), showOnLockscreen);
} else if (action.getPendingIntent() != null) {
- startPendingIntent(action.getPendingIntent());
+ startPendingIntent(action.getPendingIntent(), showOnLockscreen);
}
}
/** Start the intent */
- void startIntent(View v, Intent i);
+ void startIntent(View v, Intent i, boolean showOnLockscreen);
/** Start the PendingIntent */
- void startPendingIntent(PendingIntent pi);
+ void startPendingIntent(PendingIntent pi, boolean showOnLockscreen);
}
}
diff --git a/packages/SystemUI/plugin/src/com/android/systemui/plugins/qs/QS.java b/packages/SystemUI/plugin/src/com/android/systemui/plugins/qs/QS.java
index 757dc2e..b83ea4a 100644
--- a/packages/SystemUI/plugin/src/com/android/systemui/plugins/qs/QS.java
+++ b/packages/SystemUI/plugin/src/com/android/systemui/plugins/qs/QS.java
@@ -55,13 +55,14 @@
/**
* Asks QS to update its presentation, according to {@code NotificationPanelViewController}.
- *
* @param qsExpansionFraction How much each UI element in QS should be expanded (QQS to QS.)
* @param panelExpansionFraction Whats the expansion of the whole shade.
* @param headerTranslation How much we should vertically translate QS.
+ * @param squishinessFraction Fraction that affects tile height. 0 when collapsed,
+ * 1 when expanded.
*/
void setQsExpansion(float qsExpansionFraction, float panelExpansionFraction,
- float headerTranslation);
+ float headerTranslation, float squishinessFraction);
void setHeaderListening(boolean listening);
void notifyCustomizeChanged();
void setContainerController(QSContainerController controller);
diff --git a/packages/SystemUI/proguard.flags b/packages/SystemUI/proguard.flags
index 6114728..a110413 100644
--- a/packages/SystemUI/proguard.flags
+++ b/packages/SystemUI/proguard.flags
@@ -1,20 +1,3 @@
--keep class com.android.systemui.navigationbar.buttons.KeyButtonView {
- public float getDrawingAlpha();
- public void setDrawingAlpha(float);
-}
-
--keep class com.android.systemui.navigationbar.buttons.KeyButtonRipple {
- public float getGlowAlpha();
- public float getGlowScale();
- public void setGlowAlpha(float);
- public void setGlowScale(float);
-}
-
--keep class com.android.systemui.settings.brightness.BrightnessSliderView {
- public float getSliderScaleY();
- public void setSliderScaleY(float);
-}
-
-keep class com.android.systemui.recents.OverviewProxyRecentsImpl
-keep class com.android.systemui.statusbar.car.CarStatusBar
-keep class com.android.systemui.statusbar.phone.StatusBar
diff --git a/packages/SystemUI/res-keyguard/drawable/bubble_manage_user_education_bg.xml b/packages/SystemUI/res-keyguard/drawable/bubble_manage_user_education_bg.xml
deleted file mode 100644
index 64db25b..0000000
--- a/packages/SystemUI/res-keyguard/drawable/bubble_manage_user_education_bg.xml
+++ /dev/null
@@ -1,21 +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.
- -->
-<shape xmlns:android="http://schemas.android.com/apk/res/android"
- android:shape="rectangle">
- <solid android:color="?android:attr/colorAccent"/>
- <corners
- android:radius="?android:attr/dialogCornerRadius" />
-</shape>
\ No newline at end of file
diff --git a/packages/SystemUI/res-keyguard/drawable/circle_white.xml b/packages/SystemUI/res-keyguard/drawable/circle_white.xml
deleted file mode 100644
index d1b2097..0000000
--- a/packages/SystemUI/res-keyguard/drawable/circle_white.xml
+++ /dev/null
@@ -1,19 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- 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.
--->
-<shape xmlns:android="http://schemas.android.com/apk/res/android"
- android:shape="oval">
- <solid android:color="#33FFFFFF" />
-</shape>
\ No newline at end of file
diff --git a/packages/SystemUI/res-keyguard/drawable/face_auth_wallpaper.png b/packages/SystemUI/res-keyguard/drawable/face_auth_wallpaper.png
deleted file mode 100644
index b907f4e..0000000
--- a/packages/SystemUI/res-keyguard/drawable/face_auth_wallpaper.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res-keyguard/drawable/ic_done_black_24dp.xml b/packages/SystemUI/res-keyguard/drawable/ic_done_black_24dp.xml
deleted file mode 100644
index 5026f07..0000000
--- a/packages/SystemUI/res-keyguard/drawable/ic_done_black_24dp.xml
+++ /dev/null
@@ -1,25 +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
- -->
-
-<vector xmlns:android="http://schemas.android.com/apk/res/android"
- android:width="24dp"
- android:height="24dp"
- android:viewportWidth="24.0"
- android:viewportHeight="24.0">
- <path
- android:fillColor="#FF000000"
- android:pathData="M9,16.2l-3.5,-3.5a0.984,0.984 0,0 0,-1.4 0,0.984 0.984,0 0,0 0,1.4l4.19,4.19c0.39,0.39 1.02,0.39 1.41,0L20.3,7.7a0.984,0.984 0,0 0,0 -1.4,0.984 0.984,0 0,0 -1.4,0L9,16.2z"/>
-</vector>
diff --git a/packages/SystemUI/res-keyguard/drawable/ripple_drawable_pin.xml b/packages/SystemUI/res-keyguard/drawable/ripple_drawable_pin.xml
deleted file mode 100644
index 51c442a..0000000
--- a/packages/SystemUI/res-keyguard/drawable/ripple_drawable_pin.xml
+++ /dev/null
@@ -1,20 +0,0 @@
-<?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
- -->
-
-<ripple xmlns:android="http://schemas.android.com/apk/res/android"
- android:color="?android:attr/colorControlHighlight"
- android:radius="40dp"/>
diff --git a/packages/SystemUI/res-keyguard/drawable/super_lock_icon.xml b/packages/SystemUI/res-keyguard/drawable/super_lock_icon.xml
index 7f0f68f..c58e2e3 100644
--- a/packages/SystemUI/res-keyguard/drawable/super_lock_icon.xml
+++ b/packages/SystemUI/res-keyguard/drawable/super_lock_icon.xml
@@ -37,7 +37,7 @@
android:id="@+id/locked_fp"
android:state_middle="true"
android:state_single="false"
- android:drawable="@drawable/ic_fingerprint" />
+ android:drawable="@drawable/ic_kg_fingerprint" />
<item
android:id="@+id/unlocked"
diff --git a/packages/SystemUI/res-keyguard/values-land/integers.xml b/packages/SystemUI/res-keyguard/values-land/integers.xml
deleted file mode 100644
index 0739c3a..0000000
--- a/packages/SystemUI/res-keyguard/values-land/integers.xml
+++ /dev/null
@@ -1,23 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
-/*
-** Copyright 2012, 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>
- <!-- Gravity to make KeyguardSelectorView work in multiple orientations
- 0x13 == "left|center_vertical" -->
- <integer name="kg_selector_gravity">0x13</integer>
-</resources>
diff --git a/packages/SystemUI/res-keyguard/values-port/bools.xml b/packages/SystemUI/res-keyguard/values-port/bools.xml
deleted file mode 100644
index fdb8ebc..0000000
--- a/packages/SystemUI/res-keyguard/values-port/bools.xml
+++ /dev/null
@@ -1,19 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2012 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>
- <bool name="kg_sim_puk_account_full_screen">true</bool>
-</resources>
diff --git a/packages/SystemUI/res-keyguard/values-port/integers.xml b/packages/SystemUI/res-keyguard/values-port/integers.xml
deleted file mode 100644
index ef7e4da..0000000
--- a/packages/SystemUI/res-keyguard/values-port/integers.xml
+++ /dev/null
@@ -1,23 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
-/*
-** Copyright 2012, 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>
- <!-- Gravity to make KeyguardSelectorView work in multiple orientations
- 0x31 == "top|center_horizontal" -->
- <integer name="kg_selector_gravity">0x31</integer>
-</resources>
\ No newline at end of file
diff --git a/packages/SystemUI/res-keyguard/values-sw600dp-land/dimens.xml b/packages/SystemUI/res-keyguard/values-sw600dp-land/dimens.xml
index d816b3a..17765b5 100644
--- a/packages/SystemUI/res-keyguard/values-sw600dp-land/dimens.xml
+++ b/packages/SystemUI/res-keyguard/values-sw600dp-land/dimens.xml
@@ -23,6 +23,6 @@
<dimen name="widget_big_font_size">88dp</dimen>
<dimen name="qs_header_system_icons_area_height">0dp</dimen>
- <dimen name="qs_panel_padding_top">0dp</dimen>
+ <dimen name="qs_panel_padding_top">@dimen/qqs_layout_margin_top</dimen>
</resources>
\ No newline at end of file
diff --git a/packages/SystemUI/res-keyguard/values-sw600dp/bools.xml b/packages/SystemUI/res-keyguard/values-sw600dp/bools.xml
deleted file mode 100644
index 654821a..0000000
--- a/packages/SystemUI/res-keyguard/values-sw600dp/bools.xml
+++ /dev/null
@@ -1,19 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2011 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>
- <bool name="kg_sim_puk_account_full_screen">false</bool>
-</resources>
diff --git a/packages/SystemUI/res-keyguard/values/alias.xml b/packages/SystemUI/res-keyguard/values/alias.xml
index 6d49b1f..1e1d29a 100644
--- a/packages/SystemUI/res-keyguard/values/alias.xml
+++ b/packages/SystemUI/res-keyguard/values/alias.xml
@@ -28,9 +28,6 @@
<!-- Alias used to reference framework configuration for screen rotation. -->
<item type="bool" name="config_enableLockScreenRotation">@*android:bool/config_enableLockScreenRotation</item>
- <!-- Alias used to reference framework activity duration. -->
- <item type="integer" name="config_activityDefaultDur">@*android:integer/config_activityDefaultDur</item>
-
<!-- Alias used to reference one of two possible layouts in keyguard. -->
<item type="layout" name="keyguard_eca">@layout/keyguard_emergency_carrier_area</item>
</resources>
diff --git a/packages/SystemUI/res-keyguard/values/colors.xml b/packages/SystemUI/res-keyguard/values/colors.xml
index 74ee7ff..7a849eb 100644
--- a/packages/SystemUI/res-keyguard/values/colors.xml
+++ b/packages/SystemUI/res-keyguard/values/colors.xml
@@ -19,6 +19,4 @@
<color name="bubbleHourHandColor">#C97343</color>
<!-- Default color for minute hand of Bubble clock. -->
<color name="bubbleMinuteHandColor">#F5C983</color>
- <!-- Accent color for Typographic clock. -->
- <color name="typeClockAccentColor">#F5C983</color>
</resources>
diff --git a/packages/SystemUI/res-keyguard/values/dimens.xml b/packages/SystemUI/res-keyguard/values/dimens.xml
index e854b02..89dd741 100644
--- a/packages/SystemUI/res-keyguard/values/dimens.xml
+++ b/packages/SystemUI/res-keyguard/values/dimens.xml
@@ -31,7 +31,6 @@
<!-- Max Height of the sliding KeyguardSecurityContainer
(includes 2x keyguard_security_view_top_margin) -->
- <dimen name="keyguard_security_max_height">450dp</dimen>
<!-- pin/password field max height -->
<dimen name="keyguard_password_height">80dp</dimen>
@@ -57,7 +56,6 @@
<!-- Clock without header -->
<dimen name="widget_big_font_size">54dp</dimen>
<dimen name="bottom_text_spacing_digital">0dp</dimen>
- <dimen name="title_clock_padding">4dp</dimen>
<!-- Clock with header -->
<dimen name="widget_small_font_size">@dimen/widget_title_font_size</dimen>
<dimen name="widget_vertical_padding">5dp</dimen>
@@ -68,10 +66,8 @@
<dimen name="widget_icon_size">18dp</dimen>
<dimen name="widget_icon_padding">8dp</dimen>
<!-- Notification shelf padding when dark -->
- <dimen name="widget_bottom_separator_padding">-6dp</dimen>
<!-- The y translation to apply at the start in appear animations. -->
- <dimen name="appear_y_translation_start">32dp</dimen>
<!-- The size of the dots in the PIN unlock method. -->
<dimen name="password_dot_size">9dp</dimen>
@@ -82,7 +78,6 @@
<dimen name="password_char_padding">8dp</dimen>
<!-- The vertical margin between the date and the owner info. -->
- <dimen name="date_owner_info_margin">4dp</dimen>
<!-- The translation for disappearing security views after having solved them. -->
<dimen name="disappear_y_translation">-32dp</dimen>
diff --git a/packages/SystemUI/res-keyguard/values/donottranslate.xml b/packages/SystemUI/res-keyguard/values/donottranslate.xml
index 052d329..e677797 100644
--- a/packages/SystemUI/res-keyguard/values/donottranslate.xml
+++ b/packages/SystemUI/res-keyguard/values/donottranslate.xml
@@ -16,7 +16,6 @@
<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<!-- Skeleton string format for displaying the date. -->
- <string name="abbrev_wday_month_day_no_year">EEEEMMMMd</string>
<!-- Skeleton string format for displaying the date when an alarm is set. -->
<string name="abbrev_wday_month_day_no_year_alarm">EEEMMMd</string>
diff --git a/packages/SystemUI/res-keyguard/values/strings.xml b/packages/SystemUI/res-keyguard/values/strings.xml
index 20ff424..4fc38a8 100644
--- a/packages/SystemUI/res-keyguard/values/strings.xml
+++ b/packages/SystemUI/res-keyguard/values/strings.xml
@@ -18,32 +18,6 @@
*/
-->
<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <!-- App label in the manifest -->
- <string name="app_name">Keyguard</string>
- <!-- Instructions telling the user to enter their SIM PIN to unlock the keyguard.
- Displayed in one line in a large font. -->
- <string name="keyguard_password_enter_pin_code">Type PIN code</string>
-
- <!-- Instructions telling the user to enter their SIM PUK to unlock the keyguard.
- Displayed in one line in a large font. -->
- <string name="keyguard_password_enter_puk_code">Type SIM PUK and new PIN code</string>
-
- <!-- Prompt to enter SIM PUK in Edit Text Box in unlock screen -->
- <string name="keyguard_password_enter_puk_prompt">SIM PUK code</string>
- <!-- Prompt to enter New SIM PIN in Edit Text Box in unlock screen -->
- <string name="keyguard_password_enter_pin_prompt">New SIM PIN code</string>
-
- <!-- Displayed as hint in passwordEntry EditText on PasswordUnlockScreen [CHAR LIMIT=30]-->
- <string name="keyguard_password_entry_touch_hint"><font size="17">Touch to type password</font></string>
-
- <!-- Instructions telling the user to enter their text password to unlock the keyguard.
- Displayed in one line in a large font. -->
- <string name="keyguard_password_enter_password_code">Type password to unlock</string>
-
- <!-- Instructions telling the user to enter their PIN password to unlock the keyguard.
- Displayed in one line in a large font. -->
- <string name="keyguard_password_enter_pin_password_code">Type PIN to unlock</string>
-
<!-- Instructions telling the user to enter their PIN password to unlock the keyguard [CHAR LIMIT=30] -->
<string name="keyguard_enter_your_pin">Enter your PIN</string>
@@ -53,10 +27,6 @@
<!-- Instructions telling the user to enter their text password to unlock the keyguard [CHAR LIMIT=30] -->
<string name="keyguard_enter_your_password">Enter your password</string>
- <!-- Instructions telling the user that they entered the wrong pin while trying
- to unlock the keyguard. Displayed in one line in a large font. -->
- <string name="keyguard_password_wrong_pin_code">Incorrect PIN code.</string>
-
<!-- Shown in the lock screen when there is SIM card IO error. -->
<string name="keyguard_sim_error_message_short">Invalid Card.</string>
@@ -82,10 +52,6 @@
<!-- When the lock screen is showing and the phone plugged in, and the defend mode is triggered, say that charging is temporarily limited. -->
<string name="keyguard_plugged_in_charging_limited"><xliff:g id="percentage">%s</xliff:g> • Charging temporarily limited</string>
- <!-- When the lock screen is showing and the battery is low, warn user to plug
- in the phone soon. -->
- <string name="keyguard_low_battery">Connect your charger.</string>
-
<!-- On the keyguard screen, when pattern lock is disabled, only tell them to press menu to unlock. This is shown in small font at the bottom. -->
<string name="keyguard_instructions_when_pattern_disabled">Press Menu to unlock.</string>
@@ -132,9 +98,6 @@
<!-- Accessibility description of the SIM PUK password view. [CHAR_LIMIT=none] -->
<string name="keyguard_accessibility_sim_puk_area">SIM PUK area</string>
- <!-- Accessibility description for the text view that indicates when the next alarm is set (not shown on screen). [CHAR_LIMIT=none] -->
- <string name="keyguard_accessibility_next_alarm">Next alarm set for <xliff:g id="alarm" example="Fri 8:30 AM">%1$s</xliff:g></string>
-
<!-- KeyguardPinView - accessibility support --><skip />
<!-- Description of the Delete button in a KeyboardView. [CHAR LIMIT=NONE] -->
<string name="keyboardview_keycode_delete">Delete</string>
@@ -147,8 +110,6 @@
<!-- Description of the Enter button in a KeyboardView. [CHAR LIMIT=NONE] -->
<string name="keyboardview_keycode_enter">Enter</string>
- <!-- Message shown in pattern unlock after some number of unsuccessful attempts -->
- <string name="kg_forgot_pattern_button_text">Forgot Pattern</string>
<!-- Message shown when user enters wrong pattern -->
<string name="kg_wrong_pattern">Wrong pattern</string>
<!-- Message shown when user enters wrong password -->
@@ -160,18 +121,12 @@
<item quantity="one">Try again in 1 second.</item>
<item quantity="other">Try again in <xliff:g id="number">%d</xliff:g> seconds.</item>
</plurals>
- <!-- Instructions for using the pattern unlock screen -->
- <string name="kg_pattern_instructions">Draw your pattern</string>
<!-- Instructions for using the SIM PIN unlock screen -->
<string name="kg_sim_pin_instructions">Enter SIM PIN.</string>
<!-- Instructions for using the SIM PIN unlock screen when there's more than one SIM -->
<string name="kg_sim_pin_instructions_multi">Enter SIM PIN for \"<xliff:g id="carrier" example="CARD 1">%1$s</xliff:g>\".</string>
<!-- Instructions for disabling eSIM carrier to unlock the phone with embedded SIM. This message follows the original SIM PIN/PUK message of device without embedded SIM. -->
<string name="kg_sim_lock_esim_instructions"><xliff:g id="previous_msg" example="Enter SIM PIN.">%1$s</xliff:g> Disable eSIM to use device without mobile service.</string>
- <!-- Instructions for using the PIN unlock screen -->
- <string name="kg_pin_instructions">Enter PIN</string>
- <!-- Instructions for using the password unlock screen -->
- <string name="kg_password_instructions">Enter Password</string>
<!-- Hint shown in the PUK screen that asks the user to enter the PUK code given to them by their provider -->
<string name="kg_puk_enter_puk_hint">SIM is now disabled. Enter PUK code to continue. Contact carrier for details.</string>
<!-- Hint shown when there are multiple SIMs in the device to ask the user to enter the PUK code given to them by their provider -->
@@ -186,10 +141,6 @@
<string name="kg_invalid_sim_pin_hint">Type a PIN that is 4 to 8 numbers.</string>
<!-- Message shown when the user enters an invalid PUK code in the PUK screen -->
<string name="kg_invalid_sim_puk_hint">PUK code should be 8 numbers or more.</string>
- <!-- Message shown when the user enters an invalid PUK code -->
- <string name="kg_invalid_puk">Re-enter the correct PUK code. Repeated attempts will permanently disable the SIM.</string>
- <!-- Message shown when the user exceeds the maximum number of pattern attempts -->
- <string name="kg_login_too_many_attempts">Too many pattern attempts</string>
<!-- Message shown in dialog when max number of attempts are reached for PIN screen of keyguard -->
<string name="kg_too_many_failed_pin_attempts_dialog_message">
You have incorrectly typed your PIN <xliff:g id="number">%1$d</xliff:g> times.
@@ -230,13 +181,6 @@
<!-- Instructions telling the user that the operation to unlock the keyguard
with PUK failed. Displayed in one line in a large font. -->
<string name="kg_password_puk_failed">SIM PUK operation failed!</string>
- <!-- Notification telling the user that the PIN1 they entered is valid -->
- <string name="kg_pin_accepted">Code Accepted!</string>
-
- <!-- On the keyguard screen, it shows the carrier the phone is connected to.
- This is displayed if the phone is not connected to a carrier.-->
- <string name="keyguard_carrier_default">No service.</string>
-
<!-- Content description of the switch input method button for accessibility (not shown on the screen). [CHAR LIMIT=NONE] -->
<string name="accessibility_ime_switch_button" msgid="5032926134740456424">Switch input method</string>
@@ -261,15 +205,6 @@
<!-- An explanation text that the password needs to be entered since the user hasn't used strong authentication since quite some time. [CHAR LIMIT=80] -->
<string name="kg_prompt_reason_timeout_password">Password required for additional security</string>
- <!-- An explanation text that the pattern needs to be solved since profiles have just been switched. [CHAR LIMIT=80] -->
- <string name="kg_prompt_reason_switch_profiles_pattern">Pattern required when you switch profiles</string>
-
- <!-- An explanation text that the pin needs to be entered since profiles have just been switched. [CHAR LIMIT=80] -->
- <string name="kg_prompt_reason_switch_profiles_pin">PIN required when you switch profiles</string>
-
- <!-- An explanation text that the password needs to be entered since profiles have just been switched. [CHAR LIMIT=80] -->
- <string name="kg_prompt_reason_switch_profiles_password">Password required when you switch profiles</string>
-
<!-- An explanation text that the credential needs to be entered because a device admin has
locked the device. [CHAR LIMIT=80] -->
<string name="kg_prompt_reason_device_admin">Device locked by admin</string>
@@ -278,24 +213,6 @@
the force lock button. [CHAR LIMIT=80] -->
<string name="kg_prompt_reason_user_request">Device was locked manually</string>
- <!-- An explanation text that the pattern needs to be solved since it hasn't been solved in a while. [CHAR LIMIT=80]-->
- <plurals name="kg_prompt_reason_time_pattern">
- <item quantity="one">Device hasn\'t been unlocked for <xliff:g id="number">%d</xliff:g> hour. Confirm pattern.</item>
- <item quantity="other">Device hasn\'t been unlocked for <xliff:g id="number">%d</xliff:g> hours. Confirm pattern.</item>
- </plurals>
-
- <!-- An explanation text that the pin needs to be entered since it hasn't been entered in a while. [CHAR LIMIT=80]-->
- <plurals name="kg_prompt_reason_time_pin">
- <item quantity="one">Device hasn\'t been unlocked for <xliff:g id="number">%d</xliff:g> hour. Confirm PIN.</item>
- <item quantity="other">Device hasn\'t been unlocked for <xliff:g id="number">%d</xliff:g> hours. Confirm PIN.</item>
- </plurals>
-
- <!-- An explanation text that the password needs to be entered since it hasn't been entered in a while. [CHAR LIMIT=80]-->
- <plurals name="kg_prompt_reason_time_password">
- <item quantity="one">Device hasn\'t been unlocked for <xliff:g id="number">%d</xliff:g> hour. Confirm password.</item>
- <item quantity="other">Device hasn\'t been unlocked for <xliff:g id="number">%d</xliff:g> hours. Confirm password.</item>
- </plurals>
-
<!-- Fingerprint hint message when finger was not recognized.-->
<string name="kg_fingerprint_not_recognized">Not recognized</string>
@@ -324,5 +241,4 @@
<string name="clock_title_bubble">Bubble</string>
<!-- Name of the "Analog" clock face [CHAR LIMIT=15]-->
<string name="clock_title_analog">Analog</string>
-
</resources>
diff --git a/packages/SystemUI/res-keyguard/values/styles.xml b/packages/SystemUI/res-keyguard/values/styles.xml
index 6e89fb0..b0bdc72 100644
--- a/packages/SystemUI/res-keyguard/values/styles.xml
+++ b/packages/SystemUI/res-keyguard/values/styles.xml
@@ -75,9 +75,6 @@
</style>
<!-- Built-in clock widget stuff -->
- <style name="widget_label">
- <item name="android:textSize">@dimen/widget_label_font_size</item>
- </style>
<style name="widget_big">
<item name="android:textSize">@dimen/widget_big_font_size</item>
<item name="android:paddingBottom">@dimen/bottom_text_spacing_digital</item>
@@ -87,15 +84,7 @@
<item name="android:shadowColor">@color/keyguard_shadow_color</item>
<item name="android:shadowRadius">?attr/shadowRadius</item>
</style>
- <style name="widget_title_bold">
- <item name="android:textStyle">bold</item>
- <item name="android:textSize">@dimen/widget_title_font_size</item>
- <item name="android:paddingBottom">@dimen/widget_vertical_padding_clock</item>
- <item name="android:fontFamily">@*android:string/config_headlineFontFamily</item>
- <item name="android:ellipsize">none</item>
- <item name="android:shadowColor">@color/keyguard_shadow_color</item>
- <item name="android:shadowRadius">?attr/shadowRadius</item>
- </style>
+
<style name="widget_small_bold">
<item name="android:textStyle">bold</item>
<item name="android:textSize">@dimen/widget_small_font_size</item>
diff --git a/packages/SystemUI/res/anim/bottomsheet_in.xml b/packages/SystemUI/res/anim/bottomsheet_in.xml
deleted file mode 100644
index 0d5efeb..0000000
--- a/packages/SystemUI/res/anim/bottomsheet_in.xml
+++ /dev/null
@@ -1,26 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
- ~ 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
- -->
-
-<set xmlns:android="http://schemas.android.com/apk/res/android"
- android:interpolator="@*android:anim/accelerate_decelerate_interpolator"
- android:zAdjustment="top">
-
- <translate android:fromYDelta="100%"
- android:toYDelta="0"
- android:startOffset="@android:integer/config_shortAnimTime"
- android:duration="@*android:integer/config_mediumAnimTime"/>
-</set>
diff --git a/packages/SystemUI/res/anim/bottomsheet_out.xml b/packages/SystemUI/res/anim/bottomsheet_out.xml
deleted file mode 100644
index 01f8d2d..0000000
--- a/packages/SystemUI/res/anim/bottomsheet_out.xml
+++ /dev/null
@@ -1,25 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
- ~ 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
- -->
-<set xmlns:android="http://schemas.android.com/apk/res/android"
- android:interpolator="@*android:anim/accelerate_interpolator"
- android:zAdjustment="top">
-
- <translate xmlns:android="http://schemas.android.com/apk/res/android"
- android:fromYDelta="0"
- android:toYDelta="100%"
- android:duration="@*android:integer/config_shortAnimTime" />
-</set>
diff --git a/packages/SystemUI/res/anim/tv_pip_controls_focus_gain_animation.xml b/packages/SystemUI/res/anim/tv_pip_controls_focus_gain_animation.xml
deleted file mode 100644
index 257bf35..0000000
--- a/packages/SystemUI/res/anim/tv_pip_controls_focus_gain_animation.xml
+++ /dev/null
@@ -1,21 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2016 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.
--->
-
-<objectAnimator xmlns:android="http://schemas.android.com/apk/res/android"
- android:propertyName="alpha"
- android:valueTo="1"
- android:interpolator="@android:interpolator/fast_out_slow_in"
- android:duration="100" />
diff --git a/packages/SystemUI/res/anim/tv_pip_controls_focus_loss_animation.xml b/packages/SystemUI/res/anim/tv_pip_controls_focus_loss_animation.xml
deleted file mode 100644
index e032008..0000000
--- a/packages/SystemUI/res/anim/tv_pip_controls_focus_loss_animation.xml
+++ /dev/null
@@ -1,21 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2016 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.
--->
-
-<objectAnimator xmlns:android="http://schemas.android.com/apk/res/android"
- android:propertyName="alpha"
- android:valueTo="0"
- android:interpolator="@android:interpolator/fast_out_slow_in"
- android:duration="100" />
diff --git a/packages/SystemUI/res/anim/tv_pip_menu_fade_in_animation.xml b/packages/SystemUI/res/anim/tv_pip_menu_fade_in_animation.xml
deleted file mode 100644
index 257bf35..0000000
--- a/packages/SystemUI/res/anim/tv_pip_menu_fade_in_animation.xml
+++ /dev/null
@@ -1,21 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2016 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.
--->
-
-<objectAnimator xmlns:android="http://schemas.android.com/apk/res/android"
- android:propertyName="alpha"
- android:valueTo="1"
- android:interpolator="@android:interpolator/fast_out_slow_in"
- android:duration="100" />
diff --git a/packages/SystemUI/res/anim/tv_pip_menu_fade_out_animation.xml b/packages/SystemUI/res/anim/tv_pip_menu_fade_out_animation.xml
deleted file mode 100644
index e032008..0000000
--- a/packages/SystemUI/res/anim/tv_pip_menu_fade_out_animation.xml
+++ /dev/null
@@ -1,21 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2016 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.
--->
-
-<objectAnimator xmlns:android="http://schemas.android.com/apk/res/android"
- android:propertyName="alpha"
- android:valueTo="0"
- android:interpolator="@android:interpolator/fast_out_slow_in"
- android:duration="100" />
diff --git a/packages/SystemUI/res/color/docked_divider_background.xml b/packages/SystemUI/res/color/docked_divider_background.xml
deleted file mode 100644
index 2ab8ecd..0000000
--- a/packages/SystemUI/res/color/docked_divider_background.xml
+++ /dev/null
@@ -1,18 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2021 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.
--->
-<selector xmlns:android="http://schemas.android.com/apk/res/android">
- <item android:color="@android:color/system_neutral1_500" android:lStar="35" />
-</selector>
diff --git a/packages/SystemUI/res/color/notification_guts_buttons.xml b/packages/SystemUI/res/color/notification_guts_buttons.xml
deleted file mode 100644
index 412e0be..0000000
--- a/packages/SystemUI/res/color/notification_guts_buttons.xml
+++ /dev/null
@@ -1,7 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<selector xmlns:android="http://schemas.android.com/apk/res/android">
- <item android:state_checked="true"
- android:color="?android:attr/colorAccent" />
- <item android:color="@color/notification_primary_text_color"
- android:alpha=".54" />
-</selector>
\ No newline at end of file
diff --git a/packages/SystemUI/res/color/pin_delete_color.xml b/packages/SystemUI/res/color/pin_delete_color.xml
deleted file mode 100644
index c1b4cf8..0000000
--- a/packages/SystemUI/res/color/pin_delete_color.xml
+++ /dev/null
@@ -1,19 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
- ~ 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
- -->
-<selector xmlns:android="http://schemas.android.com/apk/res/android">
- <item android:alpha="0.61" android:color="?android:attr/textColor" />
-</selector>
\ No newline at end of file
diff --git a/packages/SystemUI/res/color/pin_divider_color.xml b/packages/SystemUI/res/color/pin_divider_color.xml
deleted file mode 100644
index e05772f..0000000
--- a/packages/SystemUI/res/color/pin_divider_color.xml
+++ /dev/null
@@ -1,19 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
- ~ 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
- -->
-<selector xmlns:android="http://schemas.android.com/apk/res/android">
- <item android:alpha="0.45" android:color="?android:attr/textColorSecondary" />
-</selector>
\ No newline at end of file
diff --git a/packages/SystemUI/res/color/qs_user_detail_name.xml b/packages/SystemUI/res/color/qs_user_detail_name.xml
deleted file mode 100644
index e262209..0000000
--- a/packages/SystemUI/res/color/qs_user_detail_name.xml
+++ /dev/null
@@ -1,23 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-
-<!--
- ~ 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
- -->
-
-<selector xmlns:android="http://schemas.android.com/apk/res/android">
- <item android:state_activated="true" android:color="?android:attr/colorAccent" />
- <item android:state_enabled="false" android:color="@color/qs_tile_disabled_color" />
- <item android:color="#66ffffff" /> <!-- 40% white -->
-</selector>
\ No newline at end of file
diff --git a/packages/SystemUI/res/color/screenrecord_switch_thumb_color.xml b/packages/SystemUI/res/color/screenrecord_switch_thumb_color.xml
deleted file mode 100644
index 22b7a1e..0000000
--- a/packages/SystemUI/res/color/screenrecord_switch_thumb_color.xml
+++ /dev/null
@@ -1,26 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2021 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.
--->
-
-<selector xmlns:android="http://schemas.android.com/apk/res/android">
- <!-- Disabled status of thumb -->
- <item android:state_enabled="false"
- android:color="@android:color/system_neutral2_100" />
- <!-- Toggle off status of thumb -->
- <item android:state_checked="false"
- android:color="@android:color/system_neutral2_100" />
- <!-- Enabled or toggle on status of thumb -->
- <item android:color="@android:color/system_accent1_100" />
-</selector>
\ No newline at end of file
diff --git a/packages/SystemUI/res/color/screenrecord_switch_track_color.xml b/packages/SystemUI/res/color/screenrecord_switch_track_color.xml
deleted file mode 100644
index bb55b07..0000000
--- a/packages/SystemUI/res/color/screenrecord_switch_track_color.xml
+++ /dev/null
@@ -1,27 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2021 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.
--->
-
-<selector xmlns:android="http://schemas.android.com/apk/res/android">
- <!-- Disabled status of thumb -->
- <item android:state_enabled="false"
- android:color="@android:color/system_neutral2_600"
- android:alpha="?android:attr/disabledAlpha" />
- <!-- Toggle off status of thumb -->
- <item android:state_checked="false"
- android:color="@android:color/system_neutral2_600" />
- <!-- Enabled or toggle on status of thumb -->
- <item android:color="@android:color/system_accent1_600" />
-</selector>
\ No newline at end of file
diff --git a/packages/SystemUI/res/color/settingslib_state_off.xml b/packages/SystemUI/res/color/settingslib_state_off.xml
deleted file mode 100644
index e821825..0000000
--- a/packages/SystemUI/res/color/settingslib_state_off.xml
+++ /dev/null
@@ -1,5 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<selector xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:androidprv="http://schemas.android.com/apk/prv/res/android">
- <item android:color="?androidprv:attr/colorAccentSecondaryVariant"/>
-</selector>
\ No newline at end of file
diff --git a/packages/SystemUI/res/drawable-hdpi/pip_dismiss_scrim.9.png b/packages/SystemUI/res/drawable-hdpi/pip_dismiss_scrim.9.png
deleted file mode 100644
index 32f1ed7..0000000
--- a/packages/SystemUI/res/drawable-hdpi/pip_dismiss_scrim.9.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/screenshot_panel.9.png b/packages/SystemUI/res/drawable-hdpi/screenshot_panel.9.png
deleted file mode 100644
index da56dcc..0000000
--- a/packages/SystemUI/res/drawable-hdpi/screenshot_panel.9.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/search_bg_transparent.9.png b/packages/SystemUI/res/drawable-hdpi/search_bg_transparent.9.png
deleted file mode 100644
index 85db9c8..0000000
--- a/packages/SystemUI/res/drawable-hdpi/search_bg_transparent.9.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mcc310-mnc004/ic_5g_plus_mobiledata.xml b/packages/SystemUI/res/drawable-mcc310-mnc004/ic_5g_plus_mobiledata.xml
deleted file mode 100644
index 998db3b..0000000
--- a/packages/SystemUI/res/drawable-mcc310-mnc004/ic_5g_plus_mobiledata.xml
+++ /dev/null
@@ -1,36 +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.
--->
-<vector xmlns:android="http://schemas.android.com/apk/res/android"
- android:viewportWidth="22"
- android:viewportHeight="17"
- android:width="22dp"
- android:height="17dp">
- <group>
- <group>
- <path android:fillColor="#FF000000"
- android:pathData="M19.98,3.54v2.81c0,0.47 -0.15,0.84 -0.44,1.11s-0.69,0.41 -1.2,0.41c-0.5,0 -0.89,-0.13 -1.19,-0.4s-0.44,-0.63 -0.45,-1.09V3.54h0.88v2.82c0,0.28 0.07,0.48 0.2,0.61c0.13,0.13 0.32,0.19 0.56,0.19c0.49,0 0.75,-0.26 0.75,-0.78V3.54H19.98z"/>
- <path android:fillColor="#FF000000"
- android:pathData="M19.42,12.25l0.57,-3.04h0.88l-0.95,4.27h-0.88l-0.69,-2.85l-0.69,2.85h-0.88l-0.95,-4.27h0.88l0.58,3.03l0.7,-3.03h0.74L19.42,12.25z"/>
- </group>
- <group>
- <path android:fillColor="#FF000000"
- android:pathData="M0.94,8.49l0.43,-4.96H5.7v1.17H2.39L2.15,7.41c0.41,-0.29 0.85,-0.43 1.33,-0.43c0.77,0 1.38,0.3 1.83,0.9c0.44,0.6 0.66,1.41 0.66,2.43c0,1.03 -0.24,1.84 -0.72,2.43c-0.48,0.59 -1.14,0.88 -1.98,0.88c-0.75,0 -1.36,-0.24 -1.83,-0.73c-0.47,-0.49 -0.74,-1.16 -0.81,-2.02h1.13c0.07,0.57 0.23,1 0.49,1.29c0.26,0.29 0.59,0.43 1.01,0.43c0.47,0 0.84,-0.2 1.1,-0.61c0.26,-0.41 0.4,-0.96 0.4,-1.65c0,-0.65 -0.14,-1.18 -0.43,-1.59C4.05,8.32 3.67,8.11 3.19,8.11c-0.4,0 -0.72,0.1 -0.96,0.31L1.9,8.75L0.94,8.49z"/>
- </group>
- <path android:fillColor="#FF000000"
- android:pathData="M13.86,12.24l-0.22,0.27c-0.63,0.73 -1.55,1.1 -2.76,1.1c-1.08,0 -1.92,-0.36 -2.53,-1.07c-0.61,-0.71 -0.93,-1.72 -0.94,-3.02V7.56c0,-1.39 0.28,-2.44 0.84,-3.13c0.56,-0.7 1.39,-1.04 2.51,-1.04c0.95,0 1.69,0.26 2.22,0.79c0.54,0.53 0.83,1.28 0.89,2.26h-1.25c-0.05,-0.62 -0.22,-1.1 -0.52,-1.45c-0.29,-0.35 -0.74,-0.52 -1.34,-0.52c-0.72,0 -1.24,0.23 -1.57,0.7C8.85,5.63 8.68,6.37 8.66,7.4v2.03c0,1 0.19,1.77 0.57,2.31c0.38,0.54 0.93,0.8 1.65,0.8c0.67,0 1.19,-0.16 1.54,-0.49l0.18,-0.17V9.59h-1.82V8.52h3.07V12.24z"/>
- </group>
-</vector>
-
diff --git a/packages/SystemUI/res/drawable-mcc311-mnc480/ic_5g_plus_mobiledata.xml b/packages/SystemUI/res/drawable-mcc311-mnc480/ic_5g_plus_mobiledata.xml
deleted file mode 100644
index 998db3b..0000000
--- a/packages/SystemUI/res/drawable-mcc311-mnc480/ic_5g_plus_mobiledata.xml
+++ /dev/null
@@ -1,36 +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.
--->
-<vector xmlns:android="http://schemas.android.com/apk/res/android"
- android:viewportWidth="22"
- android:viewportHeight="17"
- android:width="22dp"
- android:height="17dp">
- <group>
- <group>
- <path android:fillColor="#FF000000"
- android:pathData="M19.98,3.54v2.81c0,0.47 -0.15,0.84 -0.44,1.11s-0.69,0.41 -1.2,0.41c-0.5,0 -0.89,-0.13 -1.19,-0.4s-0.44,-0.63 -0.45,-1.09V3.54h0.88v2.82c0,0.28 0.07,0.48 0.2,0.61c0.13,0.13 0.32,0.19 0.56,0.19c0.49,0 0.75,-0.26 0.75,-0.78V3.54H19.98z"/>
- <path android:fillColor="#FF000000"
- android:pathData="M19.42,12.25l0.57,-3.04h0.88l-0.95,4.27h-0.88l-0.69,-2.85l-0.69,2.85h-0.88l-0.95,-4.27h0.88l0.58,3.03l0.7,-3.03h0.74L19.42,12.25z"/>
- </group>
- <group>
- <path android:fillColor="#FF000000"
- android:pathData="M0.94,8.49l0.43,-4.96H5.7v1.17H2.39L2.15,7.41c0.41,-0.29 0.85,-0.43 1.33,-0.43c0.77,0 1.38,0.3 1.83,0.9c0.44,0.6 0.66,1.41 0.66,2.43c0,1.03 -0.24,1.84 -0.72,2.43c-0.48,0.59 -1.14,0.88 -1.98,0.88c-0.75,0 -1.36,-0.24 -1.83,-0.73c-0.47,-0.49 -0.74,-1.16 -0.81,-2.02h1.13c0.07,0.57 0.23,1 0.49,1.29c0.26,0.29 0.59,0.43 1.01,0.43c0.47,0 0.84,-0.2 1.1,-0.61c0.26,-0.41 0.4,-0.96 0.4,-1.65c0,-0.65 -0.14,-1.18 -0.43,-1.59C4.05,8.32 3.67,8.11 3.19,8.11c-0.4,0 -0.72,0.1 -0.96,0.31L1.9,8.75L0.94,8.49z"/>
- </group>
- <path android:fillColor="#FF000000"
- android:pathData="M13.86,12.24l-0.22,0.27c-0.63,0.73 -1.55,1.1 -2.76,1.1c-1.08,0 -1.92,-0.36 -2.53,-1.07c-0.61,-0.71 -0.93,-1.72 -0.94,-3.02V7.56c0,-1.39 0.28,-2.44 0.84,-3.13c0.56,-0.7 1.39,-1.04 2.51,-1.04c0.95,0 1.69,0.26 2.22,0.79c0.54,0.53 0.83,1.28 0.89,2.26h-1.25c-0.05,-0.62 -0.22,-1.1 -0.52,-1.45c-0.29,-0.35 -0.74,-0.52 -1.34,-0.52c-0.72,0 -1.24,0.23 -1.57,0.7C8.85,5.63 8.68,6.37 8.66,7.4v2.03c0,1 0.19,1.77 0.57,2.31c0.38,0.54 0.93,0.8 1.65,0.8c0.67,0 1.19,-0.16 1.54,-0.49l0.18,-0.17V9.59h-1.82V8.52h3.07V12.24z"/>
- </group>
-</vector>
-
diff --git a/packages/SystemUI/res/drawable-mdpi/one_handed_tutorial.png b/packages/SystemUI/res/drawable-mdpi/one_handed_tutorial.png
deleted file mode 100644
index 6983c3b8..0000000
--- a/packages/SystemUI/res/drawable-mdpi/one_handed_tutorial.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/pip_dismiss_scrim.9.png b/packages/SystemUI/res/drawable-mdpi/pip_dismiss_scrim.9.png
deleted file mode 100644
index 33826a6..0000000
--- a/packages/SystemUI/res/drawable-mdpi/pip_dismiss_scrim.9.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/screenshot_panel.9.png b/packages/SystemUI/res/drawable-mdpi/screenshot_panel.9.png
deleted file mode 100644
index 295e91f..0000000
--- a/packages/SystemUI/res/drawable-mdpi/screenshot_panel.9.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/search_bg_transparent.9.png b/packages/SystemUI/res/drawable-mdpi/search_bg_transparent.9.png
deleted file mode 100644
index c4941a6..0000000
--- a/packages/SystemUI/res/drawable-mdpi/search_bg_transparent.9.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-nodpi/android_11_dial.xml b/packages/SystemUI/res/drawable-nodpi/android_11_dial.xml
deleted file mode 100644
index 73fd37f..0000000
--- a/packages/SystemUI/res/drawable-nodpi/android_11_dial.xml
+++ /dev/null
@@ -1,63 +0,0 @@
-<vector xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:aapt="http://schemas.android.com/aapt"
- android:width="108dp"
- android:height="108dp"
- android:viewportWidth="108"
- android:viewportHeight="108">
- <path
- android:pathData="M77.773,51.064h-1.583c-0.217,0 -0.393,-0.176 -0.393,-0.393v-1.46c0,-0.217 0.176,-0.393 0.393,-0.393h3.466c0.217,0 0.393,0.176 0.393,0.393v9.921c0,0.217 -0.176,0.393 -0.393,0.393h-1.49c-0.217,0 -0.393,-0.176 -0.393,-0.393V51.064z"
- android:fillColor="#F86734"/>
- <path
- android:pathData="M83.598,51.064h-1.583c-0.217,0 -0.393,-0.176 -0.393,-0.393v-1.46c0,-0.217 0.176,-0.393 0.393,-0.393h3.466c0.217,0 0.393,0.176 0.393,0.393v9.921c0,0.217 -0.176,0.393 -0.393,0.393h-1.49c-0.217,0 -0.393,-0.176 -0.393,-0.393V51.064z"
- android:fillColor="#F86734"/>
- <path
- android:pathData="M70.044,75.974m-0.644,0a0.644,0.644 0,1 1,1.288 0a0.644,0.644 0,1 1,-1.288 0"
- android:fillColor="#d7effe"/>
- <path
- android:pathData="M56.896,80.985m-0.718,0a0.718,0.718 0,1 1,1.436 0a0.718,0.718 0,1 1,-1.436 0"
- android:fillColor="#d7effe"/>
- <path
- android:pathData="M43.408,78.881m-0.795,0a0.795,0.795 0,1 1,1.59 0a0.795,0.795 0,1 1,-1.59 0"
- android:fillColor="#d7effe"/>
- <path
- android:pathData="M32.419,70.115m-0.874,0a0.874,0.874 0,1 1,1.748 0a0.874,0.874 0,1 1,-1.748 0"
- android:fillColor="#d7effe"/>
- <path
- android:pathData="M27.306,56.992m-0.954,0a0.954,0.954 0,1 1,1.908 0a0.954,0.954 0,1 1,-1.908 0"
- android:fillColor="#d7effe"/>
- <path
- android:pathData="M29.313,43.489m-1.036,0a1.036,1.036 0,1 1,2.072 0a1.036,1.036 0,1 1,-2.072 0"
- android:fillColor="#d7effe"/>
- <path
- android:pathData="M37.988,32.445m-1.118,0a1.118,1.118 0,1 1,2.236 0a1.118,1.118 0,1 1,-2.236 0"
- android:fillColor="#d7effe"/>
- <path
- android:pathData="M51.137,27.064m-1.201,0a1.201,1.201 0,1 1,2.402 0a1.201,1.201 0,1 1,-2.402 0"
- android:fillColor="#d7effe"/>
- <path
- android:pathData="M64.553,28.868m-1.284,0a1.284,1.284 0,1 1,2.568 0a1.284,1.284 0,1 1,-2.568 0"
- android:fillColor="#d7effe"/>
- <path
- android:pathData="M75.522,37.652m-1.368,0a1.368,1.368 0,1 1,2.736 0a1.368,1.368 0,1 1,-2.736 0"
- android:fillColor="#d7effe"/>
- <path
- android:pathData="M87.942,115.052l-47.557,-47.557l26.869,-26.87l47.557,47.558z">
- <aapt:attr name="android:fillColor">
- <gradient
- android:startY="56.087"
- android:startX="55.8464"
- android:endY="100.0297"
- android:endX="99.7891"
- android:type="linear">
- <item android:offset="0" android:color="#3F000000"/>
- <item android:offset="1" android:color="#00000000"/>
- </gradient>
- </aapt:attr>
- </path>
- <path
- android:pathData="M53.928,54.17m-18.999,0a18.999,18.999 0,1 1,37.998 0a18.999,18.999 0,1 1,-37.998 0"
- android:fillColor="#3ddc84"/>
- <path
- android:pathData="M66.353,54.17m-3.185,0a3.185,3.185 0,1 1,6.37 0a3.185,3.185 0,1 1,-6.37 0"
- android:fillColor="#FFFFFF"/>
-</vector>
diff --git a/packages/SystemUI/res/drawable-nodpi/work_challenge_background.png b/packages/SystemUI/res/drawable-nodpi/work_challenge_background.png
deleted file mode 100644
index 311f30bc..0000000
--- a/packages/SystemUI/res/drawable-nodpi/work_challenge_background.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/one_handed_tutorial.png b/packages/SystemUI/res/drawable-xhdpi/one_handed_tutorial.png
deleted file mode 100644
index 3ff692f..0000000
--- a/packages/SystemUI/res/drawable-xhdpi/one_handed_tutorial.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/pip_dismiss_scrim.9.png b/packages/SystemUI/res/drawable-xhdpi/pip_dismiss_scrim.9.png
deleted file mode 100644
index c1157f4..0000000
--- a/packages/SystemUI/res/drawable-xhdpi/pip_dismiss_scrim.9.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/remote.png b/packages/SystemUI/res/drawable-xhdpi/remote.png
deleted file mode 100644
index c0ccfe69..0000000
--- a/packages/SystemUI/res/drawable-xhdpi/remote.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/screenshot_panel.9.png b/packages/SystemUI/res/drawable-xhdpi/screenshot_panel.9.png
deleted file mode 100644
index 511537a..0000000
--- a/packages/SystemUI/res/drawable-xhdpi/screenshot_panel.9.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/search_bg_transparent.9.png b/packages/SystemUI/res/drawable-xhdpi/search_bg_transparent.9.png
deleted file mode 100644
index 4618f40..0000000
--- a/packages/SystemUI/res/drawable-xhdpi/search_bg_transparent.9.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xxhdpi/one_handed_tutorial.png b/packages/SystemUI/res/drawable-xxhdpi/one_handed_tutorial.png
deleted file mode 100644
index 75723fb..0000000
--- a/packages/SystemUI/res/drawable-xxhdpi/one_handed_tutorial.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xxhdpi/pip_dismiss_scrim.9.png b/packages/SystemUI/res/drawable-xxhdpi/pip_dismiss_scrim.9.png
deleted file mode 100644
index 8d58a7e..0000000
--- a/packages/SystemUI/res/drawable-xxhdpi/pip_dismiss_scrim.9.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xxhdpi/screenshot_panel.9.png b/packages/SystemUI/res/drawable-xxhdpi/screenshot_panel.9.png
deleted file mode 100644
index 45259d7..0000000
--- a/packages/SystemUI/res/drawable-xxhdpi/screenshot_panel.9.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xxhdpi/search_bg_transparent.9.png b/packages/SystemUI/res/drawable-xxhdpi/search_bg_transparent.9.png
deleted file mode 100644
index c0bf31d..0000000
--- a/packages/SystemUI/res/drawable-xxhdpi/search_bg_transparent.9.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xxxhdpi/one_handed_tutorial.png b/packages/SystemUI/res/drawable-xxxhdpi/one_handed_tutorial.png
deleted file mode 100644
index 173abed..0000000
--- a/packages/SystemUI/res/drawable-xxxhdpi/one_handed_tutorial.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xxxhdpi/pip_dismiss_scrim.9.png b/packages/SystemUI/res/drawable-xxxhdpi/pip_dismiss_scrim.9.png
deleted file mode 100644
index 6c04d1a..0000000
--- a/packages/SystemUI/res/drawable-xxxhdpi/pip_dismiss_scrim.9.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable/circle_blue_40dp.xml b/packages/SystemUI/res/drawable/circle_blue_40dp.xml
deleted file mode 100644
index 00d2c52..0000000
--- a/packages/SystemUI/res/drawable/circle_blue_40dp.xml
+++ /dev/null
@@ -1,22 +0,0 @@
-<?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.
--->
-<shape xmlns:android="http://schemas.android.com/apk/res/android"
- android:shape="oval">
- <size android:height="40dp"
- android:width="40dp" />
- <solid android:color="#4285f4" />
- <stroke android:color="#f1f3f4" android:width="1dp" />
-</shape>
\ No newline at end of file
diff --git a/packages/SystemUI/res/drawable/circle_white_40dp.xml b/packages/SystemUI/res/drawable/circle_white_40dp.xml
deleted file mode 100644
index bcb1640..0000000
--- a/packages/SystemUI/res/drawable/circle_white_40dp.xml
+++ /dev/null
@@ -1,22 +0,0 @@
-<?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.
--->
-<shape xmlns:android="http://schemas.android.com/apk/res/android"
- android:shape="oval">
- <size android:height="40dp"
- android:width="40dp" />
- <solid android:color="#ffffff" />
- <stroke android:color="#f1f3f4" android:width="1dp" />
-</shape>
\ No newline at end of file
diff --git a/packages/SystemUI/res/drawable/floating_dismiss_gradient_transition.xml b/packages/SystemUI/res/drawable/floating_dismiss_gradient_transition.xml
deleted file mode 100644
index 6a0695e..0000000
--- a/packages/SystemUI/res/drawable/floating_dismiss_gradient_transition.xml
+++ /dev/null
@@ -1,19 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- 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.
--->
-<transition xmlns:android="http://schemas.android.com/apk/res/android">
- <item android:drawable="@color/transparent" />
- <item android:drawable="@drawable/floating_dismiss_gradient" />
-</transition>
\ No newline at end of file
diff --git a/packages/SystemUI/res/drawable/ic_add_to_home.xml b/packages/SystemUI/res/drawable/ic_add_to_home.xml
deleted file mode 100644
index 2b40c62..0000000
--- a/packages/SystemUI/res/drawable/ic_add_to_home.xml
+++ /dev/null
@@ -1,26 +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
- -->
-
-<vector xmlns:android="http://schemas.android.com/apk/res/android"
- android:width="24dp"
- android:height="24dp"
- android:viewportWidth="24.0"
- android:viewportHeight="24.0"
- android:tint="?attr/colorControlNormal">
- <path
- android:fillColor="@android:color/white"
- android:pathData="M18,1.01L8,1c-1.1,0 -2,0.9 -2,2v3h2V5h10v14H8v-1H6v3c0,1.1 0.9,2 2,2h10c1.1,0 2,-0.9 2,-2V3c0,-1.1 -0.9,-1.99 -2,-1.99zM10,15h2V8H5v2h3.59L3,15.59 4.41,17 10,11.41V15z"/>
-</vector>
diff --git a/packages/SystemUI/res/drawable/ic_arrow_downward.xml b/packages/SystemUI/res/drawable/ic_arrow_downward.xml
deleted file mode 100644
index ddd075d..0000000
--- a/packages/SystemUI/res/drawable/ic_arrow_downward.xml
+++ /dev/null
@@ -1,25 +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.
- -->
-<vector xmlns:android="http://schemas.android.com/apk/res/android"
- android:width="24dp"
- android:height="24dp"
- android:viewportWidth="24.0"
- android:viewportHeight="24.0"
- android:tint="?attr/colorControlNormal">
- <path
- android:pathData="M20,12l-1.41,-1.41L13,16.17V4h-2v12.17l-5.58,-5.59L4,12l8,8 8,-8z"
- android:fillColor="@android:color/white"/>
-</vector>
diff --git a/packages/SystemUI/res/drawable/ic_camera.xml b/packages/SystemUI/res/drawable/ic_camera.xml
deleted file mode 100644
index b330875..0000000
--- a/packages/SystemUI/res/drawable/ic_camera.xml
+++ /dev/null
@@ -1,25 +0,0 @@
-<?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
- -->
-<vector xmlns:android="http://schemas.android.com/apk/res/android"
- android:width="17dp"
- android:height="17dp"
- android:viewportWidth="24.0"
- android:viewportHeight="24.0">
- <path
- android:fillColor="#FFF"
- android:pathData="M20,5h-3.17L15,3H9L7.17,5H4C2.9,5 2,5.9 2,7v12c0,1.1 0.9,2 2,2h16c1.1,0 2,-0.9 2,-2V7C22,5.9 21.1,5 20,5zM20,19H4V7h16V19zM12,9c-2.21,0 -4,1.79 -4,4c0,2.21 1.79,4 4,4s4,-1.79 4,-4C16,10.79 14.21,9 12,9z"/>
-</vector>
diff --git a/packages/SystemUI/res/drawable/ic_cancel_24.xml b/packages/SystemUI/res/drawable/ic_cancel_24.xml
deleted file mode 100644
index 8ab28dd..0000000
--- a/packages/SystemUI/res/drawable/ic_cancel_24.xml
+++ /dev/null
@@ -1,25 +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.
- -->
-<vector xmlns:android="http://schemas.android.com/apk/res/android"
- android:width="24dp"
- android:height="24dp"
- android:viewportWidth="24.0"
- android:viewportHeight="24.0"
- android:tint="?attr/colorControlNormal">
- <path
- android:fillColor="@android:color/white"
- android:pathData="M12,2C6.47,2 2,6.47 2,12s4.47,10 10,10 10,-4.47 10,-10S17.53,2 12,2zM17,15.59L15.59,17 12,13.41 8.41,17 7,15.59 10.59,12 7,8.41 8.41,7 12,10.59 15.59,7 17,8.41 13.41,12 17,15.59z"/>
-</vector>
\ No newline at end of file
diff --git a/packages/SystemUI/res/drawable/ic_chevron_up.xml b/packages/SystemUI/res/drawable/ic_chevron_up.xml
deleted file mode 100644
index 835d0ad..0000000
--- a/packages/SystemUI/res/drawable/ic_chevron_up.xml
+++ /dev/null
@@ -1,24 +0,0 @@
-<!--
- ~ 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
- -->
-<vector xmlns:android="http://schemas.android.com/apk/res/android"
- android:width="24dp"
- android:height="24dp"
- android:viewportWidth="24.0"
- android:viewportHeight="24.0">
- <path
- android:fillColor="@android:color/white"
- android:pathData="M7.41 15.41L12 10.83l4.59 4.58L18 14l-6-6-6 6z"/>
-</vector>
diff --git a/packages/SystemUI/res/drawable/ic_clear.xml b/packages/SystemUI/res/drawable/ic_clear.xml
deleted file mode 100644
index 5ee50d8..0000000
--- a/packages/SystemUI/res/drawable/ic_clear.xml
+++ /dev/null
@@ -1,24 +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.
- -->
-<vector xmlns:android="http://schemas.android.com/apk/res/android"
- android:width="24.0dp"
- android:height="24.0dp"
- android:viewportWidth="24.0"
- android:viewportHeight="24.0">
- <path
- android:pathData="M19,6.41L17.59,5 12,10.59 6.41,5 5,6.41 10.59,12 5,17.59 6.41,19 12,13.41 17.59,19 19,17.59 13.41,12 19,6.41z"
- android:fillColor="#FF000000"/>
-</vector>
diff --git a/packages/SystemUI/res/drawable/ic_demote_conversation.xml b/packages/SystemUI/res/drawable/ic_demote_conversation.xml
deleted file mode 100644
index 5a88160..0000000
--- a/packages/SystemUI/res/drawable/ic_demote_conversation.xml
+++ /dev/null
@@ -1,25 +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
- -->
-
-<vector xmlns:android="http://schemas.android.com/apk/res/android"
- android:width="24dp"
- android:height="24dp"
- android:viewportWidth="24.0"
- android:viewportHeight="24.0">
- <path
- android:fillColor="@android:color/white"
- android:pathData="M20,2L4.83,2l2,2L20,4v12h-1.17l1.87,1.87c0.75,-0.29 1.3,-1.02 1.3,-1.87L22,4c0,-1.1 -0.9,-2 -2,-2zM6,12h2v2L6,14zM18,11L18,9h-6.17l2,2zM18,6h-8v1.17l0.83,0.83L18,8zM0.69,3.51l1.32,1.32L2,22l4,-4h9.17l5.31,5.31 1.41,-1.41L2.1,2.1 0.69,3.51zM6,16h-0.83l-0.59,0.59 -0.58,0.58L4,6.83l2,2L6,11h2.17l5,5L6,16z"/>
-</vector>
\ No newline at end of file
diff --git a/packages/SystemUI/res/drawable/ic_drag_handle.xml b/packages/SystemUI/res/drawable/ic_drag_handle.xml
deleted file mode 100644
index 9b319f1..0000000
--- a/packages/SystemUI/res/drawable/ic_drag_handle.xml
+++ /dev/null
@@ -1,24 +0,0 @@
-<!--
- Copyright (C) 2016 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="24.0dp"
- android:height="24.0dp"
- android:viewportWidth="24.0"
- android:viewportHeight="24.0">
- <path
- android:fillColor="#FFFFFFFF"
- android:pathData="M20.0,9.0L4.0,9.0l0.0,2.0l16.0,0.0L20.0,9.0zM4.0,15.0l16.0,0.0l0.0,-2.0L4.0,13.0l0.0,2.0z"/>
-</vector>
diff --git a/packages/SystemUI/res/drawable/ic_exit_to_app.xml b/packages/SystemUI/res/drawable/ic_exit_to_app.xml
deleted file mode 100644
index a2f3c68..0000000
--- a/packages/SystemUI/res/drawable/ic_exit_to_app.xml
+++ /dev/null
@@ -1,27 +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.
- -->
-<vector xmlns:android="http://schemas.android.com/apk/res/android"
- android:width="24dp"
- android:height="24dp"
- android:viewportWidth="24"
- android:viewportHeight="24">
-
- <path
- android:pathData="M10.09 15.59L11.5 17l5-5-5-5-1.41 1.41L12.67 11H3v2h9.67l-2.58 2.59zM19 3H5c-1.11 0-2 .9-2 2v4h2V5h14v14H5v-4H3v4c0 1.1.89 2 2 2h14c1.1 0 2-.9 2-2V5c0-1.1-.9-2-2-2z"
- android:fillColor="#ffffff"
- android:fillType="evenOdd"/>
-
-</vector>
diff --git a/packages/SystemUI/res/drawable/ic_fullscreen_white_24dp.xml b/packages/SystemUI/res/drawable/ic_fullscreen_white_24dp.xml
deleted file mode 100644
index 314a25a..0000000
--- a/packages/SystemUI/res/drawable/ic_fullscreen_white_24dp.xml
+++ /dev/null
@@ -1,24 +0,0 @@
-<!--
-Copyright (C) 2016 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="24dp"
- android:height="24dp"
- android:viewportWidth="24"
- android:viewportHeight="24">
- <path
- android:fillColor="#FFFFFF"
- android:pathData="M7 14H5v5h5v-2H7v-3zm-2-4h2V7h3V5H5v5zm12 7h-3v2h5v-5h-2v3zM14 5v2h3v3h2V5h-5z" />
-</vector>
diff --git a/packages/SystemUI/res/drawable/ic_important.xml b/packages/SystemUI/res/drawable/ic_important.xml
deleted file mode 100644
index d7439e1..0000000
--- a/packages/SystemUI/res/drawable/ic_important.xml
+++ /dev/null
@@ -1,26 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
- 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.
--->
-<vector xmlns:android="http://schemas.android.com/apk/res/android"
- android:width="24dp"
- android:height="24dp"
- android:viewportWidth="24.0"
- android:viewportHeight="24.0"
- android:tint="?attr/colorControlNormal">
- <path
- android:fillColor="@android:color/white"
- android:pathData="M4,18.99h11c0.67,0 1.27,-0.32 1.63,-0.83L21,12l-4.37,-6.16C16.27,5.33 15.67,5 15,5H4l5,7 -5,6.99z"/>
-</vector>
diff --git a/packages/SystemUI/res/drawable/ic_fingerprint.xml b/packages/SystemUI/res/drawable/ic_kg_fingerprint.xml
similarity index 100%
rename from packages/SystemUI/res/drawable/ic_fingerprint.xml
rename to packages/SystemUI/res/drawable/ic_kg_fingerprint.xml
diff --git a/packages/SystemUI/res/drawable/ic_notification_block.xml b/packages/SystemUI/res/drawable/ic_notification_block.xml
deleted file mode 100644
index 27690740..0000000
--- a/packages/SystemUI/res/drawable/ic_notification_block.xml
+++ /dev/null
@@ -1,25 +0,0 @@
-<!--
-Copyright (C) 2016 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="24.0dp"
- android:height="24.0dp"
- android:viewportWidth="24.0"
- android:viewportHeight="24.0">
-
- <path
- android:fillColor="#FF000000"
- android:pathData="M12.0,2.0C6.48,2.0 2.0,6.48 2.0,12.0s4.48,10.0 10.0,10.0 10.0,-4.48 10.0,-10.0S17.52,2.0 12.0,2.0zM4.0,12.0c0.0,-4.42 3.58,-8.0 8.0,-8.0 1.85,0.0 3.5,0.63 4.9,1.69L5.69,16.9C4.63,15.55 4.0,13.85 4.0,12.0zm8.0,8.0c-1.85,0.0 -3.55,-0.63 -4.9,-1.69L18.31,7.1C19.37,8.45 20.0,10.15 20.0,12.0c0.0,4.42 -3.58,8.0 -8.0,8.0z"/>
-</vector>
diff --git a/packages/SystemUI/res/drawable/ic_notification_gentle.xml b/packages/SystemUI/res/drawable/ic_notification_gentle.xml
deleted file mode 100644
index de54b10..0000000
--- a/packages/SystemUI/res/drawable/ic_notification_gentle.xml
+++ /dev/null
@@ -1,40 +0,0 @@
-<!--
-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.
--->
-<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
- <item
- android:id="@+id/back">
- <shape android:shape="oval">
- <solid
- android:color="@color/notification_silence_color" />
- <size
- android:height="24dp"
- android:width="24dp"/>
- </shape>
- </item>
- <item
- android:id="@+id/fore"
- android:gravity="center">
- <vector
- android:width="13dp"
- android:height="13dp"
- android:viewportWidth="24"
- android:viewportHeight="24">
- <path
- android:fillColor="#FFFFFFFF"
- android:pathData="M15,14.5c-1.38,0 -2.5,-1.12 -2.5,-2.5c0,-0.28 -0.22,-0.5 -0.5,-0.5s-0.5,0.22 -0.5,0.5c0,1.38 -1.12,2.5 -2.5,2.5S6.5,13.38 6.5,12c0,-0.28 -0.22,-0.5 -0.5,-0.5c-0.24,0 -0.46,0.18 -0.49,0.42C5.41,12.55 4.89,13 4.27,13H2v-2h1.71C4.1,10.11 5,9.5 6,9.5c1.38,0 2.5,1.12 2.5,2.5c0,0.28 0.22,0.5 0.5,0.5s0.5,-0.22 0.5,-0.5c0,-1.38 1.12,-2.5 2.5,-2.5s2.5,1.12 2.5,2.5c0,0.28 0.22,0.5 0.5,0.5s0.5,-0.22 0.5,-0.5c0,-1.38 1.12,-2.5 2.5,-2.5c1.02,0 1.91,0.6 2.29,1.5H22v2h-2.27c-0.62,0 -1.14,-0.45 -1.23,-1.08c-0.04,-0.24 -0.25,-0.42 -0.49,-0.42c-0.28,0 -0.5,0.22 -0.5,0.5C17.5,13.38 16.38,14.5 15,14.5z"/>
- </vector>
- </item>
-</layer-list>
diff --git a/packages/SystemUI/res/drawable/ic_notification_interruptive.xml b/packages/SystemUI/res/drawable/ic_notification_interruptive.xml
deleted file mode 100644
index f49aa4a..0000000
--- a/packages/SystemUI/res/drawable/ic_notification_interruptive.xml
+++ /dev/null
@@ -1,41 +0,0 @@
-<!--
-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.
--->
-
-<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
- <item
- android:id="@+id/back">
- <shape android:shape="oval">
- <solid
- android:color="@color/notification_alert_color" />
- <size
- android:height="24dp"
- android:width="24dp"/>
- </shape>
- </item>
- <item
- android:id="@+id/fore"
- android:gravity="center">
- <vector
- android:width="13dp"
- android:height="13dp"
- android:viewportWidth="24"
- android:viewportHeight="24">
- <path
- android:fillColor="#FFFFFFFF"
- android:pathData="M8.98,16.65c-0.47,0 -0.91,-0.27 -1.12,-0.69l-1.93,-4.61L5.46,12.3c-0.21,0.43 -0.64,0.69 -1.12,0.69H2v-2h1.88l1,-2C5.1,8.56 5.52,8.3 6,8.3s0.9,0.26 1.12,0.69l1.73,4.14l2,-7c0.2,-0.46 0.65,-0.76 1.15,-0.76s0.95,0.3 1.15,0.76l0.04,0.12l1.96,6.88l1.7,-4.08c0.49,-0.98 1.84,-0.91 2.26,-0.06l1,2H22v2h-2.35c-0.47,0 -0.91,-0.27 -1.12,-0.7l-0.47,-0.95l-1.9,4.55c-0.25,0.5 -0.69,0.77 -1.18,0.75c-0.48,-0.01 -0.92,-0.31 -1.11,-0.76l-0.04,-0.12L12,9.37l-1.87,6.52c-0.19,0.45 -0.63,0.74 -1.11,0.76C9.01,16.65 9,16.65 8.98,16.65zM20.32,11.4L20.32,11.4C20.32,11.4 20.32,11.4 20.32,11.4z" />
- </vector>
- </item>
-</layer-list>
diff --git a/packages/SystemUI/res/drawable/ic_pause_white.xml b/packages/SystemUI/res/drawable/ic_pause_white.xml
deleted file mode 100644
index 5b65f10..0000000
--- a/packages/SystemUI/res/drawable/ic_pause_white.xml
+++ /dev/null
@@ -1,25 +0,0 @@
-<!--
-Copyright (C) 2016 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="24dp"
- android:height="24dp"
- android:viewportWidth="24"
- android:viewportHeight="24">
-
- <path
- android:fillColor="#FFFFFF"
- android:pathData="M6 19h4V5H6v14zm8-14v14h4V5h-4z" />
-</vector>
diff --git a/packages/SystemUI/res/drawable/ic_photo_camera.xml b/packages/SystemUI/res/drawable/ic_photo_camera.xml
deleted file mode 100644
index 63cd4e2..0000000
--- a/packages/SystemUI/res/drawable/ic_photo_camera.xml
+++ /dev/null
@@ -1,28 +0,0 @@
-<!--
- ~ Copyright (C) 2021 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="24dp"
- android:height="24dp"
- android:viewportWidth="24.0"
- android:viewportHeight="24.0">
- <path
- android:fillColor="#FF000000"
- android:pathData="M12,12m-3.2,0a3.2,3.2 0,1 1,6.4 0a3.2,3.2 0,1 1,-6.4 0"/>
- <path
- android:fillColor="#FF000000"
- android:pathData="M9,2L7.17,4L4,4c-1.1,0 -2,0.9 -2,2v12c0,1.1 0.9,2 2,2h16c1.1,0 2,-0.9 2,-2L22,6c0,-1.1 -0.9,-2 -2,-2h-3.17L15,2L9,2zM12,17c-2.76,0 -5,-2.24 -5,-5s2.24,-5 5,-5 5,2.24 5,5 -2.24,5 -5,5z"/>
-</vector>
\ No newline at end of file
diff --git a/packages/SystemUI/res/drawable/ic_play_arrow_white.xml b/packages/SystemUI/res/drawable/ic_play_arrow_white.xml
deleted file mode 100644
index ddc9e8d..0000000
--- a/packages/SystemUI/res/drawable/ic_play_arrow_white.xml
+++ /dev/null
@@ -1,25 +0,0 @@
-<!--
-Copyright (C) 2016 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="24dp"
- android:height="24dp"
- android:viewportWidth="24"
- android:viewportHeight="24">
-
- <path
- android:fillColor="#FFFFFF"
- android:pathData="M8 5v14l11-7z" />
-</vector>
diff --git a/packages/SystemUI/res/drawable/ic_power_settings_new_gm2_24px.xml b/packages/SystemUI/res/drawable/ic_power_settings_new_gm2_24px.xml
deleted file mode 100644
index f4edd87..0000000
--- a/packages/SystemUI/res/drawable/ic_power_settings_new_gm2_24px.xml
+++ /dev/null
@@ -1,9 +0,0 @@
-<vector xmlns:android="http://schemas.android.com/apk/res/android"
- android:width="24dp"
- android:height="24dp"
- android:viewportWidth="24"
- android:viewportHeight="24">
- <path
- android:fillColor="#FF000000"
- android:pathData="M11,2h2v10h-2zM18.37,5.64l-1.41,1.41c2.73,2.73 2.72,7.16 -0.01,9.89 -2.73,2.73 -7.17,2.73 -9.89,0.01 -2.73,-2.73 -2.74,-7.18 -0.01,-9.91l-1.41,-1.4c-3.51,3.51 -3.51,9.21 0.01,12.73 3.51,3.51 9.21,3.51 12.72,-0.01 3.51,-3.51 3.51,-9.2 0,-12.72z"/>
-</vector>
diff --git a/packages/SystemUI/res/drawable/ic_qs_bluetooth_on.xml b/packages/SystemUI/res/drawable/ic_qs_bluetooth_on.xml
deleted file mode 100644
index 1c86706..0000000
--- a/packages/SystemUI/res/drawable/ic_qs_bluetooth_on.xml
+++ /dev/null
@@ -1,24 +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.
--->
-<vector xmlns:android="http://schemas.android.com/apk/res/android"
- android:width="24dp"
- android:height="24dp"
- android:viewportWidth="24.0"
- android:viewportHeight="24.0">
- <path
- android:fillColor="@android:color/white"
- android:pathData="M17.71,7.71L12,2h-1v7.59L6.41,5 5,6.41 10.59,12 5,17.59 6.41,19 11,14.41L11,22h1l5.71,-5.71 -4.3,-4.29 4.3,-4.29zM13,5.83l1.88,1.88L13,9.59L13,5.83zM14.88,16.29L13,18.17v-3.76l1.88,1.88z"/>
-</vector>
\ No newline at end of file
diff --git a/packages/SystemUI/res/drawable/ic_qs_no_internet_airplane.xml b/packages/SystemUI/res/drawable/ic_qs_no_internet_airplane.xml
deleted file mode 100644
index 3d6ca7a..0000000
--- a/packages/SystemUI/res/drawable/ic_qs_no_internet_airplane.xml
+++ /dev/null
@@ -1,28 +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.
--->
-<vector xmlns:android="http://schemas.android.com/apk/res/android"
- android:width="24dp"
- android:height="24dp"
- android:viewportWidth="24.0"
- android:viewportHeight="24.0">
- <path
- android:fillColor="#FF000000"
- android:pathData="M11.99,2C6.47,2 2,6.48 2,12s4.47,10 9.99,10c0.34,0 0.68,-0.02 1.01,-0.05V20h-1v-0.04c-0.83,-1.2 -1.48,-2.53 -1.91,-3.96H13v-2H9.66c-0.09,-0.66 -0.16,-1.32 -0.16,-2s0.07,-1.35 0.16,-2H21.8C20.87,5.44 16.83,2 11.99,2zM18.92,8h-2.95c-0.32,-1.25 -0.78,-2.45 -1.38,-3.56C16.43,5.07 17.96,6.35 18.92,8zM12,4.04c0.83,1.2 1.48,2.53 1.91,3.96h-3.82C10.52,6.57 11.17,5.24 12,4.04zM4.26,14C4.1,13.36 4,12.69 4,12s0.1,-1.36 0.26,-2h3.38c-0.08,0.66 -0.14,1.32 -0.14,2s0.06,1.34 0.14,2H4.26zM5.08,16h2.95c0.32,1.25 0.78,2.45 1.38,3.56C7.57,18.93 6.04,17.66 5.08,16zM8.03,8H5.08c0.96,-1.66 2.49,-2.93 4.33,-3.56C8.81,5.55 8.35,6.75 8.03,8z"
- android:fillAlpha="0.3"/>
- <path
- android:fillColor="#FF000000"
- android:pathData="M22,19.3v-0.9l-3.37,-2.25v-2.47C18.63,13.3 18.35,13 18,13s-0.63,0.3 -0.63,0.68v2.47L14,18.4v0.9l3.37,-1.12v2.48l-0.84,0.68V22L18,21.55L19.47,22v-0.67l-0.84,-0.68v-2.48L22,19.3z"/>
-</vector>
\ No newline at end of file
diff --git a/packages/SystemUI/res/drawable/ic_qs_screenrecord.xml b/packages/SystemUI/res/drawable/ic_qs_screenrecord.xml
deleted file mode 100644
index 687c9c4..0000000
--- a/packages/SystemUI/res/drawable/ic_qs_screenrecord.xml
+++ /dev/null
@@ -1,9 +0,0 @@
-<vector xmlns:android="http://schemas.android.com/apk/res/android"
- android:width="24dp"
- android:height="24dp"
- android:viewportWidth="24"
- android:viewportHeight="24">
- <path
- android:fillColor="#FF000000"
- android:pathData="M18,10.48L18,6c0,-1.1 -0.9,-2 -2,-2L4,4c-1.1,0 -2,0.9 -2,2v12c0,1.1 0.9,2 2,2h12c1.1,0 2,-0.9 2,-2v-4.48l4,3.98v-11l-4,3.98zM16,9.69L16,18L4,18L4,6h12v3.69z"/>
-</vector>
diff --git a/packages/SystemUI/res/drawable/ic_qs_wifi_0.xml b/packages/SystemUI/res/drawable/ic_qs_wifi_0.xml
deleted file mode 100644
index 7cbc26f..0000000
--- a/packages/SystemUI/res/drawable/ic_qs_wifi_0.xml
+++ /dev/null
@@ -1,32 +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.
--->
-<vector xmlns:android="http://schemas.android.com/apk/res/android"
- android:width="24dp"
- android:height="24dp"
- android:viewportWidth="25.50"
- android:viewportHeight="25.50">
- <group
- android:translateX="0.77"
- android:translateY="0.23" >
- <path
- android:pathData="M14,12h6.54l3.12,-3.89c0.39,-0.48 0.29,-1.19 -0.22,-1.54C21.67,5.36 17.55,3 12,3C6.44,3 2.33,5.36 0.56,6.57C0.05,6.92 -0.05,7.63 0.33,8.11L11.16,21.6c0.42,0.53 1.23,0.53 1.66,0L14,20.13V12z"
- android:fillAlpha="0.3"
- android:fillColor="#FFFFFF"/>
- <path
- android:pathData="M22.71,15.67l-1.83,1.83l1.83,1.83c0.38,0.38 0.38,1 0,1.38v0c-0.38,0.38 -1,0.39 -1.38,0l-1.83,-1.83l-1.83,1.83c-0.38,0.38 -1,0.38 -1.38,0l-0.01,-0.01c-0.38,-0.38 -0.38,-1 0,-1.38l1.83,-1.83l-1.82,-1.82c-0.38,-0.38 -0.38,-1 0,-1.38l0.01,-0.01c0.38,-0.38 1,-0.38 1.38,0l1.82,1.82l1.82,-1.82c0.38,-0.38 1,-0.38 1.38,0l0,0C23.09,14.67 23.09,15.29 22.71,15.67z"
- android:fillColor="#FFFFFF"/>
- </group>
-</vector>
diff --git a/packages/SystemUI/res/drawable/ic_qs_wifi_1.xml b/packages/SystemUI/res/drawable/ic_qs_wifi_1.xml
deleted file mode 100644
index 694b0dd..0000000
--- a/packages/SystemUI/res/drawable/ic_qs_wifi_1.xml
+++ /dev/null
@@ -1,28 +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.
--->
-<vector xmlns:android="http://schemas.android.com/apk/res/android"
- android:width="24dp"
- android:height="24dp"
- android:viewportWidth="24.0"
- android:viewportHeight="24.0">
- <path
- android:fillColor="@android:color/white"
- android:pathData="M22,16.41L20.59,15l-2.09,2.09L16.41,15L15,16.41l2.09,2.09L15,20.59L16.41,22l2.09,-2.08L20.59,22L22,20.59l-2.08,-2.09L22,16.41z"/>
- <path
- android:fillColor="@android:color/white"
- android:pathData="M12,2.01C7.25,2.01 2.97,4.09 0,7.4L7.582,16.625C7.582,16.627 7.58,16.629 7.58,16.631L11.99,22L12,22L13,20.789L13,17.641L13,13.119C12.68,13.039 12.34,13 12,13C10.601,13 9.351,13.64 8.531,14.639L2.699,7.539C5.269,5.279 8.58,4.01 12,4.01C15.42,4.01 18.731,5.279 21.301,7.539L16.811,13L19.4,13L24,7.4C21.03,4.09 16.75,2.01 12,2.01z"
- android:fillAlpha="0.3"/>
-</vector>
diff --git a/packages/SystemUI/res/drawable/ic_qs_wifi_2.xml b/packages/SystemUI/res/drawable/ic_qs_wifi_2.xml
deleted file mode 100644
index dcb3fa8..0000000
--- a/packages/SystemUI/res/drawable/ic_qs_wifi_2.xml
+++ /dev/null
@@ -1,28 +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.
--->
-<vector xmlns:android="http://schemas.android.com/apk/res/android"
- android:width="24dp"
- android:height="24dp"
- android:viewportWidth="24.0"
- android:viewportHeight="24.0">
- <path
- android:fillColor="@android:color/white"
- android:pathData="M22,16.41L20.59,15l-2.09,2.09L16.41,15L15,16.41l2.09,2.09L15,20.59L16.41,22l2.09,-2.08L20.59,22L22,20.59l-2.08,-2.09L22,16.41z"/>
- <path
- android:fillColor="@android:color/white"
- android:pathData="M12,2C7.25,2 2.97,4.081 0,7.391L12,22L13,20.779L13,17.631L13,13L16.801,13L18,13L19.391,13L24,7.391C21.03,4.081 16.75,2 12,2zM12,4C14.747,4 17.423,4.819 19.701,6.313C20.259,6.678 20.795,7.085 21.301,7.529L17.389,12.287C16.029,10.868 14.119,9.99 12,9.99C9.88,9.99 7.969,10.869 6.609,12.289L2.699,7.529C5.269,5.269 8.58,4 12,4z"
- android:fillAlpha="0.3"/>
-</vector>
diff --git a/packages/SystemUI/res/drawable/ic_qs_wifi_3.xml b/packages/SystemUI/res/drawable/ic_qs_wifi_3.xml
deleted file mode 100644
index d68a2f6..0000000
--- a/packages/SystemUI/res/drawable/ic_qs_wifi_3.xml
+++ /dev/null
@@ -1,28 +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.
--->
-<vector xmlns:android="http://schemas.android.com/apk/res/android"
- android:width="24dp"
- android:height="24dp"
- android:viewportWidth="24.0"
- android:viewportHeight="24.0">
- <path
- android:fillColor="@android:color/white"
- android:pathData="M22,16.41L20.59,15l-2.09,2.09L16.41,15L15,16.41l2.09,2.09L15,20.59L16.41,22l2.09,-2.08L20.59,22L22,20.59l-2.08,-2.09L22,16.41z"/>
- <path
- android:fillColor="@android:color/white"
- android:pathData="M12,2C7.25,2 2.97,4.081 0,7.391L3.301,11.41L12,22L13,20.779L13,17.631L13,13L16.801,13L19.391,13L20.699,11.41C20.699,11.409 20.698,11.409 20.697,11.408L24,7.391C21.03,4.081 16.75,2 12,2zM12,4C15.42,4 18.731,5.269 21.301,7.529L19.35,9.9C17.43,8.1 14.86,6.99 12,6.99C9.14,6.99 6.57,8.1 4.65,9.9C4.65,9.901 4.649,9.902 4.648,9.902L2.699,7.529C5.269,5.269 8.58,4 12,4z"
- android:fillAlpha="0.3"/>
-</vector>
diff --git a/packages/SystemUI/res/drawable/ic_qs_wifi_4.xml b/packages/SystemUI/res/drawable/ic_qs_wifi_4.xml
deleted file mode 100644
index 886cc35..0000000
--- a/packages/SystemUI/res/drawable/ic_qs_wifi_4.xml
+++ /dev/null
@@ -1,28 +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.
--->
-<vector xmlns:android="http://schemas.android.com/apk/res/android"
- android:width="24dp"
- android:height="24dp"
- android:viewportWidth="24.0"
- android:viewportHeight="24.0">
- <path
- android:fillColor="@android:color/white"
- android:pathData="M12,2C7.25,2 2.97,4.08 0,7.39L12,22l1,-1.22V13h6.39L24,7.39C21.03,4.08 16.75,2 12,2z"
- android:fillAlpha="0.3"/>
- <path
- android:fillColor="@android:color/white"
- android:pathData="M22,16.41L20.59,15l-2.09,2.09L16.41,15L15,16.41l2.09,2.09L15,20.59L16.41,22l2.09,-2.08L20.59,22L22,20.59l-2.08,-2.09L22,16.41z"/>
-</vector>
diff --git a/packages/SystemUI/res/drawable/ic_settings_16dp.xml b/packages/SystemUI/res/drawable/ic_settings_16dp.xml
deleted file mode 100644
index 89764cf..0000000
--- a/packages/SystemUI/res/drawable/ic_settings_16dp.xml
+++ /dev/null
@@ -1,27 +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.
--->
-<vector xmlns:android="http://schemas.android.com/apk/res/android"
- android:width="16dp"
- android:height="16dp"
- android:viewportWidth="24.0"
- android:viewportHeight="24.0">
- <path
- android:fillColor="#FFFFFFFF"
- android:pathData="M13.85,22.25h-3.7c-0.74,0 -1.36,-0.54 -1.45,-1.27l-0.27,-1.89c-0.27,-0.14 -0.53,-0.29 -0.79,-0.46l-1.8,0.72c-0.7,0.26 -1.47,-0.03 -1.81,-0.65L2.2,15.53c-0.35,-0.66 -0.2,-1.44 0.36,-1.88l1.53,-1.19c-0.01,-0.15 -0.02,-0.3 -0.02,-0.46c0,-0.15 0.01,-0.31 0.02,-0.46l-1.52,-1.19C1.98,9.9 1.83,9.09 2.2,8.47l1.85,-3.19c0.34,-0.62 1.11,-0.9 1.79,-0.63l1.81,0.73c0.26,-0.17 0.52,-0.32 0.78,-0.46l0.27,-1.91c0.09,-0.7 0.71,-1.25 1.44,-1.25h3.7c0.74,0 1.36,0.54 1.45,1.27l0.27,1.89c0.27,0.14 0.53,0.29 0.79,0.46l1.8,-0.72c0.71,-0.26 1.48,0.03 1.82,0.65l1.84,3.18c0.36,0.66 0.2,1.44 -0.36,1.88l-1.52,1.19c0.01,0.15 0.02,0.3 0.02,0.46s-0.01,0.31 -0.02,0.46l1.52,1.19c0.56,0.45 0.72,1.23 0.37,1.86l-1.86,3.22c-0.34,0.62 -1.11,0.9 -1.8,0.63l-1.8,-0.72c-0.26,0.17 -0.52,0.32 -0.78,0.46l-0.27,1.91C15.21,21.71 14.59,22.25 13.85,22.25zM13.32,20.72c0,0.01 0,0.01 0,0.02L13.32,20.72zM10.68,20.7l0,0.02C10.69,20.72 10.69,20.71 10.68,20.7zM10.62,20.25h2.76l0.37,-2.55l0.53,-0.22c0.44,-0.18 0.88,-0.44 1.34,-0.78l0.45,-0.34l2.38,0.96l1.38,-2.4l-2.03,-1.58l0.07,-0.56c0.03,-0.26 0.06,-0.51 0.06,-0.78c0,-0.27 -0.03,-0.53 -0.06,-0.78l-0.07,-0.56l2.03,-1.58l-1.39,-2.4l-2.39,0.96l-0.45,-0.35c-0.42,-0.32 -0.87,-0.58 -1.33,-0.77L13.75,6.3l-0.37,-2.55h-2.76L10.25,6.3L9.72,6.51C9.28,6.7 8.84,6.95 8.38,7.3L7.93,7.63L5.55,6.68L4.16,9.07l2.03,1.58l-0.07,0.56C6.09,11.47 6.06,11.74 6.06,12c0,0.26 0.02,0.53 0.06,0.78l0.07,0.56l-2.03,1.58l1.38,2.4l2.39,-0.96l0.45,0.35c0.43,0.33 0.86,0.58 1.33,0.77l0.53,0.22L10.62,20.25zM18.22,17.72c0,0.01 -0.01,0.02 -0.01,0.03L18.22,17.72zM5.77,17.71l0.01,0.02C5.78,17.72 5.77,17.71 5.77,17.71zM3.93,9.47L3.93,9.47C3.93,9.47 3.93,9.47 3.93,9.47zM18.22,6.27c0,0.01 0.01,0.02 0.01,0.02L18.22,6.27zM5.79,6.25L5.78,6.27C5.78,6.27 5.79,6.26 5.79,6.25zM13.31,3.28c0,0.01 0,0.01 0,0.02L13.31,3.28zM10.69,3.26l0,0.02C10.69,3.27 10.69,3.27 10.69,3.26z"/>
- <path
- android:fillColor="#FFFFFFFF"
- android:pathData="M12,12m-3.5,0a3.5,3.5 0,1 1,7 0a3.5,3.5 0,1 1,-7 0"/>
-</vector>
diff --git a/packages/SystemUI/res/drawable/ic_tune_black_16dp.xml b/packages/SystemUI/res/drawable/ic_tune_black_16dp.xml
deleted file mode 100644
index c41d102..0000000
--- a/packages/SystemUI/res/drawable/ic_tune_black_16dp.xml
+++ /dev/null
@@ -1,26 +0,0 @@
-<!--
- 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.
--->
-
-<vector xmlns:android="http://schemas.android.com/apk/res/android"
- android:width="16dp"
- android:height="16dp"
- android:viewportWidth="24.0"
- android:viewportHeight="24.0"
- android:tint="?android:attr/textColorPrimary">
- <path
- android:fillColor="#FF000000"
- android:pathData="M3,17v2h6v-2L3,17zM3,5v2h10L13,5L3,5zM13,21v-2h8v-2h-8v-2h-2v6h2zM7,9v2L3,11v2h4v2h2L9,9L7,9zM21,13v-2L11,11v2h10zM15,9h2L17,7h4L21,5h-4L17,3h-2v6z"/>
-</vector>
\ No newline at end of file
diff --git a/packages/SystemUI/res/drawable/ic_unlock.xml b/packages/SystemUI/res/drawable/ic_unlock.xml
deleted file mode 100644
index 46023e6..0000000
--- a/packages/SystemUI/res/drawable/ic_unlock.xml
+++ /dev/null
@@ -1,42 +0,0 @@
-<!--
- Copyright (C) 2021 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:height="65dp" android:width="46dp" android:viewportHeight="65" android:viewportWidth="46">
- <group android:translateX="8.625" android:translateY="13.625">
- <path
- android:strokeColor="#FF000000"
- android:strokeLineCap="round"
- android:strokeLineJoin="round"
- android:strokeWidth="2"
- android:pathData="M4.75 15 C4.75,15 23.25,15 23.25,15 C24.35,15 25.25,15.9 25.25,17 C25.25,17 25.25,33 25.25,33 C25.25,34.1 24.35,35 23.25,35 C23.25,35 4.75,35 4.75,35 C3.65,35 2.75,34.1 2.75,33 C2.75,33 2.75,17 2.75,17 C2.75,15.9 3.65,15 4.75,15c " />
- </group>
- <group android:translateX="14" android:translateY="13.5">
- <path
- android:strokeColor="#FF000000"
- android:strokeLineCap="round"
- android:strokeLineJoin="round"
- android:strokeWidth="2"
- android:pathData="M27.19 14.81 C27.19,14.81 27.19,8.3 27.19,8.3 C27.19,4.92 24.44,2.88 21.19,2.75 C17.74,2.62 15,4.74 15,8.11 C15,8.11 15,15 15,15 " />
- </group>
- <group android:translateX="20" android:translateY="35.75">
- <path
- android:fillColor="#FF000000"
- android:fillAlpha="1"
- android:fillType="nonZero"
- android:pathData=" M2.75 5.25 C4.13,5.25 5.25,4.13 5.25,2.75 C5.25,1.37 4.13,0.25 2.75,0.25 C1.37,0.25 0.25,1.37 0.25,2.75 C0.25,4.13 1.37,5.25 2.75,5.25c " />
- </group>
-</vector>
diff --git a/packages/SystemUI/res/drawable/ic_volume_voice.xml b/packages/SystemUI/res/drawable/ic_volume_voice.xml
deleted file mode 100644
index 3e7748a..0000000
--- a/packages/SystemUI/res/drawable/ic_volume_voice.xml
+++ /dev/null
@@ -1,27 +0,0 @@
-<!--
- Copyright (C) 2015 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:height="24.0dp"
- android:viewportHeight="48.0"
- android:viewportWidth="48.0"
- android:width="24.0dp"
- android:tint="?android:attr/textColorPrimary" >
-
- <path
- android:fillColor="#FFFFFF"
- android:pathData="M13.25,21.59c2.88,5.66 7.51,10.29 13.18,13.17l4.4,-4.41c0.55,-0.55 1.34,-0.71 2.03,-0.49C35.1,30.6 37.51,31.0 40.0,31.0c1.11,0.0 2.0,0.89 2.0,2.0l0.0,7.0c0.0,1.11 -0.89,2.0 -2.0,2.0C21.22,42.0 6.0,26.78 6.0,8.0c0.0,-1.1 0.9,-2.0 2.0,-2.0l7.0,0.0c1.11,0.0 2.0,0.89 2.0,2.0 0.0,2.4 0.4,4.9 1.14,7.1 0.2,0.6 0.06,1.48 -0.49,2.03l-4.4,4.42z" />
-
-</vector>
\ No newline at end of file
diff --git a/packages/SystemUI/res/drawable/ic_width.xml b/packages/SystemUI/res/drawable/ic_width.xml
deleted file mode 100644
index a302c81..0000000
--- a/packages/SystemUI/res/drawable/ic_width.xml
+++ /dev/null
@@ -1,28 +0,0 @@
-<!--
- Copyright (C) 2016 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="24.0dp"
- android:height="24.0dp"
- android:viewportWidth="24.0"
- android:viewportHeight="24.0">
- <path
- android:fillColor="#FF000000"
- android:pathData="M7.77,6.76L6.23,5.4 0.82,12.0l5.41,6.52 1.54,-1.28L3.42,12.0l4.35,-5.24z
- M17.77,5.48l-1.54,1.28L20.58,12.0l-4.35,5.24 1.54,1.28L23.18,12.0l-5.41,-6.52z"/>
- <path
- android:fillColor="#FF000000"
- android:pathData="M2.0,13.0l20.0,0.0l0.0,-2.0l-20.0,0.0l0.0,2.0z" />
-</vector>
diff --git a/packages/SystemUI/res/drawable/internet_dialog_background.xml b/packages/SystemUI/res/drawable/internet_dialog_background.xml
deleted file mode 100644
index 3ceb0f6..0000000
--- a/packages/SystemUI/res/drawable/internet_dialog_background.xml
+++ /dev/null
@@ -1,23 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
- ~ 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.
- -->
-
-<inset xmlns:android="http://schemas.android.com/apk/res/android">
- <shape android:shape="rectangle">
- <corners android:radius="8dp" />
- <solid android:color="?android:attr/colorBackground" />
- </shape>
-</inset>
diff --git a/packages/SystemUI/res/drawable/internet_dialog_rounded_top_corner_background.xml b/packages/SystemUI/res/drawable/internet_dialog_rounded_top_corner_background.xml
deleted file mode 100644
index 14672ef..0000000
--- a/packages/SystemUI/res/drawable/internet_dialog_rounded_top_corner_background.xml
+++ /dev/null
@@ -1,22 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2021 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">
- <shape android:shape="rectangle">
- <corners
- android:topLeftRadius="@dimen/internet_dialog_corner_radius"
- android:topRightRadius="@dimen/internet_dialog_corner_radius"
- android:bottomLeftRadius="@dimen/internet_dialog_corner_radius"
- android:bottomRightRadius="@dimen/internet_dialog_corner_radius"/>
- <solid android:color="?android:attr/colorBackground" />
- </shape>
-</inset>
diff --git a/packages/SystemUI/res/drawable/pip_icon.xml b/packages/SystemUI/res/drawable/pip_icon.xml
deleted file mode 100644
index bd92ccd..0000000
--- a/packages/SystemUI/res/drawable/pip_icon.xml
+++ /dev/null
@@ -1,25 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
-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.
--->
-<vector xmlns:android="http://schemas.android.com/apk/res/android"
- android:width="36dp"
- android:height="36dp"
- android:viewportWidth="25"
- android:viewportHeight="25">
- <path
- android:fillColor="#FFFFFFFF"
- android:pathData="M19,7h-8v6h8L19,7zM21,3L3,3c-1.1,0 -2,0.9 -2,2v14c0,1.1 0.9,1.98 2,1.98h18c1.1,0 2,-0.88 2,-1.98L23,5c0,-1.1 -0.9,-2 -2,-2zM21,19.01L3,19.01L3,4.98h18v14.03z"/>
-</vector>
\ No newline at end of file
diff --git a/packages/SystemUI/res/drawable/pip_resize_handle.xml b/packages/SystemUI/res/drawable/pip_resize_handle.xml
deleted file mode 100644
index 0a8cbc4..0000000
--- a/packages/SystemUI/res/drawable/pip_resize_handle.xml
+++ /dev/null
@@ -1,29 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
-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.
--->
-<vector xmlns:android="http://schemas.android.com/apk/res/android"
- android:width="12.0dp"
- android:height="12.0dp"
- android:viewportWidth="12"
- android:viewportHeight="12">
- <group
- android:translateX="12"
- android:rotation="90">
- <path
- android:fillColor="#FFFFFF"
- android:pathData="M3.41421 0L2 1.41422L10.4853 9.8995L11.8995 8.48528L3.41421 0ZM2.41421 4.24268L1 5.65689L6.65685 11.3137L8.07107 9.89953L2.41421 4.24268Z" />
- </group>
-</vector>
diff --git a/packages/SystemUI/res/drawable/qs_bg_gradient.xml b/packages/SystemUI/res/drawable/qs_bg_gradient.xml
deleted file mode 100644
index a1ad528..0000000
--- a/packages/SystemUI/res/drawable/qs_bg_gradient.xml
+++ /dev/null
@@ -1,24 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- 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.
--->
-<shape
- xmlns:android="http://schemas.android.com/apk/res/android"
- android:shape="rectangle">
- <gradient
- android:angle="270"
- android:startColor="#ff000000"
- android:endColor="#00000000"
- android:type="linear" />
-</shape>
diff --git a/packages/SystemUI/res/drawable/qs_dual_tile_caret.xml b/packages/SystemUI/res/drawable/qs_dual_tile_caret.xml
deleted file mode 100644
index e27bc7a..0000000
--- a/packages/SystemUI/res/drawable/qs_dual_tile_caret.xml
+++ /dev/null
@@ -1,25 +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.
--->
-<vector xmlns:android="http://schemas.android.com/apk/res/android"
- android:width="18.0dp"
- android:height="18.0dp"
- android:viewportWidth="48.0"
- android:viewportHeight="48.0">
-
- <path
- android:fillColor="#FFFFFFFF"
- android:pathData="M14.0,20.0l10.0,10.0 10.0,-10.0z"/>
-</vector>
diff --git a/packages/SystemUI/res/drawable/rounded_bg_bottom_background.xml b/packages/SystemUI/res/drawable/rounded_bg_bottom_background.xml
deleted file mode 100644
index 382ca20..0000000
--- a/packages/SystemUI/res/drawable/rounded_bg_bottom_background.xml
+++ /dev/null
@@ -1,11 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<shape xmlns:android="http://schemas.android.com/apk/res/android"
- android:shape="rectangle">
- <solid android:color="?android:attr/panelColorBackground" />
- <corners
- android:bottomLeftRadius="?android:attr/dialogCornerRadius"
- android:topLeftRadius="0dp"
- android:bottomRightRadius="?android:attr/dialogCornerRadius"
- android:topRightRadius="0dp"
- />
-</shape>
diff --git a/packages/SystemUI/res/drawable/rounded_bg_top.xml b/packages/SystemUI/res/drawable/rounded_bg_top.xml
deleted file mode 100644
index 988ab58..0000000
--- a/packages/SystemUI/res/drawable/rounded_bg_top.xml
+++ /dev/null
@@ -1,22 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- 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.
--->
-<shape xmlns:android="http://schemas.android.com/apk/res/android"
- android:shape="rectangle">
- <solid android:color="?android:attr/colorPrimaryDark" />
- <corners
- android:topLeftRadius="?android:attr/dialogCornerRadius"
- android:topRightRadius="?android:attr/dialogCornerRadius" />
-</shape>
diff --git a/packages/SystemUI/res/drawable/screenrecord_switch_thumb.xml b/packages/SystemUI/res/drawable/screenrecord_switch_thumb.xml
deleted file mode 100644
index f78c582..0000000
--- a/packages/SystemUI/res/drawable/screenrecord_switch_thumb.xml
+++ /dev/null
@@ -1,29 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
- ~ Copyright (C) 2021 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
- android:top="4dp"
- android:left="4dp"
- android:right="4dp"
- android:bottom="4dp">
- <shape android:shape="oval" >
- <size android:height="20dp" android:width="20dp" />
- <solid android:color="@color/screenrecord_switch_thumb_color" />
- </shape>
- </item>
-</layer-list>
\ No newline at end of file
diff --git a/packages/SystemUI/res/drawable/screenrecord_switch_track.xml b/packages/SystemUI/res/drawable/screenrecord_switch_track.xml
deleted file mode 100644
index 82595e4..0000000
--- a/packages/SystemUI/res/drawable/screenrecord_switch_track.xml
+++ /dev/null
@@ -1,24 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
- ~ Copyright (C) 2021 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"
- android:shape="rectangle"
- android:width="52dp"
- android:height="28dp">
- <solid android:color="@color/screenrecord_switch_track_color" />
- <corners android:radius="35dp" />
-</shape>
\ No newline at end of file
diff --git a/packages/SystemUI/res/drawable/screenshot_rounded_corners.xml b/packages/SystemUI/res/drawable/screenshot_rounded_corners.xml
deleted file mode 100644
index fb8e9b7..0000000
--- a/packages/SystemUI/res/drawable/screenshot_rounded_corners.xml
+++ /dev/null
@@ -1,20 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
- ~ 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.
- -->
-<shape xmlns:android="http://schemas.android.com/apk/res/android"
- android:shape="rectangle">
- <corners android:radius="@dimen/screenshot_button_corner_radius"/>
-</shape>
diff --git a/packages/SystemUI/res/drawable/settingslib_switch_bar_bg_disabled.xml b/packages/SystemUI/res/drawable/settingslib_switch_bar_bg_disabled.xml
deleted file mode 100644
index 088e82b..0000000
--- a/packages/SystemUI/res/drawable/settingslib_switch_bar_bg_disabled.xml
+++ /dev/null
@@ -1,26 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
- Copyright (C) 2021 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.
- -->
-
-<ripple xmlns:android="http://schemas.android.com/apk/res/android"
- android:color="?android:attr/colorControlHighlight">
- <item>
- <shape android:shape="rectangle">
- <solid android:color="@color/settingslib_state_off_color"/>
- <corners android:radius="@dimen/settingslib_switch_bar_radius"/>
- </shape>
- </item>
-</ripple>
diff --git a/packages/SystemUI/res/drawable/stat_notify_image.xml b/packages/SystemUI/res/drawable/stat_notify_image.xml
deleted file mode 100644
index c8745d7..0000000
--- a/packages/SystemUI/res/drawable/stat_notify_image.xml
+++ /dev/null
@@ -1,28 +0,0 @@
-<!--
-Copyright (C) 2016 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="24dp"
- android:height="24dp"
- android:viewportWidth="24"
- android:viewportHeight="24">
-
- <path
- android:fillColor="#FFFFFFFF"
- android:pathData="M21,19V5c0-1.1-0.9-2-2-2H5C3.9,3,3,3.9,3,5v14c0,1.1,0.9,2,2,2h14C20.1,21,21,20.1,21,19z
-M8.5,13.5l2.5,3l3.5-4.5l4.5,6H5 L8.5,13.5z" />
- <path
- android:pathData="M0,0h24v24H0V0z" />
-</vector>
\ No newline at end of file
diff --git a/packages/SystemUI/res/drawable/stat_sys_camera.xml b/packages/SystemUI/res/drawable/stat_sys_camera.xml
deleted file mode 100644
index c914262..0000000
--- a/packages/SystemUI/res/drawable/stat_sys_camera.xml
+++ /dev/null
@@ -1,22 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
-**
-** Copyright 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.
-*/
--->
-<inset xmlns:android="http://schemas.android.com/apk/res/android"
- android:insetLeft="3dp"
- android:insetRight="3dp"
- android:drawable="@drawable/ic_camera" />
\ No newline at end of file
diff --git a/packages/SystemUI/res/drawable/stat_sys_location.xml b/packages/SystemUI/res/drawable/stat_sys_location.xml
deleted file mode 100644
index 7a5aeb9..0000000
--- a/packages/SystemUI/res/drawable/stat_sys_location.xml
+++ /dev/null
@@ -1,19 +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
- -->
-<inset xmlns:android="http://schemas.android.com/apk/res/android"
- android:insetLeft="2.5dp"
- android:insetRight="2.5dp"
- android:drawable="@drawable/ic_location" />
diff --git a/packages/SystemUI/res/drawable/stat_sys_mic_none.xml b/packages/SystemUI/res/drawable/stat_sys_mic_none.xml
deleted file mode 100644
index d6bdf9f..0000000
--- a/packages/SystemUI/res/drawable/stat_sys_mic_none.xml
+++ /dev/null
@@ -1,30 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
-**
-** Copyright 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.
-*/
--->
-<vector xmlns:android="http://schemas.android.com/apk/res/android"
- android:width="18dp"
- android:height="18dp"
- android:viewportWidth="24.0"
- android:viewportHeight="24.0">
- <path
- android:fillColor="#FFF"
- android:pathData="M12,14c1.66,0 3,-1.34 3,-3V5c0,-1.66 -1.34,-3 -3,-3S9,3.34 9,5v6C9,12.66 10.34,14 12,14zM11,5c0,-0.55 0.45,-1 1,-1s1,0.45 1,1v6c0,0.55 -0.45,1 -1,1s-1,-0.45 -1,-1V5z"/>
- <path
- android:fillColor="#FFF"
- android:pathData="M17,11c0,2.76 -2.24,5 -5,5s-5,-2.24 -5,-5H5c0,3.53 2.61,6.43 6,6.92V21h2v-3.08c3.39,-0.49 6,-3.39 6,-6.92H17z"/>
-</vector>
diff --git a/packages/SystemUI/res/drawable/tv_ic_mic_white.xml b/packages/SystemUI/res/drawable/tv_ic_mic_white.xml
deleted file mode 100644
index d887113..0000000
--- a/packages/SystemUI/res/drawable/tv_ic_mic_white.xml
+++ /dev/null
@@ -1,27 +0,0 @@
-<!--
-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.
--->
-<vector xmlns:android="http://schemas.android.com/apk/res/android"
- android:width="32dp"
- android:height="32dp"
- android:viewportWidth="24.0"
- android:viewportHeight="24.0">
- <path
- android:fillColor="#FFFFFFFF"
- android:pathData="M12,14c1.66,0 3,-1.34 3,-3V5c0,-1.66 -1.34,-3 -3,-3S9,3.34 9,5v6C9,12.66 10.34,14 12,14zM11,5c0,-0.55 0.45,-1 1,-1s1,0.45 1,1v6c0,0.55 -0.45,1 -1,1s-1,-0.45 -1,-1V5z"/>
- <path
- android:fillColor="#FFFFFFFF"
- android:pathData="M17,11c0,2.76 -2.24,5 -5,5s-5,-2.24 -5,-5H5c0,3.53 2.61,6.43 6,6.92V21h2v-3.08c3.39,-0.49 6,-3.39 6,-6.92H17z"/>
-</vector>
\ No newline at end of file
diff --git a/packages/SystemUI/res/interpolator/assist_disclosure_trace.xml b/packages/SystemUI/res/interpolator/assist_disclosure_trace.xml
deleted file mode 100644
index 6b5cd37..0000000
--- a/packages/SystemUI/res/interpolator/assist_disclosure_trace.xml
+++ /dev/null
@@ -1,22 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
- ~ Copyright (C) 2015 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
- -->
-
-<pathInterpolator xmlns:android="http://schemas.android.com/apk/res/android"
- android:controlX1="0.6"
- android:controlY1="0"
- android:controlX2="0.7"
- android:controlY2="1"/>
\ No newline at end of file
diff --git a/packages/SystemUI/res/interpolator/error_to_trustedstate_animation_interpolator_0.xml b/packages/SystemUI/res/interpolator/error_to_trustedstate_animation_interpolator_0.xml
deleted file mode 100644
index 7f4fdbf..0000000
--- a/packages/SystemUI/res/interpolator/error_to_trustedstate_animation_interpolator_0.xml
+++ /dev/null
@@ -1,19 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
-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.
--->
-<pathInterpolator
- xmlns:android="http://schemas.android.com/apk/res/android"
- android:pathData="M 0.0,0.0 c 1.0,0.0 0.6,1.0 1.0,1.0" />
diff --git a/packages/SystemUI/res/interpolator/error_to_trustedstate_animation_interpolator_1.xml b/packages/SystemUI/res/interpolator/error_to_trustedstate_animation_interpolator_1.xml
deleted file mode 100644
index 1695962..0000000
--- a/packages/SystemUI/res/interpolator/error_to_trustedstate_animation_interpolator_1.xml
+++ /dev/null
@@ -1,19 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
-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.
--->
-<pathInterpolator
- xmlns:android="http://schemas.android.com/apk/res/android"
- android:pathData="M 0.0,0.0 c 0.4,0.0 0.6,1.0 1.0,1.0" />
diff --git a/packages/SystemUI/res/interpolator/error_to_trustedstate_animation_interpolator_2.xml b/packages/SystemUI/res/interpolator/error_to_trustedstate_animation_interpolator_2.xml
deleted file mode 100644
index 91c08f8..0000000
--- a/packages/SystemUI/res/interpolator/error_to_trustedstate_animation_interpolator_2.xml
+++ /dev/null
@@ -1,19 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
-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.
--->
-<pathInterpolator
- xmlns:android="http://schemas.android.com/apk/res/android"
- android:pathData="M 0.0,0.0 l 0.236439499305,0.0 c 0.763560500695,0.0 0.458136300417,1.0 0.763560500695,1.0 L 1.0,1.0" />
diff --git a/packages/SystemUI/res/interpolator/error_to_trustedstate_animation_interpolator_3.xml b/packages/SystemUI/res/interpolator/error_to_trustedstate_animation_interpolator_3.xml
deleted file mode 100644
index f5cbc31..0000000
--- a/packages/SystemUI/res/interpolator/error_to_trustedstate_animation_interpolator_3.xml
+++ /dev/null
@@ -1,19 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
-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.
--->
-<pathInterpolator
- xmlns:android="http://schemas.android.com/apk/res/android"
- android:pathData="M 0.0,0.0 c 0.00100000000001,0.0 0.2,1.0 1.0,1.0" />
diff --git a/packages/SystemUI/res/interpolator/error_to_trustedstate_animation_interpolator_4.xml b/packages/SystemUI/res/interpolator/error_to_trustedstate_animation_interpolator_4.xml
deleted file mode 100644
index cf21d81..0000000
--- a/packages/SystemUI/res/interpolator/error_to_trustedstate_animation_interpolator_4.xml
+++ /dev/null
@@ -1,19 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
-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.
--->
-<pathInterpolator
- xmlns:android="http://schemas.android.com/apk/res/android"
- android:pathData="M 0.0,0.0 c 0.00100000000002,0.0 0.2,1.0 1.0,1.0" />
diff --git a/packages/SystemUI/res/interpolator/error_to_trustedstate_animation_interpolator_5.xml b/packages/SystemUI/res/interpolator/error_to_trustedstate_animation_interpolator_5.xml
deleted file mode 100644
index 0c18d92..0000000
--- a/packages/SystemUI/res/interpolator/error_to_trustedstate_animation_interpolator_5.xml
+++ /dev/null
@@ -1,19 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
-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.
--->
-<pathInterpolator
- xmlns:android="http://schemas.android.com/apk/res/android"
- android:pathData="M 0.0,0.0 c 0.8,0.0 0.2,1.0 1.0,1.0" />
diff --git a/packages/SystemUI/res/interpolator/error_to_trustedstate_animation_interpolator_6.xml b/packages/SystemUI/res/interpolator/error_to_trustedstate_animation_interpolator_6.xml
deleted file mode 100644
index 0bf41e5..0000000
--- a/packages/SystemUI/res/interpolator/error_to_trustedstate_animation_interpolator_6.xml
+++ /dev/null
@@ -1,19 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
-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.
--->
-<pathInterpolator
- xmlns:android="http://schemas.android.com/apk/res/android"
- android:pathData="M 0.0,0.0 c 0.2,0.0 0.0,1.0 1.0,1.0" />
diff --git a/packages/SystemUI/res/interpolator/ic_caret_down_animation_interpolator_0.xml b/packages/SystemUI/res/interpolator/ic_caret_down_animation_interpolator_0.xml
deleted file mode 100644
index ed90d64..0000000
--- a/packages/SystemUI/res/interpolator/ic_caret_down_animation_interpolator_0.xml
+++ /dev/null
@@ -1,19 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
- 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.
--->
-<pathInterpolator
- xmlns:android="http://schemas.android.com/apk/res/android"
- android:pathData="M 0.0,0.0 c 0.2,0.0 0.0,1.0 1.0,1.0" />
diff --git a/packages/SystemUI/res/interpolator/ic_caret_up_animation_interpolator_0.xml b/packages/SystemUI/res/interpolator/ic_caret_up_animation_interpolator_0.xml
deleted file mode 100644
index ed90d64..0000000
--- a/packages/SystemUI/res/interpolator/ic_caret_up_animation_interpolator_0.xml
+++ /dev/null
@@ -1,19 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
- 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.
--->
-<pathInterpolator
- xmlns:android="http://schemas.android.com/apk/res/android"
- android:pathData="M 0.0,0.0 c 0.2,0.0 0.0,1.0 1.0,1.0" />
diff --git a/packages/SystemUI/res/interpolator/ic_fingerprint_toerror_animation_interpolator_0.xml b/packages/SystemUI/res/interpolator/ic_fingerprint_toerror_animation_interpolator_0.xml
deleted file mode 100644
index fcd751d..0000000
--- a/packages/SystemUI/res/interpolator/ic_fingerprint_toerror_animation_interpolator_0.xml
+++ /dev/null
@@ -1,19 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
-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.
--->
-<pathInterpolator
- xmlns:android="http://schemas.android.com/apk/res/android"
- android:pathData="M 0.0,0.0 c 0.16666666667,0.0 0.83333333333,1.0 1.0,1.0" />
diff --git a/packages/SystemUI/res/interpolator/ic_fingerprint_toerror_animation_interpolator_1.xml b/packages/SystemUI/res/interpolator/ic_fingerprint_toerror_animation_interpolator_1.xml
deleted file mode 100644
index 38dbdb7..0000000
--- a/packages/SystemUI/res/interpolator/ic_fingerprint_toerror_animation_interpolator_1.xml
+++ /dev/null
@@ -1,19 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
-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.
--->
-<pathInterpolator
- xmlns:android="http://schemas.android.com/apk/res/android"
- android:pathData="M 0.0,0.0 c 0.8,0.0 0.5,1.0 1.0,1.0" />
diff --git a/packages/SystemUI/res/interpolator/ic_fingerprint_toerror_animation_interpolator_2.xml b/packages/SystemUI/res/interpolator/ic_fingerprint_toerror_animation_interpolator_2.xml
deleted file mode 100644
index 1695962..0000000
--- a/packages/SystemUI/res/interpolator/ic_fingerprint_toerror_animation_interpolator_2.xml
+++ /dev/null
@@ -1,19 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
-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.
--->
-<pathInterpolator
- xmlns:android="http://schemas.android.com/apk/res/android"
- android:pathData="M 0.0,0.0 c 0.4,0.0 0.6,1.0 1.0,1.0" />
diff --git a/packages/SystemUI/res/interpolator/ic_fingerprint_toerror_animation_interpolator_3.xml b/packages/SystemUI/res/interpolator/ic_fingerprint_toerror_animation_interpolator_3.xml
deleted file mode 100644
index 8538f98..0000000
--- a/packages/SystemUI/res/interpolator/ic_fingerprint_toerror_animation_interpolator_3.xml
+++ /dev/null
@@ -1,19 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
-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.
--->
-<pathInterpolator
- xmlns:android="http://schemas.android.com/apk/res/android"
- android:pathData="M 0.0,0.0 l 0.286298568507,0.0 c 0.142740286299,0.0 0.0,1.0 0.713701431493,1.0 L 1.0,1.0" />
diff --git a/packages/SystemUI/res/interpolator/ic_fingerprint_toerror_animation_interpolator_4.xml b/packages/SystemUI/res/interpolator/ic_fingerprint_toerror_animation_interpolator_4.xml
deleted file mode 100644
index 0bf41e5..0000000
--- a/packages/SystemUI/res/interpolator/ic_fingerprint_toerror_animation_interpolator_4.xml
+++ /dev/null
@@ -1,19 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
-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.
--->
-<pathInterpolator
- xmlns:android="http://schemas.android.com/apk/res/android"
- android:pathData="M 0.0,0.0 c 0.2,0.0 0.0,1.0 1.0,1.0" />
diff --git a/packages/SystemUI/res/interpolator/ic_fingerprint_toerror_animation_interpolator_5.xml b/packages/SystemUI/res/interpolator/ic_fingerprint_toerror_animation_interpolator_5.xml
deleted file mode 100644
index 2202094..0000000
--- a/packages/SystemUI/res/interpolator/ic_fingerprint_toerror_animation_interpolator_5.xml
+++ /dev/null
@@ -1,19 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
-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.
--->
-<pathInterpolator
- xmlns:android="http://schemas.android.com/apk/res/android"
- android:pathData="M 0.0,0.0 c 0.00010,0.0 0.2,1.0 1.0,1.0" />
diff --git a/packages/SystemUI/res/interpolator/ic_fingerprint_toerror_animation_interpolator_6.xml b/packages/SystemUI/res/interpolator/ic_fingerprint_toerror_animation_interpolator_6.xml
deleted file mode 100644
index 0c18d92..0000000
--- a/packages/SystemUI/res/interpolator/ic_fingerprint_toerror_animation_interpolator_6.xml
+++ /dev/null
@@ -1,19 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
-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.
--->
-<pathInterpolator
- xmlns:android="http://schemas.android.com/apk/res/android"
- android:pathData="M 0.0,0.0 c 0.8,0.0 0.2,1.0 1.0,1.0" />
diff --git a/packages/SystemUI/res/interpolator/ic_fingerprint_tofp_animation_interpolator_0.xml b/packages/SystemUI/res/interpolator/ic_fingerprint_tofp_animation_interpolator_0.xml
deleted file mode 100644
index ac1b566..0000000
--- a/packages/SystemUI/res/interpolator/ic_fingerprint_tofp_animation_interpolator_0.xml
+++ /dev/null
@@ -1,19 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
-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.
--->
-<pathInterpolator
- xmlns:android="http://schemas.android.com/apk/res/android"
- android:pathData="M 0.0,0.0 l 0.555555555556,0.0 c 0.177777777778,0.0 0.0888888888889,1.0 0.444444444444,1.0 L 1.0,1.0" />
diff --git a/packages/SystemUI/res/interpolator/ic_fingerprint_tofp_animation_interpolator_1.xml b/packages/SystemUI/res/interpolator/ic_fingerprint_tofp_animation_interpolator_1.xml
deleted file mode 100644
index 7f4fdbf..0000000
--- a/packages/SystemUI/res/interpolator/ic_fingerprint_tofp_animation_interpolator_1.xml
+++ /dev/null
@@ -1,19 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
-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.
--->
-<pathInterpolator
- xmlns:android="http://schemas.android.com/apk/res/android"
- android:pathData="M 0.0,0.0 c 1.0,0.0 0.6,1.0 1.0,1.0" />
diff --git a/packages/SystemUI/res/interpolator/ic_fingerprint_tofp_animation_interpolator_2.xml b/packages/SystemUI/res/interpolator/ic_fingerprint_tofp_animation_interpolator_2.xml
deleted file mode 100644
index 1695962..0000000
--- a/packages/SystemUI/res/interpolator/ic_fingerprint_tofp_animation_interpolator_2.xml
+++ /dev/null
@@ -1,19 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
-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.
--->
-<pathInterpolator
- xmlns:android="http://schemas.android.com/apk/res/android"
- android:pathData="M 0.0,0.0 c 0.4,0.0 0.6,1.0 1.0,1.0" />
diff --git a/packages/SystemUI/res/interpolator/ic_fingerprint_tofp_animation_interpolator_3.xml b/packages/SystemUI/res/interpolator/ic_fingerprint_tofp_animation_interpolator_3.xml
deleted file mode 100644
index 02c6cd5..0000000
--- a/packages/SystemUI/res/interpolator/ic_fingerprint_tofp_animation_interpolator_3.xml
+++ /dev/null
@@ -1,19 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
-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.
--->
-<pathInterpolator
- xmlns:android="http://schemas.android.com/apk/res/android"
- android:pathData="M 0.0,0.0 l 0.445544554455,0.0 c 0.554455445545,0.0 0.332673267327,1.0 0.554455445545,1.0 L 1.0,1.0" />
diff --git a/packages/SystemUI/res/interpolator/ic_fingerprint_tofp_animation_interpolator_4.xml b/packages/SystemUI/res/interpolator/ic_fingerprint_tofp_animation_interpolator_4.xml
deleted file mode 100644
index 7ae249e..0000000
--- a/packages/SystemUI/res/interpolator/ic_fingerprint_tofp_animation_interpolator_4.xml
+++ /dev/null
@@ -1,19 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
-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.
--->
-<pathInterpolator
- xmlns:android="http://schemas.android.com/apk/res/android"
- android:pathData="M 0.0,0.0 c 0.00010,0.0 0.6,1.0 1.0,1.0" />
diff --git a/packages/SystemUI/res/interpolator/ic_fingerprint_tofp_animation_interpolator_5.xml b/packages/SystemUI/res/interpolator/ic_fingerprint_tofp_animation_interpolator_5.xml
deleted file mode 100644
index 0c18d92..0000000
--- a/packages/SystemUI/res/interpolator/ic_fingerprint_tofp_animation_interpolator_5.xml
+++ /dev/null
@@ -1,19 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
-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.
--->
-<pathInterpolator
- xmlns:android="http://schemas.android.com/apk/res/android"
- android:pathData="M 0.0,0.0 c 0.8,0.0 0.2,1.0 1.0,1.0" />
diff --git a/packages/SystemUI/res/interpolator/ic_landscape_to_rotate_animation_interpolator_0.xml b/packages/SystemUI/res/interpolator/ic_landscape_to_rotate_animation_interpolator_0.xml
deleted file mode 100644
index 793e7ff..0000000
--- a/packages/SystemUI/res/interpolator/ic_landscape_to_rotate_animation_interpolator_0.xml
+++ /dev/null
@@ -1,19 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
- 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.
--->
-<pathInterpolator
- xmlns:android="http://schemas.android.com/apk/res/android"
- android:pathData="M 0.0,0.0 c 0.4,0.0 0.6,1.0 1.0,1.0" />
diff --git a/packages/SystemUI/res/interpolator/ic_rotate_to_landscape_animation_interpolator_0.xml b/packages/SystemUI/res/interpolator/ic_rotate_to_landscape_animation_interpolator_0.xml
deleted file mode 100644
index 793e7ff..0000000
--- a/packages/SystemUI/res/interpolator/ic_rotate_to_landscape_animation_interpolator_0.xml
+++ /dev/null
@@ -1,19 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
- 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.
--->
-<pathInterpolator
- xmlns:android="http://schemas.android.com/apk/res/android"
- android:pathData="M 0.0,0.0 c 0.4,0.0 0.6,1.0 1.0,1.0" />
diff --git a/packages/SystemUI/res/interpolator/ic_rotate_to_portrait_animation_interpolator_0.xml b/packages/SystemUI/res/interpolator/ic_rotate_to_portrait_animation_interpolator_0.xml
deleted file mode 100644
index 793e7ff..0000000
--- a/packages/SystemUI/res/interpolator/ic_rotate_to_portrait_animation_interpolator_0.xml
+++ /dev/null
@@ -1,19 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
- 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.
--->
-<pathInterpolator
- xmlns:android="http://schemas.android.com/apk/res/android"
- android:pathData="M 0.0,0.0 c 0.4,0.0 0.6,1.0 1.0,1.0" />
diff --git a/packages/SystemUI/res/interpolator/lockscreen_fingerprint_draw_off_animation_interpolator_0.xml b/packages/SystemUI/res/interpolator/lockscreen_fingerprint_draw_off_animation_interpolator_0.xml
deleted file mode 100644
index e8c1f90..0000000
--- a/packages/SystemUI/res/interpolator/lockscreen_fingerprint_draw_off_animation_interpolator_0.xml
+++ /dev/null
@@ -1,19 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
- ~ Copyright (C) 2015 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
- -->
-<pathInterpolator
- xmlns:android="http://schemas.android.com/apk/res/android"
- android:pathData="M 0.0,0.0 c 0.5,0.0 1.0,1.0 1.0,1.0" />
diff --git a/packages/SystemUI/res/interpolator/lockscreen_fingerprint_draw_off_animation_interpolator_1.xml b/packages/SystemUI/res/interpolator/lockscreen_fingerprint_draw_off_animation_interpolator_1.xml
deleted file mode 100644
index cb59de9..0000000
--- a/packages/SystemUI/res/interpolator/lockscreen_fingerprint_draw_off_animation_interpolator_1.xml
+++ /dev/null
@@ -1,19 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
- ~ Copyright (C) 2015 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
- -->
-<pathInterpolator
- xmlns:android="http://schemas.android.com/apk/res/android"
- android:pathData="M 0.0,0.0 c 0.5,0.0 0.5,1.0 1.0,1.0" />
diff --git a/packages/SystemUI/res/interpolator/lockscreen_fingerprint_draw_on_animation_interpolator_0.xml b/packages/SystemUI/res/interpolator/lockscreen_fingerprint_draw_on_animation_interpolator_0.xml
deleted file mode 100644
index 708de2a..0000000
--- a/packages/SystemUI/res/interpolator/lockscreen_fingerprint_draw_on_animation_interpolator_0.xml
+++ /dev/null
@@ -1,19 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
- ~ Copyright (C) 2015 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
- -->
-<pathInterpolator
- xmlns:android="http://schemas.android.com/apk/res/android"
- android:pathData="M 0.0,0.0 c 0.0,0.0 0.29,1.0 1.0,1.0" />
diff --git a/packages/SystemUI/res/interpolator/lockscreen_fingerprint_draw_on_animation_interpolator_1.xml b/packages/SystemUI/res/interpolator/lockscreen_fingerprint_draw_on_animation_interpolator_1.xml
deleted file mode 100644
index a5ffc40..0000000
--- a/packages/SystemUI/res/interpolator/lockscreen_fingerprint_draw_on_animation_interpolator_1.xml
+++ /dev/null
@@ -1,19 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
- ~ Copyright (C) 2015 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
- -->
-<pathInterpolator
- xmlns:android="http://schemas.android.com/apk/res/android"
- android:pathData="M 0.0,0.0 c 0.0,0.0 0.5,1.0 1.0,1.0" />
diff --git a/packages/SystemUI/res/interpolator/trusted_state_to_error_animation_interpolator_0.xml b/packages/SystemUI/res/interpolator/trusted_state_to_error_animation_interpolator_0.xml
deleted file mode 100644
index 7f4fdbf..0000000
--- a/packages/SystemUI/res/interpolator/trusted_state_to_error_animation_interpolator_0.xml
+++ /dev/null
@@ -1,19 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
-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.
--->
-<pathInterpolator
- xmlns:android="http://schemas.android.com/apk/res/android"
- android:pathData="M 0.0,0.0 c 1.0,0.0 0.6,1.0 1.0,1.0" />
diff --git a/packages/SystemUI/res/interpolator/trusted_state_to_error_animation_interpolator_1.xml b/packages/SystemUI/res/interpolator/trusted_state_to_error_animation_interpolator_1.xml
deleted file mode 100644
index 1695962..0000000
--- a/packages/SystemUI/res/interpolator/trusted_state_to_error_animation_interpolator_1.xml
+++ /dev/null
@@ -1,19 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
-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.
--->
-<pathInterpolator
- xmlns:android="http://schemas.android.com/apk/res/android"
- android:pathData="M 0.0,0.0 c 0.4,0.0 0.6,1.0 1.0,1.0" />
diff --git a/packages/SystemUI/res/interpolator/trusted_state_to_error_animation_interpolator_2.xml b/packages/SystemUI/res/interpolator/trusted_state_to_error_animation_interpolator_2.xml
deleted file mode 100644
index 138851e..0000000
--- a/packages/SystemUI/res/interpolator/trusted_state_to_error_animation_interpolator_2.xml
+++ /dev/null
@@ -1,19 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
-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.
--->
-<pathInterpolator
- xmlns:android="http://schemas.android.com/apk/res/android"
- android:pathData="M 0.0,0.0 c 0.001,0.0 0.2,1.0 1.0,1.0" />
diff --git a/packages/SystemUI/res/interpolator/trusted_state_to_error_animation_interpolator_3.xml b/packages/SystemUI/res/interpolator/trusted_state_to_error_animation_interpolator_3.xml
deleted file mode 100644
index 7657cb6..0000000
--- a/packages/SystemUI/res/interpolator/trusted_state_to_error_animation_interpolator_3.xml
+++ /dev/null
@@ -1,19 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
-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.
--->
-<pathInterpolator
- xmlns:android="http://schemas.android.com/apk/res/android"
- android:pathData="M 0.0,0.0 l 0.364238410596,0.0 c 0.127152317881,0.0 0.0,1.0 0.635761589404,1.0 L 1.0,1.0" />
diff --git a/packages/SystemUI/res/interpolator/trusted_state_to_error_animation_interpolator_4.xml b/packages/SystemUI/res/interpolator/trusted_state_to_error_animation_interpolator_4.xml
deleted file mode 100644
index 3e5efd7..0000000
--- a/packages/SystemUI/res/interpolator/trusted_state_to_error_animation_interpolator_4.xml
+++ /dev/null
@@ -1,19 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
-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.
--->
-<pathInterpolator
- xmlns:android="http://schemas.android.com/apk/res/android"
- android:pathData="M 0.0,0.0 l 0.4,0.0 c 0.0006,0.0 0.12,1.0 0.6,1.0 L 1.0,1.0" />
diff --git a/packages/SystemUI/res/interpolator/trusted_state_to_error_animation_interpolator_5.xml b/packages/SystemUI/res/interpolator/trusted_state_to_error_animation_interpolator_5.xml
deleted file mode 100644
index 2202094..0000000
--- a/packages/SystemUI/res/interpolator/trusted_state_to_error_animation_interpolator_5.xml
+++ /dev/null
@@ -1,19 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
-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.
--->
-<pathInterpolator
- xmlns:android="http://schemas.android.com/apk/res/android"
- android:pathData="M 0.0,0.0 c 0.00010,0.0 0.2,1.0 1.0,1.0" />
diff --git a/packages/SystemUI/res/interpolator/wireless_charging_animation_interpolator_0.xml b/packages/SystemUI/res/interpolator/wireless_charging_animation_interpolator_0.xml
deleted file mode 100644
index 3fe59ae..0000000
--- a/packages/SystemUI/res/interpolator/wireless_charging_animation_interpolator_0.xml
+++ /dev/null
@@ -1,21 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
-/*
-** Copyright 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.
-*/
--->
-<pathInterpolator
- xmlns:android="http://schemas.android.com/apk/res/android"
- android:pathData="M 0.0,0.0 c 0.001,0.0 0.2,1.0 1.0,1.0" />
diff --git a/packages/SystemUI/res/interpolator/wireless_charging_animation_interpolator_1.xml b/packages/SystemUI/res/interpolator/wireless_charging_animation_interpolator_1.xml
deleted file mode 100644
index 3fe59ae..0000000
--- a/packages/SystemUI/res/interpolator/wireless_charging_animation_interpolator_1.xml
+++ /dev/null
@@ -1,21 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
-/*
-** Copyright 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.
-*/
--->
-<pathInterpolator
- xmlns:android="http://schemas.android.com/apk/res/android"
- android:pathData="M 0.0,0.0 c 0.001,0.0 0.2,1.0 1.0,1.0" />
diff --git a/packages/SystemUI/res/layout-land/global_actions_column_seascape.xml b/packages/SystemUI/res/layout-land/global_actions_column_seascape.xml
deleted file mode 100644
index 412beb7..0000000
--- a/packages/SystemUI/res/layout-land/global_actions_column_seascape.xml
+++ /dev/null
@@ -1,68 +0,0 @@
-<?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
- -->
-
-<com.android.systemui.globalactions.GlobalActionsColumnLayout
- xmlns:android="http://schemas.android.com/apk/res/android"
- android:id="@id/global_actions_view"
- android:layout_width="match_parent"
- android:layout_height="match_parent"
- android:orientation="horizontal"
- android:clipToPadding="false"
- android:theme="@style/Theme.SystemUI.QuickSettings"
- android:gravity="center_horizontal | bottom"
- android:clipChildren="false"
->
- <LinearLayout
- android:layout_height="wrap_content"
- android:layout_width="wrap_content"
- android:padding="0dp"
- android:orientation="horizontal"
- >
- <!-- Grid of action items -->
- <com.android.systemui.globalactions.ListGridLayout
- android:id="@android:id/list"
- android:layout_gravity="bottom|left"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:orientation="horizontal"
- android:layout_marginBottom="@dimen/global_actions_grid_side_margin"
- android:translationZ="@dimen/global_actions_translate"
- android:paddingLeft="@dimen/global_actions_grid_vertical_padding"
- android:paddingRight="@dimen/global_actions_grid_vertical_padding"
- android:paddingTop="@dimen/global_actions_grid_horizontal_padding"
- android:paddingBottom="@dimen/global_actions_grid_horizontal_padding"
- android:background="?android:attr/colorBackgroundFloating"
- />
- <!-- For separated items-->
- <LinearLayout
- android:id="@+id/separated_button"
- android:layout_gravity="top|left"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:layout_marginRight="@dimen/global_actions_grid_side_margin"
- android:layout_marginBottom="@dimen/global_actions_grid_side_margin"
- android:paddingLeft="@dimen/global_actions_grid_vertical_padding"
- android:paddingRight="@dimen/global_actions_grid_vertical_padding"
- android:paddingTop="@dimen/global_actions_grid_horizontal_padding"
- android:paddingBottom="@dimen/global_actions_grid_horizontal_padding"
- android:orientation="horizontal"
- android:background="?android:attr/colorBackgroundFloating"
- android:translationZ="@dimen/global_actions_translate"
- />
- </LinearLayout>
-
-</com.android.systemui.globalactions.GlobalActionsColumnLayout>
diff --git a/packages/SystemUI/res/layout-land/global_actions_grid_item.xml b/packages/SystemUI/res/layout-land/global_actions_grid_item.xml
deleted file mode 100644
index 0f9deaa..0000000
--- a/packages/SystemUI/res/layout-land/global_actions_grid_item.xml
+++ /dev/null
@@ -1,61 +0,0 @@
-<?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
- -->
-
-<!-- RelativeLayouts have an issue enforcing minimum heights, so just
- work around this for now with LinearLayouts. -->
-<LinearLayout
- xmlns:android="http://schemas.android.com/apk/res/android"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:gravity="center"
- android:layout_marginTop="@dimen/global_actions_grid_item_side_margin"
- android:layout_marginBottom="@dimen/global_actions_grid_item_side_margin"
- android:layout_marginLeft="@dimen/global_actions_grid_item_vertical_margin"
- android:layout_marginRight="@dimen/global_actions_grid_item_vertical_margin"
->
- <LinearLayout
- android:layout_width="@dimen/global_actions_grid_item_height"
- android:layout_height="@dimen/global_actions_grid_item_width"
- android:gravity="top|center_horizontal"
- android:orientation="vertical"
- >
- <ImageView
- android:id="@*android:id/icon"
- android:layout_width="@dimen/global_actions_grid_item_icon_width"
- android:layout_height="@dimen/global_actions_grid_item_icon_height"
- android:layout_marginTop="@dimen/global_actions_grid_item_icon_top_margin"
- android:layout_marginBottom="@dimen/global_actions_grid_item_icon_bottom_margin"
- android:layout_marginLeft="@dimen/global_actions_grid_item_icon_side_margin"
- android:layout_marginRight="@dimen/global_actions_grid_item_icon_side_margin"
- android:scaleType="centerInside"
- android:tint="@color/global_actions_text"
- />
-
- <TextView
- android:id="@*android:id/message"
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:ellipsize="marquee"
- android:marqueeRepeatLimit="marquee_forever"
- android:singleLine="true"
- android:gravity="center"
- android:textSize="12dp"
- android:textColor="@color/global_actions_text"
- android:textAppearance="?android:attr/textAppearanceSmall"
- />
- </LinearLayout>
-</LinearLayout>
diff --git a/packages/SystemUI/res/layout-land/global_actions_grid_seascape.xml b/packages/SystemUI/res/layout-land/global_actions_grid_seascape.xml
deleted file mode 100644
index e52ad2a..0000000
--- a/packages/SystemUI/res/layout-land/global_actions_grid_seascape.xml
+++ /dev/null
@@ -1,79 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<com.android.systemui.globalactions.GlobalActionsGridLayout
- xmlns:android="http://schemas.android.com/apk/res/android"
- android:id="@id/global_actions_view"
- android:layout_width="match_parent"
- android:layout_height="match_parent"
- android:orientation="horizontal"
- android:theme="@style/Theme.SystemUI.QuickSettings"
- android:gravity="left | center_vertical"
- android:clipChildren="false"
- android:clipToPadding="false"
- android:paddingLeft="@dimen/global_actions_grid_container_shadow_offset"
- android:layout_marginLeft="@dimen/global_actions_grid_container_negative_shadow_offset"
->
- <LinearLayout
- android:layout_height="wrap_content"
- android:layout_width="wrap_content"
- android:padding="0dp"
- android:orientation="vertical"
- android:clipChildren="false"
- android:clipToPadding="false"
- android:layout_marginLeft="@dimen/global_actions_grid_container_bottom_margin"
- >
- <!-- For separated items-->
- <LinearLayout
- android:id="@+id/separated_button"
- android:layout_gravity="top|left"
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:layout_marginTop="@dimen/global_actions_grid_side_margin"
- android:layout_marginBottom="@dimen/global_actions_grid_side_margin"
- android:paddingLeft="@dimen/global_actions_grid_vertical_padding"
- android:paddingRight="@dimen/global_actions_grid_vertical_padding"
- android:paddingTop="@dimen/global_actions_grid_horizontal_padding"
- android:paddingBottom="@dimen/global_actions_grid_horizontal_padding"
- android:orientation="horizontal"
- android:layoutDirection="rtl"
- android:background="?android:attr/colorBackgroundFloating"
- android:gravity="center"
- android:translationZ="@dimen/global_actions_translate"
- />
- <!-- Grid of action items -->
- <com.android.systemui.globalactions.ListGridLayout
- android:id="@android:id/list"
- android:layout_gravity="bottom|left"
- android:gravity="right"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:orientation="vertical"
- android:layout_marginBottom="@dimen/global_actions_grid_side_margin"
- android:translationZ="@dimen/global_actions_translate"
- android:paddingLeft="@dimen/global_actions_grid_vertical_padding"
- android:paddingRight="@dimen/global_actions_grid_vertical_padding"
- android:paddingTop="@dimen/global_actions_grid_horizontal_padding"
- android:paddingBottom="@dimen/global_actions_grid_horizontal_padding"
- android:background="?android:attr/colorBackgroundFloating"
- >
- <LinearLayout
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:visibility="gone"
- android:layoutDirection="locale"
- />
- <LinearLayout
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:visibility="gone"
- android:layoutDirection="locale"
- />
- <LinearLayout
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:visibility="gone"
- android:layoutDirection="locale"
- />
- </com.android.systemui.globalactions.ListGridLayout>
- </LinearLayout>
-
-</com.android.systemui.globalactions.GlobalActionsGridLayout>
diff --git a/packages/SystemUI/res/layout-sw600dp-land/global_actions_grid_v2.xml b/packages/SystemUI/res/layout-sw600dp-land/global_actions_grid_v2.xml
deleted file mode 100644
index 953a29e..0000000
--- a/packages/SystemUI/res/layout-sw600dp-land/global_actions_grid_v2.xml
+++ /dev/null
@@ -1,68 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
- ~ 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.
- -->
-
-<LinearLayout
- xmlns:android="http://schemas.android.com/apk/res/android"
- android:id="@+id/global_actions_container"
- android:layout_width="match_parent"
- android:layout_height="match_parent"
- android:orientation="horizontal">
-
- <LinearLayout
- android:layout_weight="1"
- android:layout_height="match_parent"
- android:layout_width="0dp"
- android:clipChildren="false"
- android:orientation="vertical"
- android:clipToPadding="false"
- android:id="@+id/controls_pane"
- >
- <LinearLayout
- android:id="@+id/global_actions_controls"
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:orientation="vertical"/>
- </LinearLayout>
-
- <LinearLayout
- android:layout_weight="1"
- android:layout_height="match_parent"
- android:layout_width="0dp"
- android:orientation="vertical"
- android:id="@+id/nfc_pane"
- >
- <include layout="@layout/global_actions_view" />
-
- <include layout="@layout/global_actions_lock_view" />
-
- <LinearLayout
- android:id="@+id/global_actions_grid_root"
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:clipChildren="false"
- android:orientation="vertical"
- android:clipToPadding="false">
-
- <FrameLayout
- android:id="@+id/global_actions_wallet"
- android:layout_width="match_parent"
- android:layout_height="wrap_content"/>
-
- </LinearLayout>
-
- </LinearLayout>
-</LinearLayout>
diff --git a/packages/SystemUI/res/layout-sw600dp/global_actions_grid_v2.xml b/packages/SystemUI/res/layout-sw600dp/global_actions_grid_v2.xml
deleted file mode 100644
index 6ffcef7..0000000
--- a/packages/SystemUI/res/layout-sw600dp/global_actions_grid_v2.xml
+++ /dev/null
@@ -1,76 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
- ~ 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.
- -->
-
-<LinearLayout
- xmlns:android="http://schemas.android.com/apk/res/android"
- android:id="@+id/global_actions_container"
- android:layout_width="match_parent"
- android:layout_height="match_parent"
- android:orientation="vertical">
-
- <LinearLayout
- android:layout_weight="1"
- android:layout_height="0dp"
- android:layout_width="match_parent"
- android:orientation="vertical"
- android:id="@+id/nfc_pane"
- >
-
- <include layout="@layout/global_actions_view" />
-
- <include layout="@layout/global_actions_lock_view" />
-
-
- <com.android.systemui.globalactions.MinHeightScrollView
- android:layout_width="match_parent"
- android:layout_height="match_parent"
- android:orientation="vertical"
- android:scrollbars="none">
-
- <LinearLayout
- android:id="@+id/global_actions_grid_root"
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:clipChildren="false"
- android:orientation="vertical"
- android:clipToPadding="false">
-
- <FrameLayout
- android:id="@+id/global_actions_wallet"
- android:layout_width="match_parent"
- android:layout_height="wrap_content"/>
-
- </LinearLayout>
- </com.android.systemui.globalactions.MinHeightScrollView>
-
- </LinearLayout>
-
- <LinearLayout
- android:layout_weight="1"
- android:layout_height="0dp"
- android:layout_width="match_parent"
- android:orientation="vertical"
- android:id="@+id/controls_pane"
- android:clipToPadding="false"
- android:clipChildren="false">
- <LinearLayout
- android:id="@+id/global_actions_controls"
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:orientation="vertical"/>
- </LinearLayout>
-</LinearLayout>
diff --git a/packages/SystemUI/res/layout/app_ops_info.xml b/packages/SystemUI/res/layout/app_ops_info.xml
deleted file mode 100644
index ecf572b..0000000
--- a/packages/SystemUI/res/layout/app_ops_info.xml
+++ /dev/null
@@ -1,96 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
- Copyright 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.
--->
-
-<com.android.systemui.statusbar.notification.row.AppOpsInfo
- xmlns:android="http://schemas.android.com/apk/res/android"
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:focusable="true"
- android:id="@+id/app_ops_info"
- android:clipChildren="false"
- android:clipToPadding="false"
- android:orientation="vertical"
- android:paddingStart="@*android:dimen/notification_content_margin_start"
- android:paddingEnd="@*android:dimen/notification_content_margin_end"
- android:background="?android:attr/colorBackground"
- android:theme="@*android:style/Theme.DeviceDefault.Light">
-
- <!-- Package Info -->
- <RelativeLayout
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:clipChildren="false"
- android:clipToPadding="false"
- android:layout_marginTop="@*android:dimen/notification_header_padding_top" >
- <ImageView
- android:id="@+id/pkgicon"
- android:layout_width="@dimen/notification_guts_header_height"
- android:layout_height="@dimen/notification_guts_header_height"
- android:layout_centerVertical="true"
- android:layout_marginEnd="3dp" />
- <TextView
- android:id="@+id/pkgname"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:textAppearance="@*android:style/TextAppearance.Material.Notification.Info"
- android:layout_marginStart="3dp"
- android:layout_marginEnd="2dp"
- android:singleLine="true"
- android:layout_centerVertical="true"
- android:layout_toEndOf="@id/pkgicon" />
- </RelativeLayout>
-
- <TextView
- android:id="@+id/prompt"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:layout_marginTop="@*android:dimen/notification_header_padding_top"
- style="@style/TextAppearance.NotificationInfo.Secondary" />
-
- <!-- Settings and Done buttons -->
- <RelativeLayout
- android:id="@+id/bottom_buttons"
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:gravity="center_vertical"
- android:paddingStart="4dp"
- android:paddingEnd="4dp">
- <TextView
- android:id="@+id/settings"
- android:text="@string/notification_appops_settings"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:layout_toStartOf="@+id/ok"
- android:gravity="center_vertical"
- android:background="@drawable/ripple_drawable"
- android:layout_marginEnd="8dp"
- android:minWidth="@dimen/min_clickable_item_size"
- android:minHeight="@dimen/min_clickable_item_size"
- style="@style/TextAppearance.NotificationInfo.Button"/>
- <TextView
- android:id="@+id/ok"
- android:text="@string/notification_appops_ok"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:layout_alignParentEnd="true"
- android:gravity="end|center_vertical"
- android:background="@drawable/ripple_drawable"
- android:minWidth="@dimen/min_clickable_item_size"
- android:minHeight="@dimen/min_clickable_item_size"
- style="@style/TextAppearance.NotificationInfo.Button"/>
- </RelativeLayout>
-</com.android.systemui.statusbar.notification.row.AppOpsInfo>
diff --git a/packages/SystemUI/res/layout/controls_icon.xml b/packages/SystemUI/res/layout/controls_icon.xml
deleted file mode 100644
index 12bc5f6..0000000
--- a/packages/SystemUI/res/layout/controls_icon.xml
+++ /dev/null
@@ -1,26 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
-**
-** Copyright 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.
-*/
--->
-
-<ImageView
- xmlns:android="http://schemas.android.com/apk/res/android"
- android:layout_width="24dp"
- android:layout_height="24dp"
- android:scaleType="fitCenter"
- android:layout_marginLeft="5dp"
- android:layout_marginRight="5dp" />
diff --git a/packages/SystemUI/res/layout/global_actions_grid_item.xml b/packages/SystemUI/res/layout/global_actions_grid_item.xml
deleted file mode 100644
index 31c7cbf..0000000
--- a/packages/SystemUI/res/layout/global_actions_grid_item.xml
+++ /dev/null
@@ -1,60 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2008 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.
--->
-
-<!-- RelativeLayouts have an issue enforcing minimum heights, so just
- work around this for now with LinearLayouts. -->
-<LinearLayout
- xmlns:android="http://schemas.android.com/apk/res/android"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:gravity="center"
- android:layout_marginTop="@dimen/global_actions_grid_item_vertical_margin"
- android:layout_marginBottom="@dimen/global_actions_grid_item_vertical_margin"
- android:layout_marginLeft="@dimen/global_actions_grid_item_side_margin"
- android:layout_marginRight="@dimen/global_actions_grid_item_side_margin"
->
- <LinearLayout
- android:layout_width="@dimen/global_actions_grid_item_width"
- android:layout_height="@dimen/global_actions_grid_item_height"
- android:gravity="top|center_horizontal"
- android:orientation="vertical"
- >
- <ImageView
- android:id="@*android:id/icon"
- android:layout_width="@dimen/global_actions_grid_item_icon_width"
- android:layout_height="@dimen/global_actions_grid_item_icon_height"
- android:layout_marginTop="@dimen/global_actions_grid_item_icon_top_margin"
- android:layout_marginBottom="@dimen/global_actions_grid_item_icon_bottom_margin"
- android:layout_marginLeft="@dimen/global_actions_grid_item_icon_side_margin"
- android:layout_marginRight="@dimen/global_actions_grid_item_icon_side_margin"
- android:scaleType="centerInside"
- android:tint="@color/global_actions_text"
- />
-
- <TextView
- android:id="@*android:id/message"
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:ellipsize="marquee"
- android:marqueeRepeatLimit="marquee_forever"
- android:singleLine="true"
- android:gravity="center"
- android:textSize="12dp"
- android:textColor="@color/global_actions_text"
- android:textAppearance="?android:attr/textAppearanceSmall"
- />
- </LinearLayout>
-</LinearLayout>
diff --git a/packages/SystemUI/res/layout/global_actions_grid_v2.xml b/packages/SystemUI/res/layout/global_actions_grid_v2.xml
deleted file mode 100644
index f06a4be..0000000
--- a/packages/SystemUI/res/layout/global_actions_grid_v2.xml
+++ /dev/null
@@ -1,35 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<LinearLayout
- xmlns:android="http://schemas.android.com/apk/res/android"
- android:id="@+id/global_actions_container"
- android:layout_width="match_parent"
- android:layout_height="match_parent"
- android:orientation="vertical"
->
-
- <include layout="@layout/global_actions_view" />
-
- <include layout="@layout/global_actions_lock_view" />
-
- <com.android.systemui.globalactions.MinHeightScrollView
- android:layout_width="match_parent"
- android:layout_height="match_parent"
- android:orientation="vertical"
- android:scrollbars="none">
-
- <LinearLayout
- android:id="@+id/global_actions_grid_root"
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:clipChildren="false"
- android:orientation="vertical"
- android:clipToPadding="false">
-
- <FrameLayout
- android:id="@+id/global_actions_wallet"
- android:layout_width="match_parent"
- android:layout_height="wrap_content"/>
-
- </LinearLayout>
- </com.android.systemui.globalactions.MinHeightScrollView>
-</LinearLayout>
diff --git a/packages/SystemUI/res/layout/global_actions_item.xml b/packages/SystemUI/res/layout/global_actions_item.xml
deleted file mode 100644
index 66a4b73..0000000
--- a/packages/SystemUI/res/layout/global_actions_item.xml
+++ /dev/null
@@ -1,60 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2008 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.
--->
-
-<!-- RelativeLayouts have an issue enforcing minimum heights, so just
- work around this for now with LinearLayouts. -->
-<LinearLayout
- xmlns:android="http://schemas.android.com/apk/res/android"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:layout_gravity="center"
- android:minWidth="92dp"
- android:minHeight="92dp"
- android:gravity="center"
- android:orientation="vertical"
- android:paddingEnd="4dip"
- android:paddingStart="4dip">
-
- <ImageView
- android:id="@*android:id/icon"
- android:layout_width="24dp"
- android:layout_height="24dp"
- android:layout_gravity="center"
- android:scaleType="center"
- android:alpha="?android:attr/primaryContentAlpha"
- />
-
- <TextView
- android:id="@*android:id/message"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:layout_gravity="top|center_horizontal"
- android:paddingTop="10dp"
- android:gravity="center"
- android:textSize="12sp"
- android:textAppearance="?android:attr/textAppearanceSmall"
- />
-
- <TextView
- android:id="@*android:id/status"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:layout_gravity="top|center_horizontal"
- android:gravity="center"
- android:textColor="?android:attr/textColorTertiary"
- android:textAppearance="?android:attr/textAppearanceSmall"
- />
-</LinearLayout>
diff --git a/packages/SystemUI/res/layout/global_actions_lock_view.xml b/packages/SystemUI/res/layout/global_actions_lock_view.xml
deleted file mode 100644
index eccc636..0000000
--- a/packages/SystemUI/res/layout/global_actions_lock_view.xml
+++ /dev/null
@@ -1,35 +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.
- -->
-<androidx.constraintlayout.widget.ConstraintLayout
- xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:app="http://schemas.android.com/apk/res-auto"
- android:id="@+id/global_actions_lock_message_container"
- android:layout_width="match_parent"
- android:layout_height="match_parent"
- android:visibility="gone">
- <TextView
- android:id="@+id/global_actions_lock_message"
- style="@style/TextAppearance.Control.Title"
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:layout_marginHorizontal="@dimen/global_actions_side_margin"
- android:drawablePadding="12dp"
- android:gravity="center"
- android:text="@string/global_action_lock_message"
- app:layout_constraintBottom_toBottomOf="parent"
- app:layout_constraintTop_toTopOf="parent"
- app:layout_constraintVertical_bias="0.35"/>
-</androidx.constraintlayout.widget.ConstraintLayout>
\ No newline at end of file
diff --git a/packages/SystemUI/res/layout/horizontal_divider.xml b/packages/SystemUI/res/layout/horizontal_divider.xml
deleted file mode 100644
index a060f08..0000000
--- a/packages/SystemUI/res/layout/horizontal_divider.xml
+++ /dev/null
@@ -1,25 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
- Copyright (C) 2015 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.
--->
-<View
- xmlns:android="http://schemas.android.com/apk/res/android"
- android:layout_width="match_parent"
- android:layout_height="1dp"
- android:layout_marginTop="10dp"
- android:layout_marginBottom="10dp"
- android:layout_marginStart="40dp"
- android:layout_marginEnd="40dp"
- android:background="#4dffffff" />
diff --git a/packages/SystemUI/res/layout/internet_connectivity_dialog.xml b/packages/SystemUI/res/layout/internet_connectivity_dialog.xml
index 79ac737..f4faa62 100644
--- a/packages/SystemUI/res/layout/internet_connectivity_dialog.xml
+++ b/packages/SystemUI/res/layout/internet_connectivity_dialog.xml
@@ -20,8 +20,7 @@
xmlns:androidprv="http://schemas.android.com/apk/prv/res/android"
android:id="@+id/internet_connectivity_dialog"
android:layout_width="@dimen/large_dialog_width"
- android:layout_height="@dimen/internet_dialog_list_max_height"
- android:background="@drawable/internet_dialog_rounded_top_corner_background"
+ android:layout_height="wrap_content"
android:orientation="vertical">
<LinearLayout
diff --git a/packages/SystemUI/res/layout/mland.xml b/packages/SystemUI/res/layout/mland.xml
deleted file mode 100644
index d1b6d00..0000000
--- a/packages/SystemUI/res/layout/mland.xml
+++ /dev/null
@@ -1,103 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
- Copyright (C) 2015 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.
--->
-<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
- android:orientation="vertical"
- android:layout_width="match_parent"
- android:layout_height="match_parent"
- >
- <com.android.systemui.egg.MLand
- android:id="@+id/world"
- android:layout_width="match_parent"
- android:layout_height="match_parent">
- </com.android.systemui.egg.MLand>
- <FrameLayout
- android:id="@+id/welcome"
- android:layout_width="match_parent"
- android:layout_height="match_parent"
- android:visibility="gone"
- android:background="#a0000000"
- android:clickable="true"
- >
- <FrameLayout
- android:id="@+id/play_button"
- android:layout_width="72dp"
- android:layout_height="72dp"
- android:layout_gravity="center"
- android:clickable="true"
- android:background="@drawable/ripplebg"
- android:focusable="true"
- android:onClick="startButtonPressed"
- >
- <ImageView
- android:id="@+id/play_button_image"
- android:layout_width="48dp"
- android:layout_height="48dp"
- android:scaleType="fitCenter"
- android:layout_gravity="center"
- android:tint="#000000"
- android:src="@drawable/play"
- />
- <TextView
- android:id="@+id/play_button_text"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:layout_gravity="center"
- android:alpha="0"
- android:textSize="40dp"
- android:textColor="#000000"
- />
- </FrameLayout>
- </FrameLayout>
- <LinearLayout
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:layout_gravity="top|center_horizontal"
- android:orientation="horizontal"
- android:gravity="center_vertical"
- android:id="@+id/player_setup"
- >
- <ImageButton
- style="@android:style/Widget.Material.Button.Borderless"
- android:id="@+id/player_minus_button"
- android:layout_width="48dp"
- android:layout_height="48dp"
- android:padding="10dp"
- android:scaleType="centerInside"
- android:onClick="playerMinus"
- android:src="@drawable/minus"
- />
- <LinearLayout
- android:id="@+id/scores"
- android:layout_width="wrap_content"
- android:layout_height="64dp"
- android:padding="12dp"
- android:orientation="horizontal"
- android:clipToPadding="false"
- >
- </LinearLayout>
- <ImageButton
- style="@android:style/Widget.Material.Button.Borderless"
- android:id="@+id/player_plus_button"
- android:layout_width="48dp"
- android:layout_height="48dp"
- android:padding="10dp"
- android:scaleType="centerInside"
- android:onClick="playerPlus"
- android:src="@drawable/plus"
- />
- </LinearLayout>
-</FrameLayout>
diff --git a/packages/SystemUI/res/layout/mland_scorefield.xml b/packages/SystemUI/res/layout/mland_scorefield.xml
deleted file mode 100644
index 0ed72e43..0000000
--- a/packages/SystemUI/res/layout/mland_scorefield.xml
+++ /dev/null
@@ -1,32 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
- Copyright (C) 2015 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.
--->
-<TextView
- xmlns:android="http://schemas.android.com/apk/res/android"
- android:id="@+id/score"
- android:layout_width="wrap_content"
- android:layout_height="match_parent"
- android:textStyle="bold"
- android:textSize="22sp"
- android:gravity="center"
- android:textColor="#FFAAAAAA"
- android:paddingStart="12dp"
- android:paddingEnd="12dp"
- android:paddingTop="4dp"
- android:paddingBottom="4dp"
- android:background="@drawable/scorecard"
- android:elevation="@dimen/hud_z"
- />
diff --git a/packages/SystemUI/res/layout/nav_control_widget.xml b/packages/SystemUI/res/layout/nav_control_widget.xml
deleted file mode 100644
index 51dd68f..0000000
--- a/packages/SystemUI/res/layout/nav_control_widget.xml
+++ /dev/null
@@ -1,62 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
- Copyright (C) 2016 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.
--->
-
-<LinearLayout
- xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:systemui="http://schemas.android.com/apk/res-auto"
- android:layout_width="wrap_content"
- android:layout_height="match_parent"
- android:paddingTop="8dp"
- android:paddingBottom="8dp"
- android:gravity="center"
- android:orientation="horizontal">
-
- <ImageView
- android:id="@+id/width"
- android:layout_width="48dp"
- android:layout_height="wrap_content"
- android:src="@drawable/ic_width"
- android:clickable="true"
- android:tint="?android:attr/textColorPrimary" />
-
- <View
- android:layout_width="1dp"
- android:layout_height="match_parent"
- android:background="?android:attr/listDivider" />
-
- <ImageView
- android:id="@+id/close"
- android:layout_width="48dp"
- android:layout_height="wrap_content"
- android:src="@drawable/ic_close"
- android:clickable="true"
- android:tint="?android:attr/textColorPrimary" />
-
- <View
- android:layout_width="1dp"
- android:layout_height="match_parent"
- android:background="?android:attr/listDivider" />
-
- <ImageView
- android:id="@+id/drag"
- android:layout_width="48dp"
- android:layout_height="wrap_content"
- android:src="@drawable/ic_drag_handle"
- android:clickable="true"
- android:tint="?android:attr/textColorPrimary" />
-
-</LinearLayout>
diff --git a/packages/SystemUI/res/layout/nav_width_view.xml b/packages/SystemUI/res/layout/nav_width_view.xml
deleted file mode 100644
index 6a72faf..0000000
--- a/packages/SystemUI/res/layout/nav_width_view.xml
+++ /dev/null
@@ -1,26 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
-**
-** Copyright 2016, 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.
-*/
--->
-
-<SeekBar
- xmlns:android="http://schemas.android.com/apk/res/android"
- android:id="@+id/seekbar"
- android:layout_height="wrap_content"
- android:layout_width="match_parent"
- android:paddingTop="12dp"
- android:paddingBottom="4dp" />
diff --git a/packages/SystemUI/res/layout/navigation_bar_app_item.xml b/packages/SystemUI/res/layout/navigation_bar_app_item.xml
deleted file mode 100644
index 1078d29..0000000
--- a/packages/SystemUI/res/layout/navigation_bar_app_item.xml
+++ /dev/null
@@ -1,30 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2015 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.
--->
-
-<!--
- ImageView for an app icon in the navigation bar. Used to launch the app. The ImageView size is
- used to compute the size of the drag shadow.
--->
-<ImageView xmlns:android="http://schemas.android.com/apk/res/android"
- android:layout_width="64dp"
- android:layout_height="48dp"
- android:paddingLeft="14dp"
- android:paddingRight="14dp"
- android:paddingTop="6dp"
- android:paddingBottom="6dp"
- android:layout_gravity="center"
- android:scaleType="centerInside"
- />
diff --git a/packages/SystemUI/res/layout/ongoing_call_chip.xml b/packages/SystemUI/res/layout/ongoing_call_chip.xml
index 5389d9b..c949ba0 100644
--- a/packages/SystemUI/res/layout/ongoing_call_chip.xml
+++ b/packages/SystemUI/res/layout/ongoing_call_chip.xml
@@ -21,6 +21,7 @@
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:layout_gravity="center_vertical|start"
+ android:layout_marginStart="5dp"
>
<LinearLayout
android:id="@+id/ongoing_call_chip_background"
diff --git a/packages/SystemUI/res/layout/people_space_widget.xml b/packages/SystemUI/res/layout/people_space_widget.xml
deleted file mode 100644
index f4db321..0000000
--- a/packages/SystemUI/res/layout/people_space_widget.xml
+++ /dev/null
@@ -1,27 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
- ~ 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.
- -->
-<ListView
- xmlns:android="http://schemas.android.com/apk/res/android"
- android:id="@+id/widget_list_view"
- android:layout_width="match_parent"
- android:layout_height="match_parent"
- android:background="@drawable/people_space_widget_background"
- android:clipChildren="false"
- android:clipToPadding="false"
- android:padding="2dp"
- android:divider="@null"
- android:dividerHeight="0dp"/>
\ No newline at end of file
diff --git a/packages/SystemUI/res/layout/people_space_widget_item.xml b/packages/SystemUI/res/layout/people_space_widget_item.xml
deleted file mode 100644
index 492d3ab..0000000
--- a/packages/SystemUI/res/layout/people_space_widget_item.xml
+++ /dev/null
@@ -1,93 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
- ~ 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.
- -->
-<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
- android:layout_width="match_parent"
- android:padding="4dp"
- android:layout_height="wrap_content"
- android:orientation="vertical">
- <LinearLayout
- android:background="@drawable/people_space_tile_view_card"
- android:clipToOutline="true"
- android:id="@android:id/background"
- android:orientation="vertical"
- android:padding="4dp"
- android:layout_marginBottom="2dp"
- android:elevation="4dp"
- android:layout_width="match_parent"
- android:layout_height="wrap_content">
-
- <LinearLayout
- android:orientation="horizontal"
- android:gravity="center_vertical"
- android:paddingStart="12dp"
- android:layout_width="match_parent"
- android:layout_height="wrap_content">
-
- <ImageView
- android:id="@+id/person_icon"
- android:layout_width="60dp"
- android:layout_height="60dp" />
-
- <LinearLayout
- android:background="@drawable/people_space_rounded_border"
- android:layout_marginStart="-12dp"
- android:layout_marginTop="28dp"
- android:layout_marginBottom="14dp"
- android:layout_width="16dp"
- android:layout_height="16dp">
-
- <ImageView
- android:id="@+id/package_icon"
- android:layout_width="12dp"
- android:layout_marginStart="2dp"
- android:layout_marginEnd="2dp"
- android:layout_marginBottom="2dp"
- android:layout_marginTop="2dp"
- android:layout_height="12dp" />
- </LinearLayout>
-
- <LinearLayout
- android:orientation="vertical"
- android:paddingStart="8dp"
- android:paddingEnd="12dp"
- android:layout_width="match_parent"
- android:layout_height="wrap_content">
-
- <TextView
- android:id="@+id/name"
- android:textAppearance="@*android:style/TextAppearance.DeviceDefault.Notification.Title"
- android:textColor="?android:attr/textColorPrimary"
- android:textSize="16sp"
- android:maxLines="1"
- android:ellipsize="end"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content" />
-
- <TextView
- android:id="@+id/status"
- android:textColor="?android:attr/textColorSecondary"
- android:textAppearance="@*android:style/TextAppearance.DeviceDefault.Notification.Title"
- android:paddingVertical="2dp"
- android:textSize="12sp"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:maxLines="3"
- android:ellipsize="end" />
- </LinearLayout>
- </LinearLayout>
- </LinearLayout>
-</LinearLayout>
diff --git a/packages/SystemUI/res/layout/preference_widget_settings.xml b/packages/SystemUI/res/layout/preference_widget_settings.xml
deleted file mode 100644
index 082a295..0000000
--- a/packages/SystemUI/res/layout/preference_widget_settings.xml
+++ /dev/null
@@ -1,44 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
- Copyright (C) 2015 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.
--->
-
-<LinearLayout
- xmlns:android="http://schemas.android.com/apk/res/android"
- android:layout_height="wrap_content"
- android:layout_width="wrap_content">
-
- <RadioButton
- android:id="@+id/radio_button"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:layout_marginEnd="4dp"
- android:clickable="false"
- android:focusable="false" />
-
- <View
- android:layout_width="1dp"
- android:layout_height="match_parent"
- android:background="?android:attr/listDivider" />
-
- <ImageView
- android:id="@+id/widget_icon"
- android:layout_width="50dp"
- android:layout_height="24dp"
- android:tint="@android:color/black"
- android:src="@drawable/ic_settings"
- android:layout_gravity="center_vertical" />
-
-</LinearLayout>
diff --git a/packages/SystemUI/res/layout/punctuation_layout.xml b/packages/SystemUI/res/layout/punctuation_layout.xml
deleted file mode 100644
index 25c7648..0000000
--- a/packages/SystemUI/res/layout/punctuation_layout.xml
+++ /dev/null
@@ -1,100 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
- ~ Copyright (C) 2021 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.
- -->
-<LinearLayout
- xmlns:android="http://schemas.android.com/apk/res/android"
- android:id="@+id/punctuation_layout"
- android:orientation="horizontal"
- android:layout_width="match_parent"
- android:layout_height="match_parent"
- android:gravity="start">
- <TextView
- android:id="@+id/punctuation1"
- android:textColor="?android:attr/textColorSecondary"
- android:textAppearance="@*android:style/TextAppearance.DeviceDefault.ListItem"
- android:textSize="36sp"
- android:textStyle="bold"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:layout_marginTop="5dp"
- android:maxLines="1"
- android:alpha="0.2"
- android:rotation="350"/>
- <TextView
- android:id="@+id/punctuation2"
- android:textColor="?android:attr/textColorSecondary"
- android:textAppearance="@*android:style/TextAppearance.DeviceDefault.ListItem"
- android:textSize="36sp"
- android:textStyle="bold"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:layout_marginStart="25dp"
- android:maxLines="1"
- android:alpha="0.2"
- android:rotation="5"/>
- <TextView
- android:id="@+id/punctuation3"
- android:textColor="?android:attr/textColorSecondary"
- android:textAppearance="@*android:style/TextAppearance.DeviceDefault.ListItem"
- android:textSize="36sp"
- android:textStyle="bold"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:layout_marginTop="5dp"
- android:layout_marginStart="25dp"
- android:maxLines="1"
- android:alpha="0.2"
- android:rotation="355"/>
- <TextView
- android:id="@+id/punctuation4"
- android:textColor="?android:attr/textColorSecondary"
- android:textAppearance="@*android:style/TextAppearance.DeviceDefault.ListItem"
- android:textSize="36sp"
- android:textStyle="bold"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:layout_marginTop="-5dp"
- android:layout_marginStart="25dp"
- android:maxLines="1"
- android:alpha="0.2"
- android:rotation="10"/>
- <TextView
- android:id="@+id/punctuation5"
- android:textColor="?android:attr/textColorSecondary"
- android:textAppearance="@*android:style/TextAppearance.DeviceDefault.ListItem"
- android:textSize="36sp"
- android:textStyle="bold"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:layout_marginTop="5dp"
- android:layout_marginStart="25dp"
- android:maxLines="1"
- android:alpha="0.2"
- android:rotation="15"/>
- <TextView
- android:id="@+id/punctuation6"
- android:textColor="?android:attr/textColorSecondary"
- android:textAppearance="@*android:style/TextAppearance.DeviceDefault.ListItem"
- android:textSize="36sp"
- android:textStyle="bold"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:layout_marginTop="-5dp"
- android:layout_marginStart="25dp"
- android:maxLines="1"
- android:alpha="0.2"
- android:rotation="345"/>
-</LinearLayout>
\ No newline at end of file
diff --git a/packages/SystemUI/res/layout/qs_add_tiles_list.xml b/packages/SystemUI/res/layout/qs_add_tiles_list.xml
deleted file mode 100644
index 312c207..0000000
--- a/packages/SystemUI/res/layout/qs_add_tiles_list.xml
+++ /dev/null
@@ -1,32 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2015 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.
--->
-<FrameLayout
- xmlns:android="http://schemas.android.com/apk/res/android"
- android:layout_width="match_parent"
- android:layout_height="wrap_content">
- <ListView
- android:id="@android:id/list"
- android:layout_width="match_parent"
- android:layout_height="wrap_content" />
- <TextView
- android:paddingTop="10dp"
- android:id="@+id/empty_text"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:layout_gravity="center"
- android:textAppearance="?android:attr/textAppearanceMedium"
- android:text="@string/no_tiles_add" />
-</FrameLayout>
diff --git a/packages/SystemUI/res/layout/qs_page_indicator.xml b/packages/SystemUI/res/layout/qs_page_indicator.xml
deleted file mode 100644
index 583753a..0000000
--- a/packages/SystemUI/res/layout/qs_page_indicator.xml
+++ /dev/null
@@ -1,27 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
- Copyright (C) 2016 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.systemui.qs.PageIndicator
- xmlns:android="http://schemas.android.com/apk/res/android"
- android:id="@+id/page_indicator"
- android:layout_width="match_parent"
- android:layout_height="48dp"
- android:layout_gravity="center"
- android:layout_marginBottom="24dp"
- android:focusable="true"
- android:gravity="center"
- android:importantForAccessibility="yes"
- android:visibility="gone"/>
diff --git a/packages/SystemUI/res/layout/qs_tile_layout.xml b/packages/SystemUI/res/layout/qs_tile_layout.xml
deleted file mode 100644
index b5d1a1e..0000000
--- a/packages/SystemUI/res/layout/qs_tile_layout.xml
+++ /dev/null
@@ -1,21 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
- Copyright (C) 2015 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.systemui.qs.TileLayout
- xmlns:android="http://schemas.android.com/apk/res/android"
- android:layout_height="wrap_content"
- android:layout_width="match_parent" />
diff --git a/packages/SystemUI/res/layout/quick_status_bar_expanded_header.xml b/packages/SystemUI/res/layout/quick_status_bar_expanded_header.xml
index 6b14c96..10a2f4c 100644
--- a/packages/SystemUI/res/layout/quick_status_bar_expanded_header.xml
+++ b/packages/SystemUI/res/layout/quick_status_bar_expanded_header.xml
@@ -63,7 +63,7 @@
android:id="@+id/qqs_footer_actions"
android:layout_width="match_parent"
android:layout_height="wrap_content"
- android:layout_marginTop="16dp"
+ android:layout_marginTop="@dimen/qqs_layout_margin_top"
android:layout_marginStart="@dimen/qs_footer_margin"
android:layout_marginEnd="@dimen/qs_footer_margin"
/>
diff --git a/packages/SystemUI/res/layout/recents_onboarding.xml b/packages/SystemUI/res/layout/recents_onboarding.xml
deleted file mode 100644
index 2538612..0000000
--- a/packages/SystemUI/res/layout/recents_onboarding.xml
+++ /dev/null
@@ -1,64 +0,0 @@
-<?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.
--->
-
-<LinearLayout
- xmlns:android="http://schemas.android.com/apk/res/android"
- android:layout_height="wrap_content"
- android:layout_width="wrap_content"
- android:paddingBottom="13dp"
- android:orientation="vertical">
-
- <LinearLayout
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:paddingStart="24dp"
- android:paddingEnd="4dp"
- android:background="@drawable/recents_onboarding_toast_rounded_background"
- android:layout_gravity="center_horizontal"
- android:elevation="2dp"
- android:orientation="horizontal">
-
- <TextView
- android:id="@+id/onboarding_text"
- android:layout_width="0dp"
- android:layout_height="wrap_content"
- android:layout_weight="1"
- android:layout_gravity="center_vertical"
- android:textColor="?attr/wallpaperTextColor"
- android:textSize="16sp"/>
- <ImageView
- android:id="@+id/dismiss"
- android:layout_width="40dp"
- android:layout_height="40dp"
- android:layout_gravity="center_vertical"
- android:padding="10dp"
- android:layout_marginStart="2dp"
- android:layout_marginEnd="2dp"
- android:alpha="0.7"
- android:src="@drawable/ic_close_white"
- android:tint="?attr/wallpaperTextColor"
- android:background="?android:attr/selectableItemBackgroundBorderless"
- android:contentDescription="@string/accessibility_desc_close"/>
- </LinearLayout>
-
- <View
- android:id="@+id/arrow"
- android:elevation="2dp"
- android:layout_width="10dp"
- android:layout_height="8dp"
- android:layout_marginTop="-2dp"
- android:layout_gravity="center_horizontal"/>
-</LinearLayout>
\ No newline at end of file
diff --git a/packages/SystemUI/res/layout/remember_permission_checkbox.xml b/packages/SystemUI/res/layout/remember_permission_checkbox.xml
deleted file mode 100644
index 4985ff5..0000000
--- a/packages/SystemUI/res/layout/remember_permission_checkbox.xml
+++ /dev/null
@@ -1,34 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- 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.
--->
-
-<!-- Check box that is displayed in the activity resolver UI for the user
- to make their selection the preferred activity. -->
-<FrameLayout
- xmlns:android="http://schemas.android.com/apk/res/android"
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:paddingStart="16dp"
- android:paddingEnd="16dp"
- android:paddingTop="16dp">
-
- <CheckBox
- android:id="@+id/remember"
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:focusable="true"
- android:clickable="true"
- android:text="@string/media_projection_remember_text" />
-</FrameLayout>
diff --git a/packages/SystemUI/res/layout/rounded_corners.xml b/packages/SystemUI/res/layout/rounded_corners.xml
deleted file mode 100644
index 04fe918..0000000
--- a/packages/SystemUI/res/layout/rounded_corners.xml
+++ /dev/null
@@ -1,75 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
-** Copyright 2012, 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.
--->
-
-<!-- TODO: remove this in favor of requiring top and bottom layouts -->
-<com.android.systemui.RegionInterceptingFrameLayout
- xmlns:android="http://schemas.android.com/apk/res/android"
- android:id="@+id/rounded_corners_default"
- android:layout_width="match_parent"
- android:layout_height="match_parent">
- <ImageView
- android:id="@+id/left"
- android:layout_width="12dp"
- android:layout_height="12dp"
- android:layout_gravity="left|top"
- android:tint="#ff000000"
- android:src="@drawable/rounded"/>
-
- <FrameLayout
- android:id="@+id/privacy_dot_left_container"
- android:layout_height="@dimen/status_bar_height"
- android:layout_width="wrap_content"
- android:layout_marginTop="@dimen/status_bar_padding_top"
- android:layout_marginLeft="8dp"
- android:layout_gravity="left|top"
- android:visibility="invisible" >
- <ImageView
- android:id="@+id/privacy_dot_left"
- android:layout_height="wrap_content"
- android:layout_width="wrap_content"
- android:layout_gravity="center"
- android:src="@drawable/system_animation_ongoing_dot"
- android:visibility="visible" />
- </FrameLayout>
-
-
- <ImageView
- android:id="@+id/right"
- android:layout_width="12dp"
- android:layout_height="12dp"
- android:tint="#ff000000"
- android:layout_gravity="right|bottom"
- android:src="@drawable/rounded"/>
- <FrameLayout
- android:id="@+id/privacy_dot_right_container"
- android:layout_height="@dimen/status_bar_height"
- android:layout_width="wrap_content"
- android:layout_marginTop="@dimen/status_bar_padding_top"
- android:layout_marginRight="8dp"
- android:layout_gravity="right|top"
- android:visibility="invisible" >
- <ImageView
- android:id="@+id/privacy_dot_right"
- android:layout_height="wrap_content"
- android:layout_width="wrap_content"
- android:layout_gravity="center"
- android:src="@drawable/system_animation_ongoing_dot"
- android:visibility="visible" />
-
- </FrameLayout>
-
-</com.android.systemui.RegionInterceptingFrameLayout>
diff --git a/packages/SystemUI/res/layout/shelf_menu_anchor.xml b/packages/SystemUI/res/layout/shelf_menu_anchor.xml
deleted file mode 100644
index 984f655..0000000
--- a/packages/SystemUI/res/layout/shelf_menu_anchor.xml
+++ /dev/null
@@ -1,24 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2015 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.
--->
-<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
- android:layout_width="match_parent"
- android:layout_height="match_parent"
- android:alpha="0">
- <ImageView android:id="@+id/shelf_menu_anchor_anchor"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:alpha="0"/>
-</FrameLayout>
diff --git a/packages/SystemUI/res/layout/super_notification_shade.xml b/packages/SystemUI/res/layout/super_notification_shade.xml
index e02a1767..b28cb2f 100644
--- a/packages/SystemUI/res/layout/super_notification_shade.xml
+++ b/packages/SystemUI/res/layout/super_notification_shade.xml
@@ -81,6 +81,7 @@
<!-- Keyguard messages -->
<LinearLayout
+ android:id="@+id/keyguard_message_area_container"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
diff --git a/packages/SystemUI/res/layout/tuner_activity.xml b/packages/SystemUI/res/layout/tuner_activity.xml
index 0b792ae..83cbf14 100644
--- a/packages/SystemUI/res/layout/tuner_activity.xml
+++ b/packages/SystemUI/res/layout/tuner_activity.xml
@@ -16,9 +16,7 @@
-->
<!-- The tuner content view -->
-<LinearLayout
- android:id="@+id/content_parent"
- xmlns:android="http://schemas.android.com/apk/res/android"
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
diff --git a/packages/SystemUI/res/mipmap-hdpi/ic_daydreams.png b/packages/SystemUI/res/mipmap-hdpi/ic_daydreams.png
deleted file mode 100644
index 4779a09..0000000
--- a/packages/SystemUI/res/mipmap-hdpi/ic_daydreams.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/mipmap-mdpi/ic_daydreams.png b/packages/SystemUI/res/mipmap-mdpi/ic_daydreams.png
deleted file mode 100644
index b3a634d..0000000
--- a/packages/SystemUI/res/mipmap-mdpi/ic_daydreams.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/mipmap-xhdpi/ic_daydreams.png b/packages/SystemUI/res/mipmap-xhdpi/ic_daydreams.png
deleted file mode 100644
index 50b1f50..0000000
--- a/packages/SystemUI/res/mipmap-xhdpi/ic_daydreams.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/transition/tv_privacy_chip_collapse.xml b/packages/SystemUI/res/transition/tv_privacy_chip_collapse.xml
deleted file mode 100644
index f22e8ef..0000000
--- a/packages/SystemUI/res/transition/tv_privacy_chip_collapse.xml
+++ /dev/null
@@ -1,20 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
- ~ Copyright (C) 2021 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.
- -->
-<transitionSet xmlns:android="http://schemas.android.com/apk/res/android">
- <fade android:fadingMode="fade_in" />
- <changeBounds/>
-</transitionSet>
diff --git a/packages/SystemUI/res/values-af/strings.xml b/packages/SystemUI/res/values-af/strings.xml
index f310a7f..cadd240 100644
--- a/packages/SystemUI/res/values-af/strings.xml
+++ b/packages/SystemUI/res/values-af/strings.xml
@@ -1111,7 +1111,7 @@
<string name="media_output_dialog_group" msgid="5571251347877452212">"Groep"</string>
<string name="media_output_dialog_single_device" msgid="3102758980643351058">"1 toestel gekies"</string>
<string name="media_output_dialog_multiple_devices" msgid="1093771040315422350">"<xliff:g id="COUNT">%1$d</xliff:g> toestelle gekies"</string>
- <string name="media_output_dialog_disconnected" msgid="1834473104836986046">"<xliff:g id="DEVICE_NAME">%1$s</xliff:g> (ontkoppel)"</string>
+ <string name="media_output_dialog_disconnected" msgid="7090512852817111185">"(ontkoppel)"</string>
<string name="media_output_dialog_connect_failed" msgid="3225190634236259010">"Kon nie koppel nie. Probeer weer."</string>
<string name="media_output_dialog_pairing_new" msgid="9099497976087485862">"Bind nuwe toestel saam"</string>
<string name="build_number_clip_data_label" msgid="3623176728412560914">"Bounommer"</string>
diff --git a/packages/SystemUI/res/values-am/strings.xml b/packages/SystemUI/res/values-am/strings.xml
index ffdfba6..d06c531 100644
--- a/packages/SystemUI/res/values-am/strings.xml
+++ b/packages/SystemUI/res/values-am/strings.xml
@@ -1111,7 +1111,7 @@
<string name="media_output_dialog_group" msgid="5571251347877452212">"ቡድን"</string>
<string name="media_output_dialog_single_device" msgid="3102758980643351058">"1 መሣሪያ ተመርጧል"</string>
<string name="media_output_dialog_multiple_devices" msgid="1093771040315422350">"<xliff:g id="COUNT">%1$d</xliff:g> መሣሪያዎች ተመርጠዋል"</string>
- <string name="media_output_dialog_disconnected" msgid="1834473104836986046">"<xliff:g id="DEVICE_NAME">%1$s</xliff:g> (ግንኙነት ተቋርጧል)"</string>
+ <string name="media_output_dialog_disconnected" msgid="7090512852817111185">"(ተቋርጧል)"</string>
<string name="media_output_dialog_connect_failed" msgid="3225190634236259010">"ማገናኘት አልተቻለም። እንደገና ይሞክሩ።"</string>
<string name="media_output_dialog_pairing_new" msgid="9099497976087485862">"አዲስ መሣሪያ ያጣምሩ"</string>
<string name="build_number_clip_data_label" msgid="3623176728412560914">"የግንብ ቁጥር"</string>
diff --git a/packages/SystemUI/res/values-ar/strings.xml b/packages/SystemUI/res/values-ar/strings.xml
index 48e101b..21cfe3b 100644
--- a/packages/SystemUI/res/values-ar/strings.xml
+++ b/packages/SystemUI/res/values-ar/strings.xml
@@ -349,7 +349,7 @@
<string name="quick_settings_bluetooth_secondary_label_hearing_aids" msgid="3003338571871392293">"سماعات الأذن الطبية"</string>
<string name="quick_settings_bluetooth_secondary_label_transient" msgid="3882884317600669650">"جارٍ التفعيل…"</string>
<string name="quick_settings_brightness_label" msgid="680259653088849563">"السطوع"</string>
- <string name="quick_settings_rotation_unlocked_label" msgid="2359922767950346112">"تدوير تلقائي"</string>
+ <string name="quick_settings_rotation_unlocked_label" msgid="2359922767950346112">"التدوير التلقائي"</string>
<string name="accessibility_quick_settings_rotation" msgid="4800050198392260738">"التدوير التلقائي للشاشة"</string>
<string name="accessibility_quick_settings_rotation_value" msgid="2916484894750819251">"وضع <xliff:g id="ID_1">%s</xliff:g>"</string>
<string name="quick_settings_rotation_locked_label" msgid="4420863550666310319">"تم قفل التدوير"</string>
@@ -1066,7 +1066,7 @@
<string name="accessibility_floating_button_action_move_to_edge_and_hide_to_half" msgid="662401168245782658">"نقله إلى الحافة وإخفاؤه"</string>
<string name="accessibility_floating_button_action_move_out_edge_and_show" msgid="8354760891651663326">"نقله إلى خارج الحافة وإظهاره"</string>
<string name="accessibility_floating_button_action_double_tap_to_toggle" msgid="7976492639670692037">"إيقاف/تفعيل"</string>
- <string name="quick_controls_title" msgid="6839108006171302273">"أدوات التحكم بالأجهزة"</string>
+ <string name="quick_controls_title" msgid="6839108006171302273">"التحكم بالجهاز"</string>
<string name="controls_providers_title" msgid="6879775889857085056">"اختيار تطبيق لإضافة عناصر التحكّم"</string>
<plurals name="controls_number_of_favorites" formatted="false" msgid="1057347832073807380">
<item quantity="zero">تمت إضافة <xliff:g id="NUMBER_1">%s</xliff:g> عنصر تحكّم.</item>
@@ -1135,7 +1135,7 @@
<string name="media_output_dialog_group" msgid="5571251347877452212">"مجموعة"</string>
<string name="media_output_dialog_single_device" msgid="3102758980643351058">"تم اختيار جهاز واحد."</string>
<string name="media_output_dialog_multiple_devices" msgid="1093771040315422350">"تم اختيار <xliff:g id="COUNT">%1$d</xliff:g> جهاز."</string>
- <string name="media_output_dialog_disconnected" msgid="1834473104836986046">"<xliff:g id="DEVICE_NAME">%1$s</xliff:g> (غير متّصل)"</string>
+ <string name="media_output_dialog_disconnected" msgid="7090512852817111185">"(غير متّصل)"</string>
<string name="media_output_dialog_connect_failed" msgid="3225190634236259010">"تعذّر الاتصال. يُرجى إعادة المحاولة."</string>
<string name="media_output_dialog_pairing_new" msgid="9099497976087485862">"إقران جهاز جديد"</string>
<string name="build_number_clip_data_label" msgid="3623176728412560914">"رقم الإصدار"</string>
diff --git a/packages/SystemUI/res/values-as/strings.xml b/packages/SystemUI/res/values-as/strings.xml
index f9cb599..9a638b4 100644
--- a/packages/SystemUI/res/values-as/strings.xml
+++ b/packages/SystemUI/res/values-as/strings.xml
@@ -235,7 +235,7 @@
<string name="accessibility_battery_level_charging" msgid="8892191177774027364">"বেটাৰী চাৰ্জ হৈ আছে, <xliff:g id="BATTERY_PERCENTAGE">%d</xliff:g> শতাংশ।"</string>
<string name="accessibility_settings_button" msgid="2197034218538913880">"ছিষ্টেমৰ ছেটিং৷"</string>
<string name="accessibility_notifications_button" msgid="3960913924189228831">"জাননীসমূহ।"</string>
- <string name="accessibility_overflow_action" msgid="8555835828182509104">"সকলো জাননীবোৰ চাওক"</string>
+ <string name="accessibility_overflow_action" msgid="8555835828182509104">"আটাইবোৰ জাননী চাওক"</string>
<string name="accessibility_remove_notification" msgid="1641455251495815527">"জাননী মচক৷"</string>
<string name="accessibility_gps_enabled" msgid="4061313248217660858">"জিপিএছ সক্ষম হ\'ল৷"</string>
<string name="accessibility_gps_acquiring" msgid="896207402196024040">"জিপিএছ বিচাৰি থকা হৈছে।"</string>
@@ -311,7 +311,7 @@
<string name="gps_notification_found_text" msgid="3145873880174658526">"জিপিএছএ অৱস্থান ছেট কৰিছে"</string>
<string name="accessibility_location_active" msgid="2845747916764660369">"অৱস্থানৰ অনুৰোধ সক্ৰিয় হৈ আছে"</string>
<string name="accessibility_sensors_off_active" msgid="2619725434618911551">"ছেন্সৰ অফ সক্ৰিয় কৰা আছে"</string>
- <string name="accessibility_clear_all" msgid="970525598287244592">"সকলো জাননী মচক৷"</string>
+ <string name="accessibility_clear_all" msgid="970525598287244592">"আটাইবোৰ জাননী মচক৷"</string>
<string name="notification_group_overflow_indicator" msgid="7605120293801012648">"+ <xliff:g id="NUMBER">%s</xliff:g>"</string>
<plurals name="notification_group_overflow_description" formatted="false" msgid="91483442850649192">
<item quantity="one"> ভিতৰত আৰু <xliff:g id="NUMBER_1">%s</xliff:g>টা জাননী আছে।</item>
@@ -448,8 +448,8 @@
<string name="zen_priority_introduction" msgid="3159291973383796646">"আপুনি নিৰ্দিষ্ট কৰা এলাৰ্ম, ৰিমাইণ্ডাৰ, ইভেন্ট আৰু কল কৰোঁতাৰ বাহিৰে আন কোনো শব্দৰ পৰা আপুনি অসুবিধা নাপাব। কিন্তু, সংগীত, ভিডিঅ\' আৰু খেলসমূহকে ধৰি আপুনি প্লে কৰিব খোজা যিকোনো বস্তু তথাপি শুনিব পাৰিব।"</string>
<string name="zen_alarms_introduction" msgid="3987266042682300470">"আপুনি নিৰ্দিষ্ট কৰা এলাৰ্মৰ বাহিৰে আন কোনো ধ্বনি আৰু কম্পনৰ পৰা আপুনি অসুবিধা নাপাব। কিন্তু, সংগীত, ভিডিঅ\' আৰু খেলসমূহকে ধৰি আপুনি প্লে কৰিব খোজা যিকোনো বস্তু তথাপি শুনিব পাৰিব।"</string>
<string name="zen_priority_customize_button" msgid="4119213187257195047">"নিজৰ উপযোগিতা অনুসৰি"</string>
- <string name="zen_silence_introduction_voice" msgid="853573681302712348">"এই কার্যই এলার্ম, সংগীত, ভিডিঅ\' আৰু খেলসমূহকে ধৰি সকলোৰে বাবে ধ্বনি আৰু কম্পন অৱৰোধ কৰিব। আপুনি ফ\'ন কল তথাপি কৰিবলৈ সক্ষম হ\'ব।"</string>
- <string name="zen_silence_introduction" msgid="6117517737057344014">"এই কার্যই এলার্ম, মিউজিক, ভিডিঅ\' আৰু গেইমকে ধৰি সকলোৰে ধ্বনি আৰু কম্পন অৱৰোধ কৰে।"</string>
+ <string name="zen_silence_introduction_voice" msgid="853573681302712348">"এই কার্যই এলার্ম, সংগীত, ভিডিঅ\' আৰু খেলসমূহকে ধৰি আটাইবোৰৰ বাবে ধ্বনি আৰু কম্পন অৱৰোধ কৰিব। আপুনি ফ\'ন কল তথাপি কৰিবলৈ সক্ষম হ\'ব।"</string>
+ <string name="zen_silence_introduction" msgid="6117517737057344014">"এই কার্যই এলার্ম, মিউজিক, ভিডিঅ\' আৰু গেইমকে ধৰি আটাইবোৰৰ ধ্বনি আৰু কম্পন অৱৰোধ কৰে।"</string>
<string name="keyguard_more_overflow_text" msgid="5819512373606638727">"+<xliff:g id="NUMBER_OF_NOTIFICATIONS">%d</xliff:g>"</string>
<string name="speed_bump_explanation" msgid="7248696377626341060">"কম জৰুৰী জাননীসমূহ তলত"</string>
<string name="notification_tap_again" msgid="4477318164947497249">"খুলিবলৈ পুনৰাই টিপক"</string>
@@ -482,7 +482,7 @@
<string name="user_add_user" msgid="4336657383006913022">"ব্যৱহাৰকাৰী যোগ কৰক"</string>
<string name="user_new_user_name" msgid="2019166282704195789">"নতুন ব্যৱহাৰকাৰী"</string>
<string name="guest_exit_guest_dialog_title" msgid="5015697561580641422">"অতিথি আঁতৰাবনে?"</string>
- <string name="guest_exit_guest_dialog_message" msgid="8183450985628495709">"এই ছেশ্বনৰ সকলো এপ্ আৰু ডেটা মচা হ\'ব।"</string>
+ <string name="guest_exit_guest_dialog_message" msgid="8183450985628495709">"এই ছেশ্বনৰ আটাইবোৰ এপ্ আৰু ডেটা মচা হ\'ব।"</string>
<string name="guest_exit_guest_dialog_remove" msgid="7505817591242703757">"আঁতৰাওক"</string>
<string name="guest_wipe_session_title" msgid="7147965814683990944">"অতিথি, আপোনাক পুনৰ স্বাগতম!"</string>
<string name="guest_wipe_session_message" msgid="3393823610257065457">"আপুনি আপোনাৰ ছেশ্বন অব্যাহত ৰাখিব বিচাৰেনে?"</string>
@@ -502,24 +502,24 @@
<item quantity="other">আপুনি <xliff:g id="COUNT">%d</xliff:g> জনলৈকে ব্যৱহাৰকাৰী যোগ কৰিব পাৰে।</item>
</plurals>
<string name="user_remove_user_title" msgid="9124124694835811874">"ব্যৱহাৰকাৰীক আঁতৰাবনে?"</string>
- <string name="user_remove_user_message" msgid="6702834122128031833">"এই ব্যৱহাৰকাৰীৰ সকলো এপ্ আৰু ডেটা মচা হ\'ব।"</string>
+ <string name="user_remove_user_message" msgid="6702834122128031833">"এই ব্যৱহাৰকাৰীৰ আটাইবোৰ এপ্ আৰু ডেটা মচা হ\'ব।"</string>
<string name="user_remove_user_remove" msgid="8387386066949061256">"আঁতৰাওক"</string>
<string name="battery_saver_notification_title" msgid="8419266546034372562">"বেটাৰী সঞ্চয়কাৰী অন হৈ আছে"</string>
<string name="battery_saver_notification_text" msgid="2617841636449016951">"কাৰ্যদক্ষতা আৰু নেপথ্য ডেটা হ্ৰাস কৰে"</string>
<string name="battery_saver_notification_action_text" msgid="6022091913807026887">"বেটাৰী সঞ্চয়কাৰী অফ কৰক"</string>
- <string name="media_projection_dialog_text" msgid="1755705274910034772">"<xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g>এ আপোনাৰ স্ক্ৰীনত দৃশ্যমান হোৱা অথবা ৰেকর্ডিং অথবা কাষ্টিঙৰ সময়ত আপোনাৰ ডিভাইচত প্লে\' কৰা সকলো তথ্যলৈ এক্সেছ পাব। এইটোত পাছৱর্ড, পৰিশোধৰ সবিশেষ, ফট\', বার্তাসমূহ আৰু আপুনি প্লে\' কৰা অডিঅ\'ৰ দৰে তথ্য অন্তর্ভুক্ত হয়।"</string>
- <string name="media_projection_dialog_service_text" msgid="958000992162214611">"এই সুবিধাটো প্ৰদান কৰা সেৱাটোৱে আপোনাৰ স্ক্ৰীনত দৃশ্যমান হোৱা অথবা ৰেকর্ডিং অথবা কাষ্টিংৰ সময়ত আপোনাৰ ডিভাইচত প্লে\' কৰা সকলো তথ্যলৈ এক্সেছ পাব। এইটোত পাছৱর্ড, পৰিশোধৰ সবিশেষ, ফট\', বার্তাসমূহ আৰু আপুনি প্লে\' কৰা অডিঅ\'ৰ দৰে তথ্য অন্তর্ভুক্ত হয়।"</string>
+ <string name="media_projection_dialog_text" msgid="1755705274910034772">"<xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g>এ আপোনাৰ স্ক্ৰীনত দৃশ্যমান হোৱা অথবা ৰেকর্ডিং অথবা কাষ্টিঙৰ সময়ত আপোনাৰ ডিভাইচত প্লে\' কৰা আটাইবোৰ তথ্যলৈ এক্সেছ পাব। এইটোত পাছৱর্ড, পৰিশোধৰ সবিশেষ, ফট\', বার্তাসমূহ আৰু আপুনি প্লে\' কৰা অডিঅ\'ৰ দৰে তথ্য অন্তর্ভুক্ত হয়।"</string>
+ <string name="media_projection_dialog_service_text" msgid="958000992162214611">"এই সুবিধাটো প্ৰদান কৰা সেৱাটোৱে আপোনাৰ স্ক্ৰীনত দৃশ্যমান হোৱা অথবা ৰেকর্ডিং অথবা কাষ্টিঙৰ সময়ত আপোনাৰ ডিভাইচত প্লে\' কৰা আটাইবোৰ তথ্যলৈ এক্সেছ পাব। এইটোত পাছৱর্ড, পৰিশোধৰ সবিশেষ, ফট\', বার্তাসমূহ আৰু আপুনি প্লে\' কৰা অডিঅ\'ৰ দৰে তথ্য অন্তর্ভুক্ত হয়।"</string>
<string name="media_projection_dialog_service_title" msgid="2888507074107884040">"ৰেকর্ডিং অথবা কাষ্টিং আৰম্ভ কৰিবনে?"</string>
<string name="media_projection_dialog_title" msgid="3316063622495360646">"<xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g>ৰ জৰিয়তে ৰেকর্ডিং অথবা কাষ্টিং আৰম্ভ কৰিবনে ?"</string>
<string name="media_projection_remember_text" msgid="6896767327140422951">"পুনৰাই নেদেখুৱাব"</string>
- <string name="clear_all_notifications_text" msgid="348312370303046130">"সকলো মচক"</string>
+ <string name="clear_all_notifications_text" msgid="348312370303046130">"আটাইবোৰ মচক"</string>
<string name="manage_notifications_text" msgid="6885645344647733116">"পৰিচালনা"</string>
<string name="manage_notifications_history_text" msgid="57055985396576230">"ইতিহাস"</string>
<string name="notification_section_header_incoming" msgid="850925217908095197">"নতুন"</string>
<string name="notification_section_header_gentle" msgid="6804099527336337197">"নীৰৱ"</string>
<string name="notification_section_header_alerting" msgid="5581175033680477651">"জাননীসমূহ"</string>
<string name="notification_section_header_conversations" msgid="821834744538345661">"বাৰ্তালাপ"</string>
- <string name="accessibility_notification_section_header_gentle_clear_all" msgid="6490207897764933919">"সকলো নীৰৱ জাননী মচক"</string>
+ <string name="accessibility_notification_section_header_gentle_clear_all" msgid="6490207897764933919">"আটাইবোৰ নীৰৱ জাননী মচক"</string>
<string name="dnd_suppressing_shade_text" msgid="5588252250634464042">"অসুবিধা নিদিব-ই জাননী পজ কৰিছে"</string>
<string name="media_projection_action_text" msgid="3634906766918186440">"এতিয়াই আৰম্ভ কৰক"</string>
<string name="empty_shade_text" msgid="8935967157319717412">"কোনো জাননী নাই"</string>
@@ -704,7 +704,7 @@
<string name="enable_bluetooth_message" msgid="6740938333772779717">"আপোনাৰ টেবলেটত আপোনাৰ কীব\'ৰ্ড সংযোগ কৰিবলৈ আপুনি প্ৰথমে ব্লুটুথ অন কৰিব লাগিব।"</string>
<string name="enable_bluetooth_confirmation_ok" msgid="2866408183324184876">"অন কৰক"</string>
<string name="show_silently" msgid="5629369640872236299">"জাননীসমূহ নীৰৱে দেখুৱাওক"</string>
- <string name="block" msgid="188483833983476566">"সকলো জাননী অৱৰোধ কৰক"</string>
+ <string name="block" msgid="188483833983476566">"আটাইবোৰ জাননী অৱৰোধ কৰক"</string>
<string name="do_not_silence" msgid="4982217934250511227">"নীৰৱ নকৰিব"</string>
<string name="do_not_silence_block" msgid="4361847809775811849">"নীৰৱ অথবা অৱৰোধ নকৰিব"</string>
<string name="tuner_full_importance_settings" msgid="1388025816553459059">"জাননী নিয়ন্ত্ৰণৰ অধিক কৰ্তৃত্ব"</string>
@@ -754,7 +754,7 @@
<string name="notification_unblockable_desc" msgid="2073030886006190804">"এই জাননীসমূহ সংশোধন কৰিব নোৱাৰি।"</string>
<string name="notification_multichannel_desc" msgid="7414593090056236179">"এই ধৰণৰ জাননীবোৰ ইয়াত কনফিগাৰ কৰিব পৰা নাযায়"</string>
<string name="notification_delegate_header" msgid="1264510071031479920">"প্ৰক্সি হিচাপে পঠিওৱা জাননী"</string>
- <string name="notification_channel_dialog_title" msgid="6856514143093200019">"<xliff:g id="APP_NAME">%1$s</xliff:g>ৰ সকলো জাননী"</string>
+ <string name="notification_channel_dialog_title" msgid="6856514143093200019">"<xliff:g id="APP_NAME">%1$s</xliff:g>ৰ আটাইবোৰ জাননী"</string>
<string name="see_more_title" msgid="7409317011708185729">"অধিক চাওক"</string>
<string name="appops_camera" msgid="5215967620896725715">"এই এপে কেমেৰা ব্য়ৱহাৰ কৰি আছে।"</string>
<string name="appops_microphone" msgid="8805468338613070149">"এই এপে মাইক্ৰ\'ফ\'ন ব্য়ৱহাৰ কৰি আছে।"</string>
@@ -1062,7 +1062,7 @@
<string name="controls_favorite_default_title" msgid="967742178688938137">"নিয়ন্ত্ৰণসমূহ"</string>
<string name="controls_favorite_subtitle" msgid="6481675111056961083">"ক্ষিপ্ৰ ছেটিঙৰ পৰা এক্সেছ কৰিবলৈ নিয়ন্ত্ৰণসমূহ বাছনি কৰক"</string>
<string name="controls_favorite_rearrange" msgid="5616952398043063519">"নিয়ন্ত্ৰণসমূহ পুনৰ সজাবলৈ ধৰি ৰাখক আৰু টানি আনি এৰক"</string>
- <string name="controls_favorite_removed" msgid="5276978408529217272">"সকলো নিয়ন্ত্ৰণ আঁতৰোৱা হৈছে"</string>
+ <string name="controls_favorite_removed" msgid="5276978408529217272">"আটাইবোৰ নিয়ন্ত্ৰণ আঁতৰোৱা হৈছে"</string>
<string name="controls_favorite_toast_no_changes" msgid="7094494210840877931">"সালসলনিসমূহ ছেভ নহ’ল"</string>
<string name="controls_favorite_see_other_apps" msgid="7709087332255283460">"অন্য এপ্সমূহ চাওক"</string>
<string name="controls_favorite_load_error" msgid="5126216176144877419">"নিয়ন্ত্ৰণসমূহ ল’ড কৰিবপৰা নগ’ল। এপ্টোৰ ছেটিং সলনি কৰা হোৱা নাই বুলি নিশ্চিত কৰিবলৈ <xliff:g id="APP">%s</xliff:g> এপ্টো পৰীক্ষা কৰক।"</string>
@@ -1111,7 +1111,7 @@
<string name="media_output_dialog_group" msgid="5571251347877452212">"গোট"</string>
<string name="media_output_dialog_single_device" msgid="3102758980643351058">"১ টা ডিভাইচ বাছনি কৰা হৈছে"</string>
<string name="media_output_dialog_multiple_devices" msgid="1093771040315422350">"<xliff:g id="COUNT">%1$d</xliff:g> টা ডিভাইচ বাছনি কৰা হৈছে"</string>
- <string name="media_output_dialog_disconnected" msgid="1834473104836986046">"<xliff:g id="DEVICE_NAME">%1$s</xliff:g> (সংযোগ বিচ্ছিন্ন হৈছে)"</string>
+ <string name="media_output_dialog_disconnected" msgid="7090512852817111185">"(সংযোগ বিচ্ছিন্ন কৰা হৈছে)"</string>
<string name="media_output_dialog_connect_failed" msgid="3225190634236259010">"সংযোগ কৰিব পৰা নগ’ল। পুনৰ চেষ্টা কৰক।"</string>
<string name="media_output_dialog_pairing_new" msgid="9099497976087485862">"নতুন ডিভাইচ পেয়াৰ কৰক"</string>
<string name="build_number_clip_data_label" msgid="3623176728412560914">"বিল্ডৰ নম্বৰ"</string>
diff --git a/packages/SystemUI/res/values-az/strings.xml b/packages/SystemUI/res/values-az/strings.xml
index 72b9836..6544071 100644
--- a/packages/SystemUI/res/values-az/strings.xml
+++ b/packages/SystemUI/res/values-az/strings.xml
@@ -1111,7 +1111,7 @@
<string name="media_output_dialog_group" msgid="5571251347877452212">"Qrup"</string>
<string name="media_output_dialog_single_device" msgid="3102758980643351058">"1 cihaz seçilib"</string>
<string name="media_output_dialog_multiple_devices" msgid="1093771040315422350">"<xliff:g id="COUNT">%1$d</xliff:g> cihaz seçilib"</string>
- <string name="media_output_dialog_disconnected" msgid="1834473104836986046">"<xliff:g id="DEVICE_NAME">%1$s</xliff:g> (bağlantı kəsilib)"</string>
+ <string name="media_output_dialog_disconnected" msgid="7090512852817111185">"(bağlantı kəsildi)"</string>
<string name="media_output_dialog_connect_failed" msgid="3225190634236259010">"Qoşulmaq alınmadı. Yenə cəhd edin."</string>
<string name="media_output_dialog_pairing_new" msgid="9099497976087485862">"Cihaz əlavə edin"</string>
<string name="build_number_clip_data_label" msgid="3623176728412560914">"Montaj nömrəsi"</string>
diff --git a/packages/SystemUI/res/values-b+sr+Latn/strings.xml b/packages/SystemUI/res/values-b+sr+Latn/strings.xml
index f9468ee..eeae5c4 100644
--- a/packages/SystemUI/res/values-b+sr+Latn/strings.xml
+++ b/packages/SystemUI/res/values-b+sr+Latn/strings.xml
@@ -1117,7 +1117,7 @@
<string name="media_output_dialog_group" msgid="5571251347877452212">"Grupa"</string>
<string name="media_output_dialog_single_device" msgid="3102758980643351058">"Izabran je 1 uređaj"</string>
<string name="media_output_dialog_multiple_devices" msgid="1093771040315422350">"Izabranih uređaja: <xliff:g id="COUNT">%1$d</xliff:g>"</string>
- <string name="media_output_dialog_disconnected" msgid="1834473104836986046">"<xliff:g id="DEVICE_NAME">%1$s</xliff:g> (veza je prekinuta)"</string>
+ <string name="media_output_dialog_disconnected" msgid="7090512852817111185">"(veza je prekinuta)"</string>
<string name="media_output_dialog_connect_failed" msgid="3225190634236259010">"Povezivanje nije uspelo. Probajte ponovo."</string>
<string name="media_output_dialog_pairing_new" msgid="9099497976087485862">"Upari novi uređaj"</string>
<string name="build_number_clip_data_label" msgid="3623176728412560914">"Broj verzije"</string>
@@ -1161,7 +1161,7 @@
<string name="person_available" msgid="2318599327472755472">"Dostupno"</string>
<string name="battery_state_unknown_notification_title" msgid="8464703640483773454">"Problem sa očitavanjem merača baterije"</string>
<string name="battery_state_unknown_notification_text" msgid="13720937839460899">"Dodirnite za više informacija"</string>
- <string name="qs_alarm_tile_no_alarm" msgid="4826472008616807923">"Alarm nije podešen"</string>
+ <string name="qs_alarm_tile_no_alarm" msgid="4826472008616807923">"Nije podešen"</string>
<string name="accessibility_fingerprint_label" msgid="5255731221854153660">"Senzor za otisak prsta"</string>
<string name="accessibility_udfps_disabled_button" msgid="4284034245130239384">"Senzor za otisak prsta je onemogućen"</string>
<string name="accessibility_authenticate_hint" msgid="798914151813205721">"potvrdite identitet"</string>
diff --git a/packages/SystemUI/res/values-be/strings.xml b/packages/SystemUI/res/values-be/strings.xml
index bee7943..9b1f3e9 100644
--- a/packages/SystemUI/res/values-be/strings.xml
+++ b/packages/SystemUI/res/values-be/strings.xml
@@ -1123,7 +1123,7 @@
<string name="media_output_dialog_group" msgid="5571251347877452212">"Група"</string>
<string name="media_output_dialog_single_device" msgid="3102758980643351058">"Выбрана 1 прылада"</string>
<string name="media_output_dialog_multiple_devices" msgid="1093771040315422350">"Выбрана прылад: <xliff:g id="COUNT">%1$d</xliff:g>"</string>
- <string name="media_output_dialog_disconnected" msgid="1834473104836986046">"<xliff:g id="DEVICE_NAME">%1$s</xliff:g> (адключана)"</string>
+ <string name="media_output_dialog_disconnected" msgid="7090512852817111185">"(адключана)"</string>
<string name="media_output_dialog_connect_failed" msgid="3225190634236259010">"Не ўдалося падключыцца. Паўтарыце спробу."</string>
<string name="media_output_dialog_pairing_new" msgid="9099497976087485862">"Спалучыць з новай прыладай"</string>
<string name="build_number_clip_data_label" msgid="3623176728412560914">"Нумар зборкі"</string>
diff --git a/packages/SystemUI/res/values-bg/strings.xml b/packages/SystemUI/res/values-bg/strings.xml
index e126034..44a9a7f 100644
--- a/packages/SystemUI/res/values-bg/strings.xml
+++ b/packages/SystemUI/res/values-bg/strings.xml
@@ -1111,7 +1111,7 @@
<string name="media_output_dialog_group" msgid="5571251347877452212">"Група"</string>
<string name="media_output_dialog_single_device" msgid="3102758980643351058">"1 избрано устройство"</string>
<string name="media_output_dialog_multiple_devices" msgid="1093771040315422350">"<xliff:g id="COUNT">%1$d</xliff:g> избрани устройства"</string>
- <string name="media_output_dialog_disconnected" msgid="1834473104836986046">"<xliff:g id="DEVICE_NAME">%1$s</xliff:g> (връзката е прекратена)"</string>
+ <string name="media_output_dialog_disconnected" msgid="7090512852817111185">"(връзката е прекратена)"</string>
<string name="media_output_dialog_connect_failed" msgid="3225190634236259010">"Неуспешно свързване. Опитайте отново."</string>
<string name="media_output_dialog_pairing_new" msgid="9099497976087485862">"Сдвояване на ново устройство"</string>
<string name="build_number_clip_data_label" msgid="3623176728412560914">"Номер на компилацията"</string>
diff --git a/packages/SystemUI/res/values-bn/strings.xml b/packages/SystemUI/res/values-bn/strings.xml
index bde0d8c..d7a5314 100644
--- a/packages/SystemUI/res/values-bn/strings.xml
+++ b/packages/SystemUI/res/values-bn/strings.xml
@@ -1111,7 +1111,7 @@
<string name="media_output_dialog_group" msgid="5571251347877452212">"গ্রুপ"</string>
<string name="media_output_dialog_single_device" msgid="3102758980643351058">"১টি ডিভাইস বেছে নেওয়া হয়েছে"</string>
<string name="media_output_dialog_multiple_devices" msgid="1093771040315422350">"<xliff:g id="COUNT">%1$d</xliff:g>টি ডিভাইস বেছে নেওয়া হয়েছে"</string>
- <string name="media_output_dialog_disconnected" msgid="1834473104836986046">"<xliff:g id="DEVICE_NAME">%1$s</xliff:g> (কানেক্ট করা নেই)"</string>
+ <string name="media_output_dialog_disconnected" msgid="7090512852817111185">"(ডিসকানেক্ট হয়ে গেছে)"</string>
<string name="media_output_dialog_connect_failed" msgid="3225190634236259010">"কানেক্ট করা যায়নি। আবার চেষ্টা করুন।"</string>
<string name="media_output_dialog_pairing_new" msgid="9099497976087485862">"নতুন ডিভাইস পেয়ার করুন"</string>
<string name="build_number_clip_data_label" msgid="3623176728412560914">"বিল্ড নম্বর"</string>
diff --git a/packages/SystemUI/res/values-bs/strings.xml b/packages/SystemUI/res/values-bs/strings.xml
index c29cc31..d78839d 100644
--- a/packages/SystemUI/res/values-bs/strings.xml
+++ b/packages/SystemUI/res/values-bs/strings.xml
@@ -1117,7 +1117,7 @@
<string name="media_output_dialog_group" msgid="5571251347877452212">"Grupa"</string>
<string name="media_output_dialog_single_device" msgid="3102758980643351058">"Odabran je 1 uređaj"</string>
<string name="media_output_dialog_multiple_devices" msgid="1093771040315422350">"Broj odabranih uređaja: <xliff:g id="COUNT">%1$d</xliff:g>"</string>
- <string name="media_output_dialog_disconnected" msgid="1834473104836986046">"<xliff:g id="DEVICE_NAME">%1$s</xliff:g> (veza je prekinuta)"</string>
+ <string name="media_output_dialog_disconnected" msgid="7090512852817111185">"(veza je prekinuta)"</string>
<string name="media_output_dialog_connect_failed" msgid="3225190634236259010">"Povezivanje nije uspjelo. Pokušajte ponovo."</string>
<string name="media_output_dialog_pairing_new" msgid="9099497976087485862">"Uparite novi uređaj"</string>
<string name="build_number_clip_data_label" msgid="3623176728412560914">"Broj verzije"</string>
diff --git a/packages/SystemUI/res/values-ca/strings.xml b/packages/SystemUI/res/values-ca/strings.xml
index 751a49d..da5ad71 100644
--- a/packages/SystemUI/res/values-ca/strings.xml
+++ b/packages/SystemUI/res/values-ca/strings.xml
@@ -1111,7 +1111,7 @@
<string name="media_output_dialog_group" msgid="5571251347877452212">"Grup"</string>
<string name="media_output_dialog_single_device" msgid="3102758980643351058">"1 dispositiu seleccionat"</string>
<string name="media_output_dialog_multiple_devices" msgid="1093771040315422350">"S\'han seleccionat <xliff:g id="COUNT">%1$d</xliff:g> dispositius"</string>
- <string name="media_output_dialog_disconnected" msgid="1834473104836986046">"<xliff:g id="DEVICE_NAME">%1$s</xliff:g> (desconnectat)"</string>
+ <string name="media_output_dialog_disconnected" msgid="7090512852817111185">"(desconnectat)"</string>
<string name="media_output_dialog_connect_failed" msgid="3225190634236259010">"No s\'ha pogut connectar. Torna-ho a provar."</string>
<string name="media_output_dialog_pairing_new" msgid="9099497976087485862">"Vincula un dispositiu nou"</string>
<string name="build_number_clip_data_label" msgid="3623176728412560914">"Número de compilació"</string>
diff --git a/packages/SystemUI/res/values-cs/strings.xml b/packages/SystemUI/res/values-cs/strings.xml
index 1aa9c44..96c5e8c 100644
--- a/packages/SystemUI/res/values-cs/strings.xml
+++ b/packages/SystemUI/res/values-cs/strings.xml
@@ -1123,7 +1123,7 @@
<string name="media_output_dialog_group" msgid="5571251347877452212">"Skupina"</string>
<string name="media_output_dialog_single_device" msgid="3102758980643351058">"Je vybráno 1 zařízení"</string>
<string name="media_output_dialog_multiple_devices" msgid="1093771040315422350">"Vybraná zařízení: <xliff:g id="COUNT">%1$d</xliff:g>"</string>
- <string name="media_output_dialog_disconnected" msgid="1834473104836986046">"<xliff:g id="DEVICE_NAME">%1$s</xliff:g> (odpojeno)"</string>
+ <string name="media_output_dialog_disconnected" msgid="7090512852817111185">"(odpojeno)"</string>
<string name="media_output_dialog_connect_failed" msgid="3225190634236259010">"Spojení se nezdařilo. Zkuste to znovu."</string>
<string name="media_output_dialog_pairing_new" msgid="9099497976087485862">"Spárovat nové zařízení"</string>
<string name="build_number_clip_data_label" msgid="3623176728412560914">"Číslo sestavení"</string>
diff --git a/packages/SystemUI/res/values-da/strings.xml b/packages/SystemUI/res/values-da/strings.xml
index 492546f..a70c896 100644
--- a/packages/SystemUI/res/values-da/strings.xml
+++ b/packages/SystemUI/res/values-da/strings.xml
@@ -1111,7 +1111,7 @@
<string name="media_output_dialog_group" msgid="5571251347877452212">"Gruppe"</string>
<string name="media_output_dialog_single_device" msgid="3102758980643351058">"Der er valgt 1 enhed"</string>
<string name="media_output_dialog_multiple_devices" msgid="1093771040315422350">"Der er valgt <xliff:g id="COUNT">%1$d</xliff:g> enhed"</string>
- <string name="media_output_dialog_disconnected" msgid="1834473104836986046">"<xliff:g id="DEVICE_NAME">%1$s</xliff:g> (ingen forbindelse)"</string>
+ <string name="media_output_dialog_disconnected" msgid="7090512852817111185">"(afbrudt)"</string>
<string name="media_output_dialog_connect_failed" msgid="3225190634236259010">"Der kunne ikke oprettes forbindelse. Prøv igen."</string>
<string name="media_output_dialog_pairing_new" msgid="9099497976087485862">"Par ny enhed"</string>
<string name="build_number_clip_data_label" msgid="3623176728412560914">"Buildnummer"</string>
diff --git a/packages/SystemUI/res/values-de/strings.xml b/packages/SystemUI/res/values-de/strings.xml
index 085e082..3eb1715 100644
--- a/packages/SystemUI/res/values-de/strings.xml
+++ b/packages/SystemUI/res/values-de/strings.xml
@@ -1111,7 +1111,7 @@
<string name="media_output_dialog_group" msgid="5571251347877452212">"Gruppe"</string>
<string name="media_output_dialog_single_device" msgid="3102758980643351058">"Ein Gerät ausgewählt"</string>
<string name="media_output_dialog_multiple_devices" msgid="1093771040315422350">"<xliff:g id="COUNT">%1$d</xliff:g> Geräte ausgewählt"</string>
- <string name="media_output_dialog_disconnected" msgid="1834473104836986046">"<xliff:g id="DEVICE_NAME">%1$s</xliff:g> (nicht verbunden)"</string>
+ <string name="media_output_dialog_disconnected" msgid="7090512852817111185">"(nicht verbunden)"</string>
<string name="media_output_dialog_connect_failed" msgid="3225190634236259010">"Verbindung nicht möglich. Versuch es noch einmal."</string>
<string name="media_output_dialog_pairing_new" msgid="9099497976087485862">"Neues Gerät koppeln"</string>
<string name="build_number_clip_data_label" msgid="3623176728412560914">"Build-Nummer"</string>
diff --git a/packages/SystemUI/res/values-el/strings.xml b/packages/SystemUI/res/values-el/strings.xml
index b6ef245..39ee63a 100644
--- a/packages/SystemUI/res/values-el/strings.xml
+++ b/packages/SystemUI/res/values-el/strings.xml
@@ -1111,7 +1111,7 @@
<string name="media_output_dialog_group" msgid="5571251347877452212">"Ομάδα"</string>
<string name="media_output_dialog_single_device" msgid="3102758980643351058">"Επιλέχτηκε 1 συσκευή"</string>
<string name="media_output_dialog_multiple_devices" msgid="1093771040315422350">"Επιλέχτηκαν <xliff:g id="COUNT">%1$d</xliff:g> συσκευές"</string>
- <string name="media_output_dialog_disconnected" msgid="1834473104836986046">"<xliff:g id="DEVICE_NAME">%1$s</xliff:g> (αποσυνδέθηκε)"</string>
+ <string name="media_output_dialog_disconnected" msgid="7090512852817111185">"(αποσυνδέθηκε)"</string>
<string name="media_output_dialog_connect_failed" msgid="3225190634236259010">"Δεν ήταν δυνατή η σύνδεση. Δοκιμάστε ξανά."</string>
<string name="media_output_dialog_pairing_new" msgid="9099497976087485862">"Σύζευξη νέας συσκευής"</string>
<string name="build_number_clip_data_label" msgid="3623176728412560914">"Αριθμός έκδοσης"</string>
diff --git a/packages/SystemUI/res/values-en-rAU/strings.xml b/packages/SystemUI/res/values-en-rAU/strings.xml
index d50402f..74bf5c4 100644
--- a/packages/SystemUI/res/values-en-rAU/strings.xml
+++ b/packages/SystemUI/res/values-en-rAU/strings.xml
@@ -1111,7 +1111,7 @@
<string name="media_output_dialog_group" msgid="5571251347877452212">"Group"</string>
<string name="media_output_dialog_single_device" msgid="3102758980643351058">"One device selected"</string>
<string name="media_output_dialog_multiple_devices" msgid="1093771040315422350">"<xliff:g id="COUNT">%1$d</xliff:g> devices selected"</string>
- <string name="media_output_dialog_disconnected" msgid="1834473104836986046">"<xliff:g id="DEVICE_NAME">%1$s</xliff:g> (disconnected)"</string>
+ <string name="media_output_dialog_disconnected" msgid="7090512852817111185">"(disconnected)"</string>
<string name="media_output_dialog_connect_failed" msgid="3225190634236259010">"Couldn\'t connect. Try again."</string>
<string name="media_output_dialog_pairing_new" msgid="9099497976087485862">"Pair new device"</string>
<string name="build_number_clip_data_label" msgid="3623176728412560914">"Build number"</string>
diff --git a/packages/SystemUI/res/values-en-rCA/strings.xml b/packages/SystemUI/res/values-en-rCA/strings.xml
index d30be77..262f9e1 100644
--- a/packages/SystemUI/res/values-en-rCA/strings.xml
+++ b/packages/SystemUI/res/values-en-rCA/strings.xml
@@ -1111,7 +1111,7 @@
<string name="media_output_dialog_group" msgid="5571251347877452212">"Group"</string>
<string name="media_output_dialog_single_device" msgid="3102758980643351058">"One device selected"</string>
<string name="media_output_dialog_multiple_devices" msgid="1093771040315422350">"<xliff:g id="COUNT">%1$d</xliff:g> devices selected"</string>
- <string name="media_output_dialog_disconnected" msgid="1834473104836986046">"<xliff:g id="DEVICE_NAME">%1$s</xliff:g> (disconnected)"</string>
+ <string name="media_output_dialog_disconnected" msgid="7090512852817111185">"(disconnected)"</string>
<string name="media_output_dialog_connect_failed" msgid="3225190634236259010">"Couldn\'t connect. Try again."</string>
<string name="media_output_dialog_pairing_new" msgid="9099497976087485862">"Pair new device"</string>
<string name="build_number_clip_data_label" msgid="3623176728412560914">"Build number"</string>
diff --git a/packages/SystemUI/res/values-en-rGB/strings.xml b/packages/SystemUI/res/values-en-rGB/strings.xml
index d50402f..74bf5c4 100644
--- a/packages/SystemUI/res/values-en-rGB/strings.xml
+++ b/packages/SystemUI/res/values-en-rGB/strings.xml
@@ -1111,7 +1111,7 @@
<string name="media_output_dialog_group" msgid="5571251347877452212">"Group"</string>
<string name="media_output_dialog_single_device" msgid="3102758980643351058">"One device selected"</string>
<string name="media_output_dialog_multiple_devices" msgid="1093771040315422350">"<xliff:g id="COUNT">%1$d</xliff:g> devices selected"</string>
- <string name="media_output_dialog_disconnected" msgid="1834473104836986046">"<xliff:g id="DEVICE_NAME">%1$s</xliff:g> (disconnected)"</string>
+ <string name="media_output_dialog_disconnected" msgid="7090512852817111185">"(disconnected)"</string>
<string name="media_output_dialog_connect_failed" msgid="3225190634236259010">"Couldn\'t connect. Try again."</string>
<string name="media_output_dialog_pairing_new" msgid="9099497976087485862">"Pair new device"</string>
<string name="build_number_clip_data_label" msgid="3623176728412560914">"Build number"</string>
diff --git a/packages/SystemUI/res/values-en-rIN/strings.xml b/packages/SystemUI/res/values-en-rIN/strings.xml
index d50402f..74bf5c4 100644
--- a/packages/SystemUI/res/values-en-rIN/strings.xml
+++ b/packages/SystemUI/res/values-en-rIN/strings.xml
@@ -1111,7 +1111,7 @@
<string name="media_output_dialog_group" msgid="5571251347877452212">"Group"</string>
<string name="media_output_dialog_single_device" msgid="3102758980643351058">"One device selected"</string>
<string name="media_output_dialog_multiple_devices" msgid="1093771040315422350">"<xliff:g id="COUNT">%1$d</xliff:g> devices selected"</string>
- <string name="media_output_dialog_disconnected" msgid="1834473104836986046">"<xliff:g id="DEVICE_NAME">%1$s</xliff:g> (disconnected)"</string>
+ <string name="media_output_dialog_disconnected" msgid="7090512852817111185">"(disconnected)"</string>
<string name="media_output_dialog_connect_failed" msgid="3225190634236259010">"Couldn\'t connect. Try again."</string>
<string name="media_output_dialog_pairing_new" msgid="9099497976087485862">"Pair new device"</string>
<string name="build_number_clip_data_label" msgid="3623176728412560914">"Build number"</string>
diff --git a/packages/SystemUI/res/values-en-rXC/strings.xml b/packages/SystemUI/res/values-en-rXC/strings.xml
index 880be2b..015d9bf 100644
--- a/packages/SystemUI/res/values-en-rXC/strings.xml
+++ b/packages/SystemUI/res/values-en-rXC/strings.xml
@@ -1111,7 +1111,7 @@
<string name="media_output_dialog_group" msgid="5571251347877452212">"Group"</string>
<string name="media_output_dialog_single_device" msgid="3102758980643351058">"1 device selected"</string>
<string name="media_output_dialog_multiple_devices" msgid="1093771040315422350">"<xliff:g id="COUNT">%1$d</xliff:g> devices selected"</string>
- <string name="media_output_dialog_disconnected" msgid="1834473104836986046">"<xliff:g id="DEVICE_NAME">%1$s</xliff:g> (disconnected)"</string>
+ <string name="media_output_dialog_disconnected" msgid="7090512852817111185">"(disconnected)"</string>
<string name="media_output_dialog_connect_failed" msgid="3225190634236259010">"Couldn\'t connect. Try again."</string>
<string name="media_output_dialog_pairing_new" msgid="9099497976087485862">"Pair new device"</string>
<string name="build_number_clip_data_label" msgid="3623176728412560914">"Build number"</string>
diff --git a/packages/SystemUI/res/values-es-rUS/strings.xml b/packages/SystemUI/res/values-es-rUS/strings.xml
index f68196bf..bc150e0 100644
--- a/packages/SystemUI/res/values-es-rUS/strings.xml
+++ b/packages/SystemUI/res/values-es-rUS/strings.xml
@@ -807,7 +807,7 @@
<string name="battery_detail_switch_title" msgid="6940976502957380405">"Ahorro de batería"</string>
<string name="battery_detail_switch_summary" msgid="3668748557848025990">"Reduce el rendimiento y el uso de datos en segundo plano"</string>
<string name="keyboard_key_button_template" msgid="8005673627272051429">"Botón <xliff:g id="NAME">%1$s</xliff:g>"</string>
- <string name="keyboard_key_home" msgid="3734400625170020657">"Página principal"</string>
+ <string name="keyboard_key_home" msgid="3734400625170020657">"Inicio"</string>
<string name="keyboard_key_back" msgid="4185420465469481999">"Atrás"</string>
<string name="keyboard_key_dpad_up" msgid="2164184320424941416">"Arriba"</string>
<string name="keyboard_key_dpad_down" msgid="2110172278574325796">"Abajo"</string>
@@ -827,7 +827,7 @@
<string name="keyboard_key_page_up" msgid="173914303254199845">"Re Pág"</string>
<string name="keyboard_key_page_down" msgid="9035902490071829731">"Av Pág"</string>
<string name="keyboard_key_forward_del" msgid="5325501825762733459">"Borrar"</string>
- <string name="keyboard_key_move_home" msgid="3496502501803911971">"Página principal"</string>
+ <string name="keyboard_key_move_home" msgid="3496502501803911971">"Inicio"</string>
<string name="keyboard_key_move_end" msgid="99190401463834854">"Fin"</string>
<string name="keyboard_key_insert" msgid="4621692715704410493">"Insertar"</string>
<string name="keyboard_key_num_lock" msgid="7209960042043090548">"Bloqueo numérico"</string>
@@ -1111,7 +1111,7 @@
<string name="media_output_dialog_group" msgid="5571251347877452212">"Grupo"</string>
<string name="media_output_dialog_single_device" msgid="3102758980643351058">"Se seleccionó 1 dispositivo"</string>
<string name="media_output_dialog_multiple_devices" msgid="1093771040315422350">"Se seleccionaron <xliff:g id="COUNT">%1$d</xliff:g> dispositivos"</string>
- <string name="media_output_dialog_disconnected" msgid="1834473104836986046">"<xliff:g id="DEVICE_NAME">%1$s</xliff:g> (desconectado)"</string>
+ <string name="media_output_dialog_disconnected" msgid="7090512852817111185">"(desconectado)"</string>
<string name="media_output_dialog_connect_failed" msgid="3225190634236259010">"No se pudo establecer la conexión. Vuelve a intentarlo."</string>
<string name="media_output_dialog_pairing_new" msgid="9099497976087485862">"Vincular dispositivo nuevo"</string>
<string name="build_number_clip_data_label" msgid="3623176728412560914">"Número de compilación"</string>
diff --git a/packages/SystemUI/res/values-es/strings.xml b/packages/SystemUI/res/values-es/strings.xml
index 7f4c0bc..fae2ba6 100644
--- a/packages/SystemUI/res/values-es/strings.xml
+++ b/packages/SystemUI/res/values-es/strings.xml
@@ -1111,7 +1111,7 @@
<string name="media_output_dialog_group" msgid="5571251347877452212">"Grupo"</string>
<string name="media_output_dialog_single_device" msgid="3102758980643351058">"1 dispositivo seleccionado"</string>
<string name="media_output_dialog_multiple_devices" msgid="1093771040315422350">"<xliff:g id="COUNT">%1$d</xliff:g> dispositivos seleccionados"</string>
- <string name="media_output_dialog_disconnected" msgid="1834473104836986046">"<xliff:g id="DEVICE_NAME">%1$s</xliff:g> (desconectado)"</string>
+ <string name="media_output_dialog_disconnected" msgid="7090512852817111185">"(desconectado)"</string>
<string name="media_output_dialog_connect_failed" msgid="3225190634236259010">"No se ha podido conectar. Inténtalo de nuevo."</string>
<string name="media_output_dialog_pairing_new" msgid="9099497976087485862">"Emparejar nuevo dispositivo"</string>
<string name="build_number_clip_data_label" msgid="3623176728412560914">"Número de compilación"</string>
diff --git a/packages/SystemUI/res/values-et/strings.xml b/packages/SystemUI/res/values-et/strings.xml
index 9bd6e83..f71c163 100644
--- a/packages/SystemUI/res/values-et/strings.xml
+++ b/packages/SystemUI/res/values-et/strings.xml
@@ -345,7 +345,7 @@
<string name="quick_settings_bluetooth_secondary_label_hearing_aids" msgid="3003338571871392293">"Kuuldeaparaadid"</string>
<string name="quick_settings_bluetooth_secondary_label_transient" msgid="3882884317600669650">"Sisselülitamine …"</string>
<string name="quick_settings_brightness_label" msgid="680259653088849563">"Heledus"</string>
- <string name="quick_settings_rotation_unlocked_label" msgid="2359922767950346112">"Automaatne pööramine"</string>
+ <string name="quick_settings_rotation_unlocked_label" msgid="2359922767950346112">"Autom. pööramine"</string>
<string name="accessibility_quick_settings_rotation" msgid="4800050198392260738">"Kuva automaatne pööramine"</string>
<string name="accessibility_quick_settings_rotation_value" msgid="2916484894750819251">"Režiim <xliff:g id="ID_1">%s</xliff:g>"</string>
<string name="quick_settings_rotation_locked_label" msgid="4420863550666310319">"Pööramine on lukustatud"</string>
@@ -1111,7 +1111,7 @@
<string name="media_output_dialog_group" msgid="5571251347877452212">"Grupp"</string>
<string name="media_output_dialog_single_device" msgid="3102758980643351058">"1 seade on valitud"</string>
<string name="media_output_dialog_multiple_devices" msgid="1093771040315422350">"<xliff:g id="COUNT">%1$d</xliff:g> seadet on valitud"</string>
- <string name="media_output_dialog_disconnected" msgid="1834473104836986046">"<xliff:g id="DEVICE_NAME">%1$s</xliff:g> (pole ühendatud)"</string>
+ <string name="media_output_dialog_disconnected" msgid="7090512852817111185">"(ühendus on katkestatud)"</string>
<string name="media_output_dialog_connect_failed" msgid="3225190634236259010">"Ühenduse loomine ebaõnnestus. Proovige uuesti."</string>
<string name="media_output_dialog_pairing_new" msgid="9099497976087485862">"Uue seadme sidumine"</string>
<string name="build_number_clip_data_label" msgid="3623176728412560914">"Järgunumber"</string>
diff --git a/packages/SystemUI/res/values-eu/strings.xml b/packages/SystemUI/res/values-eu/strings.xml
index 53415d5..75942ae 100644
--- a/packages/SystemUI/res/values-eu/strings.xml
+++ b/packages/SystemUI/res/values-eu/strings.xml
@@ -1111,7 +1111,7 @@
<string name="media_output_dialog_group" msgid="5571251347877452212">"Taldea"</string>
<string name="media_output_dialog_single_device" msgid="3102758980643351058">"1 gailu hautatu da"</string>
<string name="media_output_dialog_multiple_devices" msgid="1093771040315422350">"<xliff:g id="COUNT">%1$d</xliff:g> gailu hautatu dira"</string>
- <string name="media_output_dialog_disconnected" msgid="1834473104836986046">"<xliff:g id="DEVICE_NAME">%1$s</xliff:g> (deskonektatuta)"</string>
+ <string name="media_output_dialog_disconnected" msgid="7090512852817111185">"(deskonektatuta)"</string>
<string name="media_output_dialog_connect_failed" msgid="3225190634236259010">"Ezin izan da konektatu. Saiatu berriro."</string>
<string name="media_output_dialog_pairing_new" msgid="9099497976087485862">"Parekatu beste gailu batekin"</string>
<string name="build_number_clip_data_label" msgid="3623176728412560914">"Konpilazio-zenbakia"</string>
diff --git a/packages/SystemUI/res/values-fa/strings.xml b/packages/SystemUI/res/values-fa/strings.xml
index acb57f8..5a35b0d 100644
--- a/packages/SystemUI/res/values-fa/strings.xml
+++ b/packages/SystemUI/res/values-fa/strings.xml
@@ -1111,7 +1111,7 @@
<string name="media_output_dialog_group" msgid="5571251347877452212">"گروه"</string>
<string name="media_output_dialog_single_device" msgid="3102758980643351058">"۱ دستگاه انتخاب شد"</string>
<string name="media_output_dialog_multiple_devices" msgid="1093771040315422350">"<xliff:g id="COUNT">%1$d</xliff:g> دستگاه انتخاب شد"</string>
- <string name="media_output_dialog_disconnected" msgid="1834473104836986046">"<xliff:g id="DEVICE_NAME">%1$s</xliff:g> (اتصال قطع شد)"</string>
+ <string name="media_output_dialog_disconnected" msgid="7090512852817111185">"(اتصال قطع شد)"</string>
<string name="media_output_dialog_connect_failed" msgid="3225190634236259010">"متصل نشد. دوباره امتحان کنید."</string>
<string name="media_output_dialog_pairing_new" msgid="9099497976087485862">"مرتبط کردن دستگاه جدید"</string>
<string name="build_number_clip_data_label" msgid="3623176728412560914">"شماره ساخت"</string>
@@ -1155,7 +1155,7 @@
<string name="person_available" msgid="2318599327472755472">"دردسترس"</string>
<string name="battery_state_unknown_notification_title" msgid="8464703640483773454">"مشکلی در خواندن میزان باتری وجود دارد"</string>
<string name="battery_state_unknown_notification_text" msgid="13720937839460899">"برای اطلاعات بیشتر ضربه بزنید"</string>
- <string name="qs_alarm_tile_no_alarm" msgid="4826472008616807923">"هشداری تنظیم نشده است"</string>
+ <string name="qs_alarm_tile_no_alarm" msgid="4826472008616807923">"هشداری تنظیم نشده"</string>
<string name="accessibility_fingerprint_label" msgid="5255731221854153660">"حسگر اثرانگشت"</string>
<string name="accessibility_udfps_disabled_button" msgid="4284034245130239384">"حسگر اثر انگشت غیرفعال است"</string>
<string name="accessibility_authenticate_hint" msgid="798914151813205721">"اصالتسنجی کردن"</string>
diff --git a/packages/SystemUI/res/values-fi/strings.xml b/packages/SystemUI/res/values-fi/strings.xml
index 0c1db38..525a800 100644
--- a/packages/SystemUI/res/values-fi/strings.xml
+++ b/packages/SystemUI/res/values-fi/strings.xml
@@ -1046,7 +1046,7 @@
<string name="accessibility_floating_button_action_move_to_edge_and_hide_to_half" msgid="662401168245782658">"Siirrä reunaan ja piilota"</string>
<string name="accessibility_floating_button_action_move_out_edge_and_show" msgid="8354760891651663326">"Siirrä pois reunasta ja näytä"</string>
<string name="accessibility_floating_button_action_double_tap_to_toggle" msgid="7976492639670692037">"vaihda"</string>
- <string name="quick_controls_title" msgid="6839108006171302273">"Laitteiden hallinta"</string>
+ <string name="quick_controls_title" msgid="6839108006171302273">"Laitehallinta"</string>
<string name="controls_providers_title" msgid="6879775889857085056">"Valitse sovellus lisätäksesi säätimiä"</string>
<plurals name="controls_number_of_favorites" formatted="false" msgid="1057347832073807380">
<item quantity="other"><xliff:g id="NUMBER_1">%s</xliff:g> säädintä lisätty</item>
@@ -1111,7 +1111,7 @@
<string name="media_output_dialog_group" msgid="5571251347877452212">"Ryhmä"</string>
<string name="media_output_dialog_single_device" msgid="3102758980643351058">"1 laite valittu"</string>
<string name="media_output_dialog_multiple_devices" msgid="1093771040315422350">"<xliff:g id="COUNT">%1$d</xliff:g> laitetta valittu"</string>
- <string name="media_output_dialog_disconnected" msgid="1834473104836986046">"<xliff:g id="DEVICE_NAME">%1$s</xliff:g> (yhteys katkaistu)"</string>
+ <string name="media_output_dialog_disconnected" msgid="7090512852817111185">"(yhteys katkaistu)"</string>
<string name="media_output_dialog_connect_failed" msgid="3225190634236259010">"Ei yhteyttä. Yritä uudelleen."</string>
<string name="media_output_dialog_pairing_new" msgid="9099497976087485862">"Muodosta uusi laitepari"</string>
<string name="build_number_clip_data_label" msgid="3623176728412560914">"Koontiversion numero"</string>
diff --git a/packages/SystemUI/res/values-fr-rCA/strings.xml b/packages/SystemUI/res/values-fr-rCA/strings.xml
index 6ece89f..e8b1b8b 100644
--- a/packages/SystemUI/res/values-fr-rCA/strings.xml
+++ b/packages/SystemUI/res/values-fr-rCA/strings.xml
@@ -1111,7 +1111,7 @@
<string name="media_output_dialog_group" msgid="5571251347877452212">"Groupe"</string>
<string name="media_output_dialog_single_device" msgid="3102758980643351058">"Un appareil sélectionné"</string>
<string name="media_output_dialog_multiple_devices" msgid="1093771040315422350">"<xliff:g id="COUNT">%1$d</xliff:g> appareil sélectionné"</string>
- <string name="media_output_dialog_disconnected" msgid="1834473104836986046">"<xliff:g id="DEVICE_NAME">%1$s</xliff:g> (déconnecté)"</string>
+ <string name="media_output_dialog_disconnected" msgid="7090512852817111185">"(déconnecté)"</string>
<string name="media_output_dialog_connect_failed" msgid="3225190634236259010">"Impossible de se connecter. Réessayez."</string>
<string name="media_output_dialog_pairing_new" msgid="9099497976087485862">"Associer un autre appareil"</string>
<string name="build_number_clip_data_label" msgid="3623176728412560914">"Numéro de version"</string>
diff --git a/packages/SystemUI/res/values-fr/strings.xml b/packages/SystemUI/res/values-fr/strings.xml
index 91c05c6..d16796d 100644
--- a/packages/SystemUI/res/values-fr/strings.xml
+++ b/packages/SystemUI/res/values-fr/strings.xml
@@ -1111,7 +1111,7 @@
<string name="media_output_dialog_group" msgid="5571251347877452212">"Groupe"</string>
<string name="media_output_dialog_single_device" msgid="3102758980643351058">"1 appareil sélectionné"</string>
<string name="media_output_dialog_multiple_devices" msgid="1093771040315422350">"<xliff:g id="COUNT">%1$d</xliff:g> appareils sélectionnés"</string>
- <string name="media_output_dialog_disconnected" msgid="1834473104836986046">"<xliff:g id="DEVICE_NAME">%1$s</xliff:g> (déconnecté)"</string>
+ <string name="media_output_dialog_disconnected" msgid="7090512852817111185">"(déconnecté)"</string>
<string name="media_output_dialog_connect_failed" msgid="3225190634236259010">"Impossible de se connecter. Réessayez."</string>
<string name="media_output_dialog_pairing_new" msgid="9099497976087485862">"Associer un nouvel appareil"</string>
<string name="build_number_clip_data_label" msgid="3623176728412560914">"Numéro de build"</string>
diff --git a/packages/SystemUI/res/values-fr/tiles_states_strings.xml b/packages/SystemUI/res/values-fr/tiles_states_strings.xml
index e66169d..5898e0c 100644
--- a/packages/SystemUI/res/values-fr/tiles_states_strings.xml
+++ b/packages/SystemUI/res/values-fr/tiles_states_strings.xml
@@ -64,7 +64,7 @@
<string-array name="tile_states_rotation">
<item msgid="4578491772376121579">"Indisponible"</item>
<item msgid="5776427577477729185">"Désactivé"</item>
- <item msgid="7105052717007227415">"Activé"</item>
+ <item msgid="7105052717007227415">"Activée"</item>
</string-array>
<string-array name="tile_states_bt">
<item msgid="5330252067413512277">"Indisponible"</item>
diff --git a/packages/SystemUI/res/values-gl/strings.xml b/packages/SystemUI/res/values-gl/strings.xml
index d4fd046..55a431e 100644
--- a/packages/SystemUI/res/values-gl/strings.xml
+++ b/packages/SystemUI/res/values-gl/strings.xml
@@ -1111,7 +1111,7 @@
<string name="media_output_dialog_group" msgid="5571251347877452212">"Grupo"</string>
<string name="media_output_dialog_single_device" msgid="3102758980643351058">"Seleccionouse 1 dispositivo"</string>
<string name="media_output_dialog_multiple_devices" msgid="1093771040315422350">"Seleccionáronse <xliff:g id="COUNT">%1$d</xliff:g> dispositivos"</string>
- <string name="media_output_dialog_disconnected" msgid="1834473104836986046">"<xliff:g id="DEVICE_NAME">%1$s</xliff:g> (dispositivo desconectado)"</string>
+ <string name="media_output_dialog_disconnected" msgid="7090512852817111185">"(desconectado)"</string>
<string name="media_output_dialog_connect_failed" msgid="3225190634236259010">"Non se puido establecer a conexión. Téntao de novo."</string>
<string name="media_output_dialog_pairing_new" msgid="9099497976087485862">"Vincular dispositivo novo"</string>
<string name="build_number_clip_data_label" msgid="3623176728412560914">"Número de compilación"</string>
diff --git a/packages/SystemUI/res/values-gu/strings.xml b/packages/SystemUI/res/values-gu/strings.xml
index 8733604..b310977 100644
--- a/packages/SystemUI/res/values-gu/strings.xml
+++ b/packages/SystemUI/res/values-gu/strings.xml
@@ -1111,7 +1111,7 @@
<string name="media_output_dialog_group" msgid="5571251347877452212">"ગ્રૂપ"</string>
<string name="media_output_dialog_single_device" msgid="3102758980643351058">"1 ડિવાઇસ પસંદ કર્યું"</string>
<string name="media_output_dialog_multiple_devices" msgid="1093771040315422350">"<xliff:g id="COUNT">%1$d</xliff:g> ડિવાઇસ પસંદ કર્યા"</string>
- <string name="media_output_dialog_disconnected" msgid="1834473104836986046">"<xliff:g id="DEVICE_NAME">%1$s</xliff:g> (ડિસ્કનેક્ટ થયેલું)"</string>
+ <string name="media_output_dialog_disconnected" msgid="7090512852817111185">"(ડિસ્કનેક્ટ કરેલું)"</string>
<string name="media_output_dialog_connect_failed" msgid="3225190634236259010">"કનેક્ટ કરી શકાયું નહીં. ફરી પ્રયાસ કરો."</string>
<string name="media_output_dialog_pairing_new" msgid="9099497976087485862">"નવા ડિવાઇસ સાથે જોડાણ કરો"</string>
<string name="build_number_clip_data_label" msgid="3623176728412560914">"બિલ્ડ નંબર"</string>
diff --git a/packages/SystemUI/res/values-hi/strings.xml b/packages/SystemUI/res/values-hi/strings.xml
index ff3bd7f..ea75b10 100644
--- a/packages/SystemUI/res/values-hi/strings.xml
+++ b/packages/SystemUI/res/values-hi/strings.xml
@@ -1111,7 +1111,7 @@
<string name="media_output_dialog_group" msgid="5571251347877452212">"ग्रुप"</string>
<string name="media_output_dialog_single_device" msgid="3102758980643351058">"एक डिवाइस चुना गया"</string>
<string name="media_output_dialog_multiple_devices" msgid="1093771040315422350">"<xliff:g id="COUNT">%1$d</xliff:g> डिवाइस चुने गए"</string>
- <string name="media_output_dialog_disconnected" msgid="1834473104836986046">"<xliff:g id="DEVICE_NAME">%1$s</xliff:g> (डिसकनेक्ट किया गया)"</string>
+ <string name="media_output_dialog_disconnected" msgid="7090512852817111185">"(डिसकनेक्ट हो गया)"</string>
<string name="media_output_dialog_connect_failed" msgid="3225190634236259010">"कनेक्ट नहीं किया जा सका. फिर से कोशिश करें."</string>
<string name="media_output_dialog_pairing_new" msgid="9099497976087485862">"नया डिवाइस जोड़ें"</string>
<string name="build_number_clip_data_label" msgid="3623176728412560914">"बिल्ड नंबर"</string>
diff --git a/packages/SystemUI/res/values-hr/strings.xml b/packages/SystemUI/res/values-hr/strings.xml
index 1acb156..8082bd7 100644
--- a/packages/SystemUI/res/values-hr/strings.xml
+++ b/packages/SystemUI/res/values-hr/strings.xml
@@ -346,7 +346,7 @@
<string name="quick_settings_bluetooth_secondary_label_hearing_aids" msgid="3003338571871392293">"Slušni aparati"</string>
<string name="quick_settings_bluetooth_secondary_label_transient" msgid="3882884317600669650">"Uključivanje…"</string>
<string name="quick_settings_brightness_label" msgid="680259653088849563">"Svjetlina"</string>
- <string name="quick_settings_rotation_unlocked_label" msgid="2359922767950346112">"Automatsko zakretanje"</string>
+ <string name="quick_settings_rotation_unlocked_label" msgid="2359922767950346112">"Autom. zakretanje"</string>
<string name="accessibility_quick_settings_rotation" msgid="4800050198392260738">"Automatsko zakretanje zaslona"</string>
<string name="accessibility_quick_settings_rotation_value" msgid="2916484894750819251">"Način: <xliff:g id="ID_1">%s</xliff:g>"</string>
<string name="quick_settings_rotation_locked_label" msgid="4420863550666310319">"Izmjenjivanje je zaključano"</string>
@@ -1117,7 +1117,7 @@
<string name="media_output_dialog_group" msgid="5571251347877452212">"Grupa"</string>
<string name="media_output_dialog_single_device" msgid="3102758980643351058">"Odabran je jedan uređaj"</string>
<string name="media_output_dialog_multiple_devices" msgid="1093771040315422350">"Odabrano uređaja: <xliff:g id="COUNT">%1$d</xliff:g>"</string>
- <string name="media_output_dialog_disconnected" msgid="1834473104836986046">"<xliff:g id="DEVICE_NAME">%1$s</xliff:g> (nije povezano)"</string>
+ <string name="media_output_dialog_disconnected" msgid="7090512852817111185">"(nije povezano)"</string>
<string name="media_output_dialog_connect_failed" msgid="3225190634236259010">"Povezivanje nije bilo moguće. Pokušajte ponovo."</string>
<string name="media_output_dialog_pairing_new" msgid="9099497976087485862">"Uparite novi uređaj"</string>
<string name="build_number_clip_data_label" msgid="3623176728412560914">"Broj međuverzije"</string>
diff --git a/packages/SystemUI/res/values-hu/strings.xml b/packages/SystemUI/res/values-hu/strings.xml
index 9986abe..0d3cfb8 100644
--- a/packages/SystemUI/res/values-hu/strings.xml
+++ b/packages/SystemUI/res/values-hu/strings.xml
@@ -1111,7 +1111,7 @@
<string name="media_output_dialog_group" msgid="5571251347877452212">"Csoport"</string>
<string name="media_output_dialog_single_device" msgid="3102758980643351058">"1 eszköz kiválasztva"</string>
<string name="media_output_dialog_multiple_devices" msgid="1093771040315422350">"<xliff:g id="COUNT">%1$d</xliff:g> eszköz kiválasztva"</string>
- <string name="media_output_dialog_disconnected" msgid="1834473104836986046">"<xliff:g id="DEVICE_NAME">%1$s</xliff:g> (leválasztva)"</string>
+ <string name="media_output_dialog_disconnected" msgid="7090512852817111185">"(leválasztva)"</string>
<string name="media_output_dialog_connect_failed" msgid="3225190634236259010">"Sikertelen csatlakozás. Próbálja újra."</string>
<string name="media_output_dialog_pairing_new" msgid="9099497976087485862">"Új eszköz párosítása"</string>
<string name="build_number_clip_data_label" msgid="3623176728412560914">"Buildszám"</string>
diff --git a/packages/SystemUI/res/values-hy/strings.xml b/packages/SystemUI/res/values-hy/strings.xml
index 25931bf..3272466 100644
--- a/packages/SystemUI/res/values-hy/strings.xml
+++ b/packages/SystemUI/res/values-hy/strings.xml
@@ -1111,7 +1111,7 @@
<string name="media_output_dialog_group" msgid="5571251347877452212">"Խումբ"</string>
<string name="media_output_dialog_single_device" msgid="3102758980643351058">"Ընտրված է 1 սարք"</string>
<string name="media_output_dialog_multiple_devices" msgid="1093771040315422350">"Ընտրված է <xliff:g id="COUNT">%1$d</xliff:g> սարք"</string>
- <string name="media_output_dialog_disconnected" msgid="1834473104836986046">"<xliff:g id="DEVICE_NAME">%1$s</xliff:g> (անջատված է)"</string>
+ <string name="media_output_dialog_disconnected" msgid="7090512852817111185">"(անջատված է)"</string>
<string name="media_output_dialog_connect_failed" msgid="3225190634236259010">"Չհաջողվեց միանալ։ Նորից փորձեք։"</string>
<string name="media_output_dialog_pairing_new" msgid="9099497976087485862">"Նոր սարքի զուգակցում"</string>
<string name="build_number_clip_data_label" msgid="3623176728412560914">"Կառուցման համարը"</string>
diff --git a/packages/SystemUI/res/values-in/strings.xml b/packages/SystemUI/res/values-in/strings.xml
index b197f62..15e0bd2 100644
--- a/packages/SystemUI/res/values-in/strings.xml
+++ b/packages/SystemUI/res/values-in/strings.xml
@@ -1111,7 +1111,7 @@
<string name="media_output_dialog_group" msgid="5571251347877452212">"Grup"</string>
<string name="media_output_dialog_single_device" msgid="3102758980643351058">"1 perangkat dipilih"</string>
<string name="media_output_dialog_multiple_devices" msgid="1093771040315422350">"<xliff:g id="COUNT">%1$d</xliff:g> perangkat dipilih"</string>
- <string name="media_output_dialog_disconnected" msgid="1834473104836986046">"<xliff:g id="DEVICE_NAME">%1$s</xliff:g> (terputus)"</string>
+ <string name="media_output_dialog_disconnected" msgid="7090512852817111185">"(terputus)"</string>
<string name="media_output_dialog_connect_failed" msgid="3225190634236259010">"Tidak dapat terhubung. Coba lagi."</string>
<string name="media_output_dialog_pairing_new" msgid="9099497976087485862">"Sambungkan perangkat baru"</string>
<string name="build_number_clip_data_label" msgid="3623176728412560914">"Nomor build"</string>
diff --git a/packages/SystemUI/res/values-is/strings.xml b/packages/SystemUI/res/values-is/strings.xml
index 8ae27dc..09c23fd 100644
--- a/packages/SystemUI/res/values-is/strings.xml
+++ b/packages/SystemUI/res/values-is/strings.xml
@@ -1111,7 +1111,7 @@
<string name="media_output_dialog_group" msgid="5571251347877452212">"Hópur"</string>
<string name="media_output_dialog_single_device" msgid="3102758980643351058">"1 tæki valið"</string>
<string name="media_output_dialog_multiple_devices" msgid="1093771040315422350">"<xliff:g id="COUNT">%1$d</xliff:g> tæki valin"</string>
- <string name="media_output_dialog_disconnected" msgid="1834473104836986046">"<xliff:g id="DEVICE_NAME">%1$s</xliff:g> (aftengt)"</string>
+ <string name="media_output_dialog_disconnected" msgid="7090512852817111185">"(aftengt)"</string>
<string name="media_output_dialog_connect_failed" msgid="3225190634236259010">"Tenging mistókst. Reyndu aftur."</string>
<string name="media_output_dialog_pairing_new" msgid="9099497976087485862">"Para nýtt tæki"</string>
<string name="build_number_clip_data_label" msgid="3623176728412560914">"Útgáfunúmer smíðar"</string>
diff --git a/packages/SystemUI/res/values-it/strings.xml b/packages/SystemUI/res/values-it/strings.xml
index 96fc861..fbd5c63 100644
--- a/packages/SystemUI/res/values-it/strings.xml
+++ b/packages/SystemUI/res/values-it/strings.xml
@@ -516,7 +516,7 @@
<string name="manage_notifications_text" msgid="6885645344647733116">"Gestisci"</string>
<string name="manage_notifications_history_text" msgid="57055985396576230">"Cronologia"</string>
<string name="notification_section_header_incoming" msgid="850925217908095197">"Nuove"</string>
- <string name="notification_section_header_gentle" msgid="6804099527336337197">"Silenziose"</string>
+ <string name="notification_section_header_gentle" msgid="6804099527336337197">"Notifiche silenziose"</string>
<string name="notification_section_header_alerting" msgid="5581175033680477651">"Notifiche"</string>
<string name="notification_section_header_conversations" msgid="821834744538345661">"Conversazioni"</string>
<string name="accessibility_notification_section_header_gentle_clear_all" msgid="6490207897764933919">"Cancella tutte le notifiche silenziose"</string>
@@ -1046,7 +1046,7 @@
<string name="accessibility_floating_button_action_move_to_edge_and_hide_to_half" msgid="662401168245782658">"Sposta fino a bordo e nascondi"</string>
<string name="accessibility_floating_button_action_move_out_edge_and_show" msgid="8354760891651663326">"Sposta fuori da bordo e mostra"</string>
<string name="accessibility_floating_button_action_double_tap_to_toggle" msgid="7976492639670692037">"attiva/disattiva"</string>
- <string name="quick_controls_title" msgid="6839108006171302273">"Controllo dei dispositivi"</string>
+ <string name="quick_controls_title" msgid="6839108006171302273">"Controllo dispositivi"</string>
<string name="controls_providers_title" msgid="6879775889857085056">"Scegli un\'app per aggiungere controlli"</string>
<plurals name="controls_number_of_favorites" formatted="false" msgid="1057347832073807380">
<item quantity="other"><xliff:g id="NUMBER_1">%s</xliff:g> controlli aggiunti.</item>
@@ -1111,7 +1111,7 @@
<string name="media_output_dialog_group" msgid="5571251347877452212">"Gruppo"</string>
<string name="media_output_dialog_single_device" msgid="3102758980643351058">"1 dispositivo selezionato"</string>
<string name="media_output_dialog_multiple_devices" msgid="1093771040315422350">"<xliff:g id="COUNT">%1$d</xliff:g> dispositivi selezionati"</string>
- <string name="media_output_dialog_disconnected" msgid="1834473104836986046">"<xliff:g id="DEVICE_NAME">%1$s</xliff:g> (disconnesso)"</string>
+ <string name="media_output_dialog_disconnected" msgid="7090512852817111185">"(disconnesso)"</string>
<string name="media_output_dialog_connect_failed" msgid="3225190634236259010">"Impossibile connettersi. Riprova."</string>
<string name="media_output_dialog_pairing_new" msgid="9099497976087485862">"Accoppia nuovo dispositivo"</string>
<string name="build_number_clip_data_label" msgid="3623176728412560914">"Numero build"</string>
@@ -1155,7 +1155,7 @@
<string name="person_available" msgid="2318599327472755472">"Disponibile"</string>
<string name="battery_state_unknown_notification_title" msgid="8464703640483773454">"Problema durante la lettura dell\'indicatore di livello della batteria"</string>
<string name="battery_state_unknown_notification_text" msgid="13720937839460899">"Tocca per ulteriori informazioni"</string>
- <string name="qs_alarm_tile_no_alarm" msgid="4826472008616807923">"Nessuna sveglia"</string>
+ <string name="qs_alarm_tile_no_alarm" msgid="4826472008616807923">"Nessuna"</string>
<string name="accessibility_fingerprint_label" msgid="5255731221854153660">"Sensore di impronte digitali"</string>
<string name="accessibility_udfps_disabled_button" msgid="4284034245130239384">"Sensore di impronte digitali disattivato"</string>
<string name="accessibility_authenticate_hint" msgid="798914151813205721">"effettuare l\'autenticazione"</string>
diff --git a/packages/SystemUI/res/values-it/tiles_states_strings.xml b/packages/SystemUI/res/values-it/tiles_states_strings.xml
index d142069..f18536c 100644
--- a/packages/SystemUI/res/values-it/tiles_states_strings.xml
+++ b/packages/SystemUI/res/values-it/tiles_states_strings.xml
@@ -32,127 +32,127 @@
<!-- no translation found for tile_states_default:1 (7086813178962737808) -->
<!-- no translation found for tile_states_default:2 (9192445505551219506) -->
<string-array name="tile_states_internet">
- <item msgid="5499482407653291407">"Elemento non disponibile"</item>
+ <item msgid="5499482407653291407">"Non disponibile"</item>
<item msgid="3048856902433862868">"Off"</item>
<item msgid="6877982264300789870">"On"</item>
</string-array>
<string-array name="tile_states_wifi">
- <item msgid="8054147400538405410">"Elemento non disponibile"</item>
+ <item msgid="8054147400538405410">"Non disponibile"</item>
<item msgid="4293012229142257455">"Off"</item>
<item msgid="6221288736127914861">"On"</item>
</string-array>
<string-array name="tile_states_cell">
- <item msgid="1235899788959500719">"Elemento non disponibile"</item>
+ <item msgid="1235899788959500719">"Non disponibile"</item>
<item msgid="2074416252859094119">"Off"</item>
<item msgid="287997784730044767">"On"</item>
</string-array>
<string-array name="tile_states_battery">
- <item msgid="6311253873330062961">"Elemento non disponibile"</item>
+ <item msgid="6311253873330062961">"Non disponibile"</item>
<item msgid="7838121007534579872">"Off"</item>
<item msgid="1578872232501319194">"On"</item>
</string-array>
<string-array name="tile_states_dnd">
- <item msgid="467587075903158357">"Elemento non disponibile"</item>
+ <item msgid="467587075903158357">"Non disponibile"</item>
<item msgid="5376619709702103243">"Off"</item>
<item msgid="4875147066469902392">"On"</item>
</string-array>
<string-array name="tile_states_flashlight">
- <item msgid="3465257127433353857">"Elemento non disponibile"</item>
+ <item msgid="3465257127433353857">"Non disponibile"</item>
<item msgid="5044688398303285224">"Off"</item>
<item msgid="8527389108867454098">"On"</item>
</string-array>
<string-array name="tile_states_rotation">
- <item msgid="4578491772376121579">"Elemento non disponibile"</item>
+ <item msgid="4578491772376121579">"Non disponibile"</item>
<item msgid="5776427577477729185">"Off"</item>
<item msgid="7105052717007227415">"On"</item>
</string-array>
<string-array name="tile_states_bt">
- <item msgid="5330252067413512277">"Elemento non disponibile"</item>
+ <item msgid="5330252067413512277">"Non disponibile"</item>
<item msgid="5315121904534729843">"Off"</item>
<item msgid="503679232285959074">"On"</item>
</string-array>
<string-array name="tile_states_airplane">
- <item msgid="1985366811411407764">"Elemento non disponibile"</item>
+ <item msgid="1985366811411407764">"Non disponibile"</item>
<item msgid="4801037224991420996">"Off"</item>
<item msgid="1982293347302546665">"On"</item>
</string-array>
<string-array name="tile_states_location">
- <item msgid="3316542218706374405">"Elemento non disponibile"</item>
+ <item msgid="3316542218706374405">"Non disponibile"</item>
<item msgid="4813655083852587017">"Off"</item>
<item msgid="6744077414775180687">"On"</item>
</string-array>
<string-array name="tile_states_hotspot">
- <item msgid="3145597331197351214">"Elemento non disponibile"</item>
+ <item msgid="3145597331197351214">"Non disponibile"</item>
<item msgid="5715725170633593906">"Off"</item>
<item msgid="2075645297847971154">"On"</item>
</string-array>
<string-array name="tile_states_inversion">
- <item msgid="3638187931191394628">"Elemento non disponibile"</item>
+ <item msgid="3638187931191394628">"Non disponibile"</item>
<item msgid="9103697205127645916">"Off"</item>
<item msgid="8067744885820618230">"On"</item>
</string-array>
<string-array name="tile_states_saver">
- <item msgid="39714521631367660">"Elemento non disponibile"</item>
+ <item msgid="39714521631367660">"Non disponibile"</item>
<item msgid="6983679487661600728">"Off"</item>
<item msgid="7520663805910678476">"On"</item>
</string-array>
<string-array name="tile_states_dark">
- <item msgid="2762596907080603047">"Elemento non disponibile"</item>
+ <item msgid="2762596907080603047">"Non disponibile"</item>
<item msgid="400477985171353">"Off"</item>
<item msgid="630890598801118771">"On"</item>
</string-array>
<string-array name="tile_states_work">
- <item msgid="389523503690414094">"Elemento non disponibile"</item>
+ <item msgid="389523503690414094">"Non disponibile"</item>
<item msgid="8045580926543311193">"Off"</item>
<item msgid="4913460972266982499">"On"</item>
</string-array>
<string-array name="tile_states_cast">
- <item msgid="6032026038702435350">"Elemento non disponibile"</item>
+ <item msgid="6032026038702435350">"Non disponibile"</item>
<item msgid="1488620600954313499">"Off"</item>
<item msgid="588467578853244035">"On"</item>
</string-array>
<string-array name="tile_states_night">
- <item msgid="7857498964264855466">"Elemento non disponibile"</item>
+ <item msgid="7857498964264855466">"Non disponibile"</item>
<item msgid="2744885441164350155">"Off"</item>
<item msgid="151121227514952197">"On"</item>
</string-array>
<string-array name="tile_states_screenrecord">
- <item msgid="1085836626613341403">"Elemento non disponibile"</item>
+ <item msgid="1085836626613341403">"Non disponibile"</item>
<item msgid="8259411607272330225">"Off"</item>
<item msgid="578444932039713369">"On"</item>
</string-array>
<string-array name="tile_states_reverse">
- <item msgid="3574611556622963971">"Elemento non disponibile"</item>
+ <item msgid="3574611556622963971">"Non disponibile"</item>
<item msgid="8707481475312432575">"Off"</item>
<item msgid="8031106212477483874">"On"</item>
</string-array>
<string-array name="tile_states_reduce_brightness">
- <item msgid="1839836132729571766">"Elemento non disponibile"</item>
+ <item msgid="1839836132729571766">"Non disponibile"</item>
<item msgid="4572245614982283078">"Off"</item>
<item msgid="6536448410252185664">"On"</item>
</string-array>
<string-array name="tile_states_cameratoggle">
- <item msgid="6680671247180519913">"Elemento non disponibile"</item>
+ <item msgid="6680671247180519913">"Non disponibile"</item>
<item msgid="4765607635752003190">"Off"</item>
<item msgid="1697460731949649844">"On"</item>
</string-array>
<string-array name="tile_states_mictoggle">
- <item msgid="6895831614067195493">"Elemento non disponibile"</item>
+ <item msgid="6895831614067195493">"Non disponibile"</item>
<item msgid="3296179158646568218">"Off"</item>
<item msgid="8998632451221157987">"On"</item>
</string-array>
<string-array name="tile_states_controls">
- <item msgid="8199009425335668294">"Elemento non disponibile"</item>
+ <item msgid="8199009425335668294">"Non disponibile"</item>
<item msgid="4544919905196727508">"Off"</item>
<item msgid="3422023746567004609">"On"</item>
</string-array>
<string-array name="tile_states_wallet">
- <item msgid="4177615438710836341">"Elemento non disponibile"</item>
+ <item msgid="4177615438710836341">"Non disponibile"</item>
<item msgid="7571394439974244289">"Off"</item>
<item msgid="6866424167599381915">"On"</item>
</string-array>
<string-array name="tile_states_alarm">
- <item msgid="4936533380177298776">"Elemento non disponibile"</item>
+ <item msgid="4936533380177298776">"Non disponibile"</item>
<item msgid="2710157085538036590">"Off"</item>
<item msgid="7809470840976856149">"On"</item>
</string-array>
diff --git a/packages/SystemUI/res/values-iw/strings.xml b/packages/SystemUI/res/values-iw/strings.xml
index 2ecf51d..e7dce87 100644
--- a/packages/SystemUI/res/values-iw/strings.xml
+++ b/packages/SystemUI/res/values-iw/strings.xml
@@ -1123,7 +1123,7 @@
<string name="media_output_dialog_group" msgid="5571251347877452212">"קבוצה"</string>
<string name="media_output_dialog_single_device" msgid="3102758980643351058">"נבחר מכשיר אחד"</string>
<string name="media_output_dialog_multiple_devices" msgid="1093771040315422350">"נבחרו <xliff:g id="COUNT">%1$d</xliff:g> מכשירים"</string>
- <string name="media_output_dialog_disconnected" msgid="1834473104836986046">"<xliff:g id="DEVICE_NAME">%1$s</xliff:g> (מנותק)"</string>
+ <string name="media_output_dialog_disconnected" msgid="7090512852817111185">"(מנותק)"</string>
<string name="media_output_dialog_connect_failed" msgid="3225190634236259010">"לא ניתן היה להתחבר. יש לנסות שוב."</string>
<string name="media_output_dialog_pairing_new" msgid="9099497976087485862">"התאמה של מכשיר חדש"</string>
<string name="build_number_clip_data_label" msgid="3623176728412560914">"מספר Build"</string>
@@ -1167,7 +1167,7 @@
<string name="person_available" msgid="2318599327472755472">"אונליין"</string>
<string name="battery_state_unknown_notification_title" msgid="8464703640483773454">"בעיה בקריאת מדדי הסוללה"</string>
<string name="battery_state_unknown_notification_text" msgid="13720937839460899">"יש להקיש כדי להציג מידע נוסף"</string>
- <string name="qs_alarm_tile_no_alarm" msgid="4826472008616807923">"לא הוגדרה התראה"</string>
+ <string name="qs_alarm_tile_no_alarm" msgid="4826472008616807923">"לא הוגדרה"</string>
<string name="accessibility_fingerprint_label" msgid="5255731221854153660">"חיישן טביעות אצבע"</string>
<string name="accessibility_udfps_disabled_button" msgid="4284034245130239384">"חיישן טביעות האצבע מושבת"</string>
<string name="accessibility_authenticate_hint" msgid="798914151813205721">"אימות"</string>
diff --git a/packages/SystemUI/res/values-ja/strings.xml b/packages/SystemUI/res/values-ja/strings.xml
index 74cc6be..273cd05 100644
--- a/packages/SystemUI/res/values-ja/strings.xml
+++ b/packages/SystemUI/res/values-ja/strings.xml
@@ -1111,7 +1111,7 @@
<string name="media_output_dialog_group" msgid="5571251347877452212">"グループ"</string>
<string name="media_output_dialog_single_device" msgid="3102758980643351058">"選択したデバイス: 1 台"</string>
<string name="media_output_dialog_multiple_devices" msgid="1093771040315422350">"選択したデバイス: <xliff:g id="COUNT">%1$d</xliff:g> 台"</string>
- <string name="media_output_dialog_disconnected" msgid="1834473104836986046">"<xliff:g id="DEVICE_NAME">%1$s</xliff:g>(未接続)"</string>
+ <string name="media_output_dialog_disconnected" msgid="7090512852817111185">"(接続解除済み)"</string>
<string name="media_output_dialog_connect_failed" msgid="3225190634236259010">"接続できませんでした。もう一度お試しください。"</string>
<string name="media_output_dialog_pairing_new" msgid="9099497976087485862">"新しいデバイスとのペア設定"</string>
<string name="build_number_clip_data_label" msgid="3623176728412560914">"ビルド番号"</string>
diff --git a/packages/SystemUI/res/values-ka/strings.xml b/packages/SystemUI/res/values-ka/strings.xml
index 6596f6a..2450a24 100644
--- a/packages/SystemUI/res/values-ka/strings.xml
+++ b/packages/SystemUI/res/values-ka/strings.xml
@@ -1111,7 +1111,7 @@
<string name="media_output_dialog_group" msgid="5571251347877452212">"ჯგუფი"</string>
<string name="media_output_dialog_single_device" msgid="3102758980643351058">"არჩეულია 1 მოწყობილობა"</string>
<string name="media_output_dialog_multiple_devices" msgid="1093771040315422350">"არჩეულია <xliff:g id="COUNT">%1$d</xliff:g> მოწყობილობა"</string>
- <string name="media_output_dialog_disconnected" msgid="1834473104836986046">"<xliff:g id="DEVICE_NAME">%1$s</xliff:g> (კავშირი გაწყვეტილია)"</string>
+ <string name="media_output_dialog_disconnected" msgid="7090512852817111185">"(კავშირი გაწყვეტილია)"</string>
<string name="media_output_dialog_connect_failed" msgid="3225190634236259010">"დაკავშირება ვერ მოხერხდა. ცადეთ ხელახლა."</string>
<string name="media_output_dialog_pairing_new" msgid="9099497976087485862">"ახალი მოწყობილობის დაწყვილება"</string>
<string name="build_number_clip_data_label" msgid="3623176728412560914">"ანაწყობის ნომერი"</string>
diff --git a/packages/SystemUI/res/values-kk/strings.xml b/packages/SystemUI/res/values-kk/strings.xml
index b347709..7365973 100644
--- a/packages/SystemUI/res/values-kk/strings.xml
+++ b/packages/SystemUI/res/values-kk/strings.xml
@@ -1111,7 +1111,7 @@
<string name="media_output_dialog_group" msgid="5571251347877452212">"Топ"</string>
<string name="media_output_dialog_single_device" msgid="3102758980643351058">"1 құрылғы таңдалды."</string>
<string name="media_output_dialog_multiple_devices" msgid="1093771040315422350">"<xliff:g id="COUNT">%1$d</xliff:g> құрылғы таңдалды."</string>
- <string name="media_output_dialog_disconnected" msgid="1834473104836986046">"<xliff:g id="DEVICE_NAME">%1$s</xliff:g> (ажыратылған)"</string>
+ <string name="media_output_dialog_disconnected" msgid="7090512852817111185">"(ажыратулы)"</string>
<string name="media_output_dialog_connect_failed" msgid="3225190634236259010">"Қосылмады. Қайта қосылып көріңіз."</string>
<string name="media_output_dialog_pairing_new" msgid="9099497976087485862">"Жаңа құрылғымен жұптау"</string>
<string name="build_number_clip_data_label" msgid="3623176728412560914">"Құрама нөмірі"</string>
diff --git a/packages/SystemUI/res/values-km/strings.xml b/packages/SystemUI/res/values-km/strings.xml
index db0018d..f4607ff 100644
--- a/packages/SystemUI/res/values-km/strings.xml
+++ b/packages/SystemUI/res/values-km/strings.xml
@@ -1111,7 +1111,7 @@
<string name="media_output_dialog_group" msgid="5571251347877452212">"ក្រុម"</string>
<string name="media_output_dialog_single_device" msgid="3102758980643351058">"បានជ្រើសរើសឧបករណ៍ 1"</string>
<string name="media_output_dialog_multiple_devices" msgid="1093771040315422350">"បានជ្រើសរើសឧបករណ៍ <xliff:g id="COUNT">%1$d</xliff:g>"</string>
- <string name="media_output_dialog_disconnected" msgid="1834473104836986046">"<xliff:g id="DEVICE_NAME">%1$s</xliff:g> (បានផ្ដាច់)"</string>
+ <string name="media_output_dialog_disconnected" msgid="7090512852817111185">"(បានដាច់)"</string>
<string name="media_output_dialog_connect_failed" msgid="3225190634236259010">"មិនអាចភ្ជាប់បានទេ។ សូមព្យាយាមម្ដងទៀត។"</string>
<string name="media_output_dialog_pairing_new" msgid="9099497976087485862">"ផ្គូផ្គងឧបករណ៍ថ្មី"</string>
<string name="build_number_clip_data_label" msgid="3623176728412560914">"លេខកំណែបង្កើត"</string>
diff --git a/packages/SystemUI/res/values-kn/strings.xml b/packages/SystemUI/res/values-kn/strings.xml
index 60bb5ec..6604d2e 100644
--- a/packages/SystemUI/res/values-kn/strings.xml
+++ b/packages/SystemUI/res/values-kn/strings.xml
@@ -1111,7 +1111,7 @@
<string name="media_output_dialog_group" msgid="5571251347877452212">"ಗುಂಪು"</string>
<string name="media_output_dialog_single_device" msgid="3102758980643351058">"1 ಸಾಧನವನ್ನು ಆಯ್ಕೆ ಮಾಡಲಾಗಿದೆ"</string>
<string name="media_output_dialog_multiple_devices" msgid="1093771040315422350">"<xliff:g id="COUNT">%1$d</xliff:g> ಸಾಧನಗಳನ್ನು ಆಯ್ಕೆ ಮಾಡಲಾಗಿದೆ"</string>
- <string name="media_output_dialog_disconnected" msgid="1834473104836986046">"<xliff:g id="DEVICE_NAME">%1$s</xliff:g> (ಸಂಪರ್ಕ ಕಡಿತಗೊಳಿಸಲಾಗಿದೆ)"</string>
+ <string name="media_output_dialog_disconnected" msgid="7090512852817111185">"(ಡಿಸ್ಕನೆಕ್ಟ್ ಆಗಿದೆ)"</string>
<string name="media_output_dialog_connect_failed" msgid="3225190634236259010">"ಸಂಪರ್ಕಿಸಲು ಸಾಧ್ಯವಾಗುತ್ತಿಲ್ಲ. ಪುನಃ ಪ್ರಯತ್ನಿಸಿ."</string>
<string name="media_output_dialog_pairing_new" msgid="9099497976087485862">"ಹೊಸ ಸಾಧನವನ್ನು ಜೋಡಿಸಿ"</string>
<string name="build_number_clip_data_label" msgid="3623176728412560914">"ಬಿಲ್ಡ್ ಸಂಖ್ಯೆ"</string>
diff --git a/packages/SystemUI/res/values-ko/strings.xml b/packages/SystemUI/res/values-ko/strings.xml
index 01d3158..5d0d809 100644
--- a/packages/SystemUI/res/values-ko/strings.xml
+++ b/packages/SystemUI/res/values-ko/strings.xml
@@ -1111,7 +1111,7 @@
<string name="media_output_dialog_group" msgid="5571251347877452212">"그룹"</string>
<string name="media_output_dialog_single_device" msgid="3102758980643351058">"기기 1대 선택됨"</string>
<string name="media_output_dialog_multiple_devices" msgid="1093771040315422350">"기기 <xliff:g id="COUNT">%1$d</xliff:g>대 선택됨"</string>
- <string name="media_output_dialog_disconnected" msgid="1834473104836986046">"<xliff:g id="DEVICE_NAME">%1$s</xliff:g>(연결 끊김)"</string>
+ <string name="media_output_dialog_disconnected" msgid="7090512852817111185">"(연결 끊김)"</string>
<string name="media_output_dialog_connect_failed" msgid="3225190634236259010">"연결할 수 없습니다. 다시 시도하세요."</string>
<string name="media_output_dialog_pairing_new" msgid="9099497976087485862">"새 기기와 페어링"</string>
<string name="build_number_clip_data_label" msgid="3623176728412560914">"빌드 번호"</string>
diff --git a/packages/SystemUI/res/values-ky/strings.xml b/packages/SystemUI/res/values-ky/strings.xml
index e5383c7..c2b6e4b 100644
--- a/packages/SystemUI/res/values-ky/strings.xml
+++ b/packages/SystemUI/res/values-ky/strings.xml
@@ -1111,7 +1111,7 @@
<string name="media_output_dialog_group" msgid="5571251347877452212">"Топ"</string>
<string name="media_output_dialog_single_device" msgid="3102758980643351058">"1 түзмөк тандалды"</string>
<string name="media_output_dialog_multiple_devices" msgid="1093771040315422350">"<xliff:g id="COUNT">%1$d</xliff:g> түзмөк тандалды"</string>
- <string name="media_output_dialog_disconnected" msgid="1834473104836986046">"<xliff:g id="DEVICE_NAME">%1$s</xliff:g> (ажыратылды)"</string>
+ <string name="media_output_dialog_disconnected" msgid="7090512852817111185">"(ажыратылды)"</string>
<string name="media_output_dialog_connect_failed" msgid="3225190634236259010">"Байланышпай койду. Кайталоо."</string>
<string name="media_output_dialog_pairing_new" msgid="9099497976087485862">"Жаңы түзмөктү жупташтыруу"</string>
<string name="build_number_clip_data_label" msgid="3623176728412560914">"Курама номери"</string>
diff --git a/packages/SystemUI/res/values-land/styles.xml b/packages/SystemUI/res/values-land/styles.xml
index 82cba58..f3d83645 100644
--- a/packages/SystemUI/res/values-land/styles.xml
+++ b/packages/SystemUI/res/values-land/styles.xml
@@ -25,12 +25,6 @@
<item name="android:layout_gravity">center_horizontal</item>
</style>
- <style name="DockedDividerHandle">
- <item name="android:layout_gravity">center_vertical</item>
- <item name="android:layout_width">48dp</item>
- <item name="android:layout_height">96dp</item>
- </style>
-
<style name="DockedDividerMinimizedShadow">
<item name="android:layout_width">8dp</item>
<item name="android:layout_height">match_parent</item>
diff --git a/packages/SystemUI/res/values-lo/strings.xml b/packages/SystemUI/res/values-lo/strings.xml
index c75dbca..ccc3f34 100644
--- a/packages/SystemUI/res/values-lo/strings.xml
+++ b/packages/SystemUI/res/values-lo/strings.xml
@@ -1111,7 +1111,7 @@
<string name="media_output_dialog_group" msgid="5571251347877452212">"ກຸ່ມ"</string>
<string name="media_output_dialog_single_device" msgid="3102758980643351058">"ເລືອກ 1 ອຸປະກອນແລ້ວ"</string>
<string name="media_output_dialog_multiple_devices" msgid="1093771040315422350">"ເລືອກ <xliff:g id="COUNT">%1$d</xliff:g> ອຸປະກອນແລ້ວ"</string>
- <string name="media_output_dialog_disconnected" msgid="1834473104836986046">"<xliff:g id="DEVICE_NAME">%1$s</xliff:g> (ຕັດການເຊື່ອມຕໍ່ແລ້ວ)"</string>
+ <string name="media_output_dialog_disconnected" msgid="7090512852817111185">"(ຕັດການເຊື່ອມຕໍ່ແລ້ວ)"</string>
<string name="media_output_dialog_connect_failed" msgid="3225190634236259010">"ບໍ່ສາມາດເຊື່ອມຕໍ່ໄດ້. ລອງໃໝ່."</string>
<string name="media_output_dialog_pairing_new" msgid="9099497976087485862">"ຈັບຄູ່ອຸປະກອນໃໝ່"</string>
<string name="build_number_clip_data_label" msgid="3623176728412560914">"ໝາຍເລກສ້າງ"</string>
diff --git a/packages/SystemUI/res/values-lt/strings.xml b/packages/SystemUI/res/values-lt/strings.xml
index 2d5a4c4..16adb99 100644
--- a/packages/SystemUI/res/values-lt/strings.xml
+++ b/packages/SystemUI/res/values-lt/strings.xml
@@ -1123,7 +1123,7 @@
<string name="media_output_dialog_group" msgid="5571251347877452212">"Grupė"</string>
<string name="media_output_dialog_single_device" msgid="3102758980643351058">"Pasirinktas 1 įrenginys"</string>
<string name="media_output_dialog_multiple_devices" msgid="1093771040315422350">"Pasirinkta įrenginių: <xliff:g id="COUNT">%1$d</xliff:g>"</string>
- <string name="media_output_dialog_disconnected" msgid="1834473104836986046">"„<xliff:g id="DEVICE_NAME">%1$s</xliff:g>“ (atjungta)"</string>
+ <string name="media_output_dialog_disconnected" msgid="7090512852817111185">"(atjungta)"</string>
<string name="media_output_dialog_connect_failed" msgid="3225190634236259010">"Nepavyko prijungti. Bandykite dar kartą."</string>
<string name="media_output_dialog_pairing_new" msgid="9099497976087485862">"Naujo įrenginio susiejimas"</string>
<string name="build_number_clip_data_label" msgid="3623176728412560914">"Versijos numeris"</string>
diff --git a/packages/SystemUI/res/values-lv/strings.xml b/packages/SystemUI/res/values-lv/strings.xml
index c98bd79..65d7ff6 100644
--- a/packages/SystemUI/res/values-lv/strings.xml
+++ b/packages/SystemUI/res/values-lv/strings.xml
@@ -1117,7 +1117,7 @@
<string name="media_output_dialog_group" msgid="5571251347877452212">"Grupa"</string>
<string name="media_output_dialog_single_device" msgid="3102758980643351058">"Atlasīta viena ierīce"</string>
<string name="media_output_dialog_multiple_devices" msgid="1093771040315422350">"Atlasītas vairākas ierīces (kopā <xliff:g id="COUNT">%1$d</xliff:g>)"</string>
- <string name="media_output_dialog_disconnected" msgid="1834473104836986046">"<xliff:g id="DEVICE_NAME">%1$s</xliff:g> (savienojums pārtraukts)"</string>
+ <string name="media_output_dialog_disconnected" msgid="7090512852817111185">"(savienojums pārtraukts)"</string>
<string name="media_output_dialog_connect_failed" msgid="3225190634236259010">"Nevarēja izveidot savienojumu. Mēģiniet vēlreiz."</string>
<string name="media_output_dialog_pairing_new" msgid="9099497976087485862">"Savienošana pārī ar jaunu ierīci"</string>
<string name="build_number_clip_data_label" msgid="3623176728412560914">"Versijas numurs"</string>
diff --git a/packages/SystemUI/res/values-mk/strings.xml b/packages/SystemUI/res/values-mk/strings.xml
index 1f22b69..d9bf595 100644
--- a/packages/SystemUI/res/values-mk/strings.xml
+++ b/packages/SystemUI/res/values-mk/strings.xml
@@ -1111,7 +1111,7 @@
<string name="media_output_dialog_group" msgid="5571251347877452212">"Група"</string>
<string name="media_output_dialog_single_device" msgid="3102758980643351058">"Избран е 1 уред"</string>
<string name="media_output_dialog_multiple_devices" msgid="1093771040315422350">"Избрани се <xliff:g id="COUNT">%1$d</xliff:g> уреди"</string>
- <string name="media_output_dialog_disconnected" msgid="1834473104836986046">"<xliff:g id="DEVICE_NAME">%1$s</xliff:g> (исклучен)"</string>
+ <string name="media_output_dialog_disconnected" msgid="7090512852817111185">"(врската е прекината)"</string>
<string name="media_output_dialog_connect_failed" msgid="3225190634236259010">"Не може да се поврзе. Обидете се повторно."</string>
<string name="media_output_dialog_pairing_new" msgid="9099497976087485862">"Спарете нов уред"</string>
<string name="build_number_clip_data_label" msgid="3623176728412560914">"Број на верзија"</string>
diff --git a/packages/SystemUI/res/values-ml/strings.xml b/packages/SystemUI/res/values-ml/strings.xml
index d448f04..76ea49c 100644
--- a/packages/SystemUI/res/values-ml/strings.xml
+++ b/packages/SystemUI/res/values-ml/strings.xml
@@ -1111,7 +1111,7 @@
<string name="media_output_dialog_group" msgid="5571251347877452212">"ഗ്രൂപ്പ്"</string>
<string name="media_output_dialog_single_device" msgid="3102758980643351058">"ഒരു ഉപകരണം തിരഞ്ഞെടുത്തു"</string>
<string name="media_output_dialog_multiple_devices" msgid="1093771040315422350">"<xliff:g id="COUNT">%1$d</xliff:g> ഉപകരണങ്ങൾ തിരഞ്ഞെടുത്തു"</string>
- <string name="media_output_dialog_disconnected" msgid="1834473104836986046">"<xliff:g id="DEVICE_NAME">%1$s</xliff:g> (വിച്ഛേദിച്ചു)"</string>
+ <string name="media_output_dialog_disconnected" msgid="7090512852817111185">"(വിച്ഛേദിച്ചു)"</string>
<string name="media_output_dialog_connect_failed" msgid="3225190634236259010">"കണക്റ്റ് ചെയ്യാനായില്ല. വീണ്ടും ശ്രമിക്കുക."</string>
<string name="media_output_dialog_pairing_new" msgid="9099497976087485862">"പുതിയ ഉപകരണവുമായി ജോടിയാക്കുക"</string>
<string name="build_number_clip_data_label" msgid="3623176728412560914">"ബിൽഡ് നമ്പർ"</string>
diff --git a/packages/SystemUI/res/values-mn/strings.xml b/packages/SystemUI/res/values-mn/strings.xml
index e8fbef3..558e6db 100644
--- a/packages/SystemUI/res/values-mn/strings.xml
+++ b/packages/SystemUI/res/values-mn/strings.xml
@@ -1111,7 +1111,7 @@
<string name="media_output_dialog_group" msgid="5571251347877452212">"Бүлэг"</string>
<string name="media_output_dialog_single_device" msgid="3102758980643351058">"1 төхөөрөмж сонгосон"</string>
<string name="media_output_dialog_multiple_devices" msgid="1093771040315422350">"<xliff:g id="COUNT">%1$d</xliff:g> төхөөрөмж сонгосон"</string>
- <string name="media_output_dialog_disconnected" msgid="1834473104836986046">"<xliff:g id="DEVICE_NAME">%1$s</xliff:g> (салсан)"</string>
+ <string name="media_output_dialog_disconnected" msgid="7090512852817111185">"(салсан)"</string>
<string name="media_output_dialog_connect_failed" msgid="3225190634236259010">"Холбогдож чадсангүй. Дахин оролдоно уу."</string>
<string name="media_output_dialog_pairing_new" msgid="9099497976087485862">"Шинэ төхөөрөмж хослуулах"</string>
<string name="build_number_clip_data_label" msgid="3623176728412560914">"Хийцийн дугаар"</string>
diff --git a/packages/SystemUI/res/values-mr/strings.xml b/packages/SystemUI/res/values-mr/strings.xml
index 1ab644d..071307a 100644
--- a/packages/SystemUI/res/values-mr/strings.xml
+++ b/packages/SystemUI/res/values-mr/strings.xml
@@ -1111,7 +1111,7 @@
<string name="media_output_dialog_group" msgid="5571251347877452212">"गट"</string>
<string name="media_output_dialog_single_device" msgid="3102758980643351058">"एक डिव्हाइस निवडले"</string>
<string name="media_output_dialog_multiple_devices" msgid="1093771040315422350">"<xliff:g id="COUNT">%1$d</xliff:g> डिव्हाइस निवडली आहेत"</string>
- <string name="media_output_dialog_disconnected" msgid="1834473104836986046">"<xliff:g id="DEVICE_NAME">%1$s</xliff:g> (डिस्कनेक्ट केले)"</string>
+ <string name="media_output_dialog_disconnected" msgid="7090512852817111185">"(डिस्कनेक्ट केलेले)"</string>
<string name="media_output_dialog_connect_failed" msgid="3225190634236259010">"कनेक्ट करू शकलो नाही. पुन्हा प्रयत्न करा."</string>
<string name="media_output_dialog_pairing_new" msgid="9099497976087485862">"नवीन डिव्हाइससोबत पेअर करा"</string>
<string name="build_number_clip_data_label" msgid="3623176728412560914">"बिल्ड नंबर"</string>
diff --git a/packages/SystemUI/res/values-ms/strings.xml b/packages/SystemUI/res/values-ms/strings.xml
index 0a4bd89..5d2c9cb 100644
--- a/packages/SystemUI/res/values-ms/strings.xml
+++ b/packages/SystemUI/res/values-ms/strings.xml
@@ -1111,7 +1111,7 @@
<string name="media_output_dialog_group" msgid="5571251347877452212">"Kumpulan"</string>
<string name="media_output_dialog_single_device" msgid="3102758980643351058">"1 peranti dipilih"</string>
<string name="media_output_dialog_multiple_devices" msgid="1093771040315422350">"<xliff:g id="COUNT">%1$d</xliff:g> peranti dipilih"</string>
- <string name="media_output_dialog_disconnected" msgid="1834473104836986046">"<xliff:g id="DEVICE_NAME">%1$s</xliff:g> (diputuskan sambungan)"</string>
+ <string name="media_output_dialog_disconnected" msgid="7090512852817111185">"(diputuskan sambungan)"</string>
<string name="media_output_dialog_connect_failed" msgid="3225190634236259010">"Tidak boleh menyambung. Cuba lagi."</string>
<string name="media_output_dialog_pairing_new" msgid="9099497976087485862">"Gandingkan peranti baharu"</string>
<string name="build_number_clip_data_label" msgid="3623176728412560914">"Nombor binaan"</string>
diff --git a/packages/SystemUI/res/values-my/strings.xml b/packages/SystemUI/res/values-my/strings.xml
index 643bd01..4760834 100644
--- a/packages/SystemUI/res/values-my/strings.xml
+++ b/packages/SystemUI/res/values-my/strings.xml
@@ -512,7 +512,7 @@
<string name="media_projection_dialog_service_title" msgid="2888507074107884040">"ရိုက်ကူးဖမ်းယူခြင်း (သို့) ကာစ်လုပ်ခြင်း စတင်မလား။"</string>
<string name="media_projection_dialog_title" msgid="3316063622495360646">"<xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> နှင့် ဖမ်းယူခြင်း သို့မဟုတ် ကာစ်လုပ်ခြင်း စတင်မလား။"</string>
<string name="media_projection_remember_text" msgid="6896767327140422951">"နောက်ထပ် မပြပါနှင့်"</string>
- <string name="clear_all_notifications_text" msgid="348312370303046130">"အားလုံးထုတ်ပစ်ရန်"</string>
+ <string name="clear_all_notifications_text" msgid="348312370303046130">"အားလုံးရှင်းရန်"</string>
<string name="manage_notifications_text" msgid="6885645344647733116">"စီမံရန်"</string>
<string name="manage_notifications_history_text" msgid="57055985396576230">"မှတ်တမ်း"</string>
<string name="notification_section_header_incoming" msgid="850925217908095197">"အသစ်"</string>
@@ -1111,7 +1111,8 @@
<string name="media_output_dialog_group" msgid="5571251347877452212">"အုပ်စု"</string>
<string name="media_output_dialog_single_device" msgid="3102758980643351058">"စက်ပစ္စည်း ၁ ခုကို ရွေးချယ်ထားသည်"</string>
<string name="media_output_dialog_multiple_devices" msgid="1093771040315422350">"စက်ပစ္စည်း <xliff:g id="COUNT">%1$d</xliff:g> ခုကို ရွေးချယ်ထားသည်"</string>
- <string name="media_output_dialog_disconnected" msgid="1834473104836986046">"<xliff:g id="DEVICE_NAME">%1$s</xliff:g> (ချိတ်ဆက်မထားပါ)"</string>
+ <!-- no translation found for media_output_dialog_disconnected (7090512852817111185) -->
+ <skip />
<string name="media_output_dialog_connect_failed" msgid="3225190634236259010">"ချိတ်ဆက်၍ မရပါ။ ထပ်စမ်းကြည့်ပါ။"</string>
<string name="media_output_dialog_pairing_new" msgid="9099497976087485862">"စက်အသစ် တွဲချိတ်ရန်"</string>
<string name="build_number_clip_data_label" msgid="3623176728412560914">"တည်ဆောက်မှုနံပါတ်"</string>
diff --git a/packages/SystemUI/res/values-nb/strings.xml b/packages/SystemUI/res/values-nb/strings.xml
index 70529a6..994826d 100644
--- a/packages/SystemUI/res/values-nb/strings.xml
+++ b/packages/SystemUI/res/values-nb/strings.xml
@@ -1111,7 +1111,7 @@
<string name="media_output_dialog_group" msgid="5571251347877452212">"Gruppe"</string>
<string name="media_output_dialog_single_device" msgid="3102758980643351058">"1 enhet er valgt"</string>
<string name="media_output_dialog_multiple_devices" msgid="1093771040315422350">"<xliff:g id="COUNT">%1$d</xliff:g> enheter er valgt"</string>
- <string name="media_output_dialog_disconnected" msgid="1834473104836986046">"<xliff:g id="DEVICE_NAME">%1$s</xliff:g> (frakoblet)"</string>
+ <string name="media_output_dialog_disconnected" msgid="7090512852817111185">"(frakoblet)"</string>
<string name="media_output_dialog_connect_failed" msgid="3225190634236259010">"Kunne ikke koble til. Prøv på nytt."</string>
<string name="media_output_dialog_pairing_new" msgid="9099497976087485862">"Koble til en ny enhet"</string>
<string name="build_number_clip_data_label" msgid="3623176728412560914">"Delversjonsnummer"</string>
diff --git a/packages/SystemUI/res/values-ne/strings.xml b/packages/SystemUI/res/values-ne/strings.xml
index d75bb1b..27749da 100644
--- a/packages/SystemUI/res/values-ne/strings.xml
+++ b/packages/SystemUI/res/values-ne/strings.xml
@@ -1111,7 +1111,7 @@
<string name="media_output_dialog_group" msgid="5571251347877452212">"समूह"</string>
<string name="media_output_dialog_single_device" msgid="3102758980643351058">"१ यन्त्र चयन गरियो"</string>
<string name="media_output_dialog_multiple_devices" msgid="1093771040315422350">"<xliff:g id="COUNT">%1$d</xliff:g> वटा यन्त्र चयन गरिए"</string>
- <string name="media_output_dialog_disconnected" msgid="1834473104836986046">"<xliff:g id="DEVICE_NAME">%1$s</xliff:g> (डिस्कनेक्ट गरिएको)"</string>
+ <string name="media_output_dialog_disconnected" msgid="7090512852817111185">"(डिस्कनेक्ट गरिएको छ)"</string>
<string name="media_output_dialog_connect_failed" msgid="3225190634236259010">"कनेक्ट गर्न सकिएन। फेरि प्रयास गर्नुहोस्।"</string>
<string name="media_output_dialog_pairing_new" msgid="9099497976087485862">"नयाँ डिभाइस कनेक्ट गर्नुहोस्"</string>
<string name="build_number_clip_data_label" msgid="3623176728412560914">"बिल्ड नम्बर"</string>
diff --git a/packages/SystemUI/res/values-nl/strings.xml b/packages/SystemUI/res/values-nl/strings.xml
index cf72f0c..7cc4402 100644
--- a/packages/SystemUI/res/values-nl/strings.xml
+++ b/packages/SystemUI/res/values-nl/strings.xml
@@ -1111,7 +1111,7 @@
<string name="media_output_dialog_group" msgid="5571251347877452212">"Groep"</string>
<string name="media_output_dialog_single_device" msgid="3102758980643351058">"Eén apparaat geselecteerd"</string>
<string name="media_output_dialog_multiple_devices" msgid="1093771040315422350">"<xliff:g id="COUNT">%1$d</xliff:g> apparaten geselecteerd"</string>
- <string name="media_output_dialog_disconnected" msgid="1834473104836986046">"<xliff:g id="DEVICE_NAME">%1$s</xliff:g> (verbinding verbroken)"</string>
+ <string name="media_output_dialog_disconnected" msgid="7090512852817111185">"(verbinding verbroken)"</string>
<string name="media_output_dialog_connect_failed" msgid="3225190634236259010">"Kan geen verbinding maken. Probeer het nog eens."</string>
<string name="media_output_dialog_pairing_new" msgid="9099497976087485862">"Nieuw apparaat koppelen"</string>
<string name="build_number_clip_data_label" msgid="3623176728412560914">"Build-nummer"</string>
diff --git a/packages/SystemUI/res/values-or/strings.xml b/packages/SystemUI/res/values-or/strings.xml
index 6821f8c..b3a8e12 100644
--- a/packages/SystemUI/res/values-or/strings.xml
+++ b/packages/SystemUI/res/values-or/strings.xml
@@ -1111,7 +1111,7 @@
<string name="media_output_dialog_group" msgid="5571251347877452212">"ଗୋଷ୍ଠୀ"</string>
<string name="media_output_dialog_single_device" msgid="3102758980643351058">"1ଟି ଡିଭାଇସ୍ ଚୟନ କରାଯାଇଛି"</string>
<string name="media_output_dialog_multiple_devices" msgid="1093771040315422350">"<xliff:g id="COUNT">%1$d</xliff:g>ଟି ଡିଭାଇସ୍ ଚୟନ କରାଯାଇଛି"</string>
- <string name="media_output_dialog_disconnected" msgid="1834473104836986046">"<xliff:g id="DEVICE_NAME">%1$s</xliff:g> (ବିଚ୍ଛିନ୍ନ କରାଯାଇଛି)"</string>
+ <string name="media_output_dialog_disconnected" msgid="7090512852817111185">"(ବିଚ୍ଛିନ୍ନ କରାଯାଇଛି)"</string>
<string name="media_output_dialog_connect_failed" msgid="3225190634236259010">"ସଂଯୋଗ କରାଯାଇପାରିଲା ନାହିଁ। ପୁଣି ଚେଷ୍ଟା କରନ୍ତୁ।"</string>
<string name="media_output_dialog_pairing_new" msgid="9099497976087485862">"ନୂଆ ଡିଭାଇସକୁ ପେୟାର୍ କରନ୍ତୁ"</string>
<string name="build_number_clip_data_label" msgid="3623176728412560914">"ବିଲ୍ଡ ନମ୍ୱର"</string>
diff --git a/packages/SystemUI/res/values-pa/strings.xml b/packages/SystemUI/res/values-pa/strings.xml
index ee748a8..827a96f 100644
--- a/packages/SystemUI/res/values-pa/strings.xml
+++ b/packages/SystemUI/res/values-pa/strings.xml
@@ -1111,7 +1111,7 @@
<string name="media_output_dialog_group" msgid="5571251347877452212">"ਗਰੁੱਪ"</string>
<string name="media_output_dialog_single_device" msgid="3102758980643351058">"1 ਡੀਵਾਈਸ ਨੂੰ ਚੁਣਿਆ ਗਿਆ"</string>
<string name="media_output_dialog_multiple_devices" msgid="1093771040315422350">"<xliff:g id="COUNT">%1$d</xliff:g> ਡੀਵਾਈਸਾਂ ਨੂੰ ਚੁਣਿਆ ਗਿਆ"</string>
- <string name="media_output_dialog_disconnected" msgid="1834473104836986046">"<xliff:g id="DEVICE_NAME">%1$s</xliff:g> (ਡਿਸਕਨੈਕਟ ਹੋਇਆ)"</string>
+ <string name="media_output_dialog_disconnected" msgid="7090512852817111185">"(ਡਿਸਕਨੈਕਟ ਹੈ)"</string>
<string name="media_output_dialog_connect_failed" msgid="3225190634236259010">"ਕਨੈਕਟ ਨਹੀਂ ਕੀਤਾ ਜਾ ਸਕਿਆ। ਦੁਬਾਰਾ ਕੋਸ਼ਿਸ਼ ਕਰੋ।"</string>
<string name="media_output_dialog_pairing_new" msgid="9099497976087485862">"ਨਵਾਂ ਡੀਵਾਈਸ ਜੋੜਾਬੱਧ ਕਰੋ"</string>
<string name="build_number_clip_data_label" msgid="3623176728412560914">"ਬਿਲਡ ਨੰਬਰ"</string>
diff --git a/packages/SystemUI/res/values-pl/strings.xml b/packages/SystemUI/res/values-pl/strings.xml
index ac2d489..9826639 100644
--- a/packages/SystemUI/res/values-pl/strings.xml
+++ b/packages/SystemUI/res/values-pl/strings.xml
@@ -1123,7 +1123,7 @@
<string name="media_output_dialog_group" msgid="5571251347877452212">"Grupa"</string>
<string name="media_output_dialog_single_device" msgid="3102758980643351058">"Wybrano 1 urządzenie"</string>
<string name="media_output_dialog_multiple_devices" msgid="1093771040315422350">"Wybrane urządzenia: <xliff:g id="COUNT">%1$d</xliff:g>"</string>
- <string name="media_output_dialog_disconnected" msgid="1834473104836986046">"<xliff:g id="DEVICE_NAME">%1$s</xliff:g> (rozłączono)"</string>
+ <string name="media_output_dialog_disconnected" msgid="7090512852817111185">"(odłączono)"</string>
<string name="media_output_dialog_connect_failed" msgid="3225190634236259010">"Nie udało się połączyć. Spróbuj ponownie."</string>
<string name="media_output_dialog_pairing_new" msgid="9099497976087485862">"Sparuj nowe urządzenie"</string>
<string name="build_number_clip_data_label" msgid="3623176728412560914">"Numer kompilacji"</string>
diff --git a/packages/SystemUI/res/values-pt-rBR/strings.xml b/packages/SystemUI/res/values-pt-rBR/strings.xml
index 6a67522..6624b4e 100644
--- a/packages/SystemUI/res/values-pt-rBR/strings.xml
+++ b/packages/SystemUI/res/values-pt-rBR/strings.xml
@@ -1111,7 +1111,7 @@
<string name="media_output_dialog_group" msgid="5571251347877452212">"Grupo"</string>
<string name="media_output_dialog_single_device" msgid="3102758980643351058">"1 dispositivo selecionado"</string>
<string name="media_output_dialog_multiple_devices" msgid="1093771040315422350">"<xliff:g id="COUNT">%1$d</xliff:g> dispositivos selecionados"</string>
- <string name="media_output_dialog_disconnected" msgid="1834473104836986046">"<xliff:g id="DEVICE_NAME">%1$s</xliff:g> (desconectado)"</string>
+ <string name="media_output_dialog_disconnected" msgid="7090512852817111185">"(sem conexão)"</string>
<string name="media_output_dialog_connect_failed" msgid="3225190634236259010">"Não foi possível conectar. Tente novamente."</string>
<string name="media_output_dialog_pairing_new" msgid="9099497976087485862">"Parear novo dispositivo"</string>
<string name="build_number_clip_data_label" msgid="3623176728412560914">"Número da versão"</string>
diff --git a/packages/SystemUI/res/values-pt-rPT/strings.xml b/packages/SystemUI/res/values-pt-rPT/strings.xml
index 6225ae4..56ac4ae 100644
--- a/packages/SystemUI/res/values-pt-rPT/strings.xml
+++ b/packages/SystemUI/res/values-pt-rPT/strings.xml
@@ -1111,7 +1111,7 @@
<string name="media_output_dialog_group" msgid="5571251347877452212">"Grupo"</string>
<string name="media_output_dialog_single_device" msgid="3102758980643351058">"1 dispositivo selecionado"</string>
<string name="media_output_dialog_multiple_devices" msgid="1093771040315422350">"<xliff:g id="COUNT">%1$d</xliff:g> dispositivos selecionados"</string>
- <string name="media_output_dialog_disconnected" msgid="1834473104836986046">"<xliff:g id="DEVICE_NAME">%1$s</xliff:g> (desligado)"</string>
+ <string name="media_output_dialog_disconnected" msgid="7090512852817111185">"(desligado)"</string>
<string name="media_output_dialog_connect_failed" msgid="3225190634236259010">"Não foi possível ligar. Tente novamente."</string>
<string name="media_output_dialog_pairing_new" msgid="9099497976087485862">"Sincronize o novo dispositivo"</string>
<string name="build_number_clip_data_label" msgid="3623176728412560914">"Número da compilação"</string>
diff --git a/packages/SystemUI/res/values-pt/strings.xml b/packages/SystemUI/res/values-pt/strings.xml
index 6a67522..6624b4e 100644
--- a/packages/SystemUI/res/values-pt/strings.xml
+++ b/packages/SystemUI/res/values-pt/strings.xml
@@ -1111,7 +1111,7 @@
<string name="media_output_dialog_group" msgid="5571251347877452212">"Grupo"</string>
<string name="media_output_dialog_single_device" msgid="3102758980643351058">"1 dispositivo selecionado"</string>
<string name="media_output_dialog_multiple_devices" msgid="1093771040315422350">"<xliff:g id="COUNT">%1$d</xliff:g> dispositivos selecionados"</string>
- <string name="media_output_dialog_disconnected" msgid="1834473104836986046">"<xliff:g id="DEVICE_NAME">%1$s</xliff:g> (desconectado)"</string>
+ <string name="media_output_dialog_disconnected" msgid="7090512852817111185">"(sem conexão)"</string>
<string name="media_output_dialog_connect_failed" msgid="3225190634236259010">"Não foi possível conectar. Tente novamente."</string>
<string name="media_output_dialog_pairing_new" msgid="9099497976087485862">"Parear novo dispositivo"</string>
<string name="build_number_clip_data_label" msgid="3623176728412560914">"Número da versão"</string>
diff --git a/packages/SystemUI/res/values-ro/strings.xml b/packages/SystemUI/res/values-ro/strings.xml
index a09779d..2d14dbe 100644
--- a/packages/SystemUI/res/values-ro/strings.xml
+++ b/packages/SystemUI/res/values-ro/strings.xml
@@ -1117,7 +1117,7 @@
<string name="media_output_dialog_group" msgid="5571251347877452212">"Grup"</string>
<string name="media_output_dialog_single_device" msgid="3102758980643351058">"S-a selectat un dispozitiv"</string>
<string name="media_output_dialog_multiple_devices" msgid="1093771040315422350">"S-au selectat <xliff:g id="COUNT">%1$d</xliff:g> dispozitive"</string>
- <string name="media_output_dialog_disconnected" msgid="1834473104836986046">"<xliff:g id="DEVICE_NAME">%1$s</xliff:g> (s-a deconectat)"</string>
+ <string name="media_output_dialog_disconnected" msgid="7090512852817111185">"(deconectat)"</string>
<string name="media_output_dialog_connect_failed" msgid="3225190634236259010">"Nu s-a putut conecta. Reîncercați."</string>
<string name="media_output_dialog_pairing_new" msgid="9099497976087485862">"Asociați un nou dispozitiv"</string>
<string name="build_number_clip_data_label" msgid="3623176728412560914">"Numărul versiunii"</string>
diff --git a/packages/SystemUI/res/values-ru/strings.xml b/packages/SystemUI/res/values-ru/strings.xml
index 1b6e85b..2c1f7b8 100644
--- a/packages/SystemUI/res/values-ru/strings.xml
+++ b/packages/SystemUI/res/values-ru/strings.xml
@@ -1123,7 +1123,7 @@
<string name="media_output_dialog_group" msgid="5571251347877452212">"Группа"</string>
<string name="media_output_dialog_single_device" msgid="3102758980643351058">"Выбрано 1 устройство"</string>
<string name="media_output_dialog_multiple_devices" msgid="1093771040315422350">"Выбрано устройств: <xliff:g id="COUNT">%1$d</xliff:g>"</string>
- <string name="media_output_dialog_disconnected" msgid="1834473104836986046">"<xliff:g id="DEVICE_NAME">%1$s</xliff:g> (отключено)"</string>
+ <string name="media_output_dialog_disconnected" msgid="7090512852817111185">"(нет подключения)"</string>
<string name="media_output_dialog_connect_failed" msgid="3225190634236259010">"Не удалось подключиться. Повторите попытку."</string>
<string name="media_output_dialog_pairing_new" msgid="9099497976087485862">"Подключить новое устройство"</string>
<string name="build_number_clip_data_label" msgid="3623176728412560914">"Номер сборки"</string>
@@ -1167,7 +1167,7 @@
<string name="person_available" msgid="2318599327472755472">"Онлайн"</string>
<string name="battery_state_unknown_notification_title" msgid="8464703640483773454">"Не удалось узнать уровень заряда батареи"</string>
<string name="battery_state_unknown_notification_text" msgid="13720937839460899">"Нажмите, чтобы узнать больше."</string>
- <string name="qs_alarm_tile_no_alarm" msgid="4826472008616807923">"Будильников нет"</string>
+ <string name="qs_alarm_tile_no_alarm" msgid="4826472008616807923">"Нет будильников"</string>
<string name="accessibility_fingerprint_label" msgid="5255731221854153660">"Сканер отпечатков пальцев"</string>
<string name="accessibility_udfps_disabled_button" msgid="4284034245130239384">"Сканер отпечатков пальцев отключен"</string>
<string name="accessibility_authenticate_hint" msgid="798914151813205721">"выполнить аутентификацию"</string>
diff --git a/packages/SystemUI/res/values-si/strings.xml b/packages/SystemUI/res/values-si/strings.xml
index 94d8705..d0fae03 100644
--- a/packages/SystemUI/res/values-si/strings.xml
+++ b/packages/SystemUI/res/values-si/strings.xml
@@ -1111,7 +1111,7 @@
<string name="media_output_dialog_group" msgid="5571251347877452212">"සමූහය"</string>
<string name="media_output_dialog_single_device" msgid="3102758980643351058">"උපාංග 1ක් තෝරන ලදී"</string>
<string name="media_output_dialog_multiple_devices" msgid="1093771040315422350">"උපාංග <xliff:g id="COUNT">%1$d</xliff:g>ක් තෝරන ලදී"</string>
- <string name="media_output_dialog_disconnected" msgid="1834473104836986046">"<xliff:g id="DEVICE_NAME">%1$s</xliff:g> (විසන්ධි විය)"</string>
+ <string name="media_output_dialog_disconnected" msgid="7090512852817111185">"(විසන්ධි විය)"</string>
<string name="media_output_dialog_connect_failed" msgid="3225190634236259010">"සම්බන්ධ වීමට නොහැකි විය. නැවත උත්සාහ කරන්න."</string>
<string name="media_output_dialog_pairing_new" msgid="9099497976087485862">"නව උපාංගය යුගල කරන්න"</string>
<string name="build_number_clip_data_label" msgid="3623176728412560914">"නිමැවුම් අංකය"</string>
diff --git a/packages/SystemUI/res/values-sk/strings.xml b/packages/SystemUI/res/values-sk/strings.xml
index a0ba5cd..9bb6ddf 100644
--- a/packages/SystemUI/res/values-sk/strings.xml
+++ b/packages/SystemUI/res/values-sk/strings.xml
@@ -1123,7 +1123,7 @@
<string name="media_output_dialog_group" msgid="5571251347877452212">"Skupina"</string>
<string name="media_output_dialog_single_device" msgid="3102758980643351058">"1 vybrané zariadenie"</string>
<string name="media_output_dialog_multiple_devices" msgid="1093771040315422350">"Počet vybraných zariadení: <xliff:g id="COUNT">%1$d</xliff:g>"</string>
- <string name="media_output_dialog_disconnected" msgid="1834473104836986046">"<xliff:g id="DEVICE_NAME">%1$s</xliff:g> (odpojené)"</string>
+ <string name="media_output_dialog_disconnected" msgid="7090512852817111185">"(odpojené)"</string>
<string name="media_output_dialog_connect_failed" msgid="3225190634236259010">"Nepodarilo sa pripojiť. Skúste to znova."</string>
<string name="media_output_dialog_pairing_new" msgid="9099497976087485862">"Spárovať nové zariadenie"</string>
<string name="build_number_clip_data_label" msgid="3623176728412560914">"Číslo zostavy"</string>
diff --git a/packages/SystemUI/res/values-sl/strings.xml b/packages/SystemUI/res/values-sl/strings.xml
index 649e123..3630f37 100644
--- a/packages/SystemUI/res/values-sl/strings.xml
+++ b/packages/SystemUI/res/values-sl/strings.xml
@@ -1123,7 +1123,7 @@
<string name="media_output_dialog_group" msgid="5571251347877452212">"Skupina"</string>
<string name="media_output_dialog_single_device" msgid="3102758980643351058">"Izbrana je ena naprava"</string>
<string name="media_output_dialog_multiple_devices" msgid="1093771040315422350">"Izbranih je toliko naprav: <xliff:g id="COUNT">%1$d</xliff:g>"</string>
- <string name="media_output_dialog_disconnected" msgid="1834473104836986046">"<xliff:g id="DEVICE_NAME">%1$s</xliff:g> (povezava prekinjena)"</string>
+ <string name="media_output_dialog_disconnected" msgid="7090512852817111185">"(povezava je prekinjena)"</string>
<string name="media_output_dialog_connect_failed" msgid="3225190634236259010">"Povezave ni bilo mogoče vzpostaviti. Poskusite znova."</string>
<string name="media_output_dialog_pairing_new" msgid="9099497976087485862">"Seznanitev nove naprave"</string>
<string name="build_number_clip_data_label" msgid="3623176728412560914">"Delovna različica"</string>
diff --git a/packages/SystemUI/res/values-sq/strings.xml b/packages/SystemUI/res/values-sq/strings.xml
index f5c30dd..e0abe17 100644
--- a/packages/SystemUI/res/values-sq/strings.xml
+++ b/packages/SystemUI/res/values-sq/strings.xml
@@ -1111,7 +1111,7 @@
<string name="media_output_dialog_group" msgid="5571251347877452212">"Grupi"</string>
<string name="media_output_dialog_single_device" msgid="3102758980643351058">"1 pajisje e zgjedhur"</string>
<string name="media_output_dialog_multiple_devices" msgid="1093771040315422350">"<xliff:g id="COUNT">%1$d</xliff:g> pajisje të zgjedhura"</string>
- <string name="media_output_dialog_disconnected" msgid="1834473104836986046">"<xliff:g id="DEVICE_NAME">%1$s</xliff:g> (e shkëputur)"</string>
+ <string name="media_output_dialog_disconnected" msgid="7090512852817111185">"(shkëputur)"</string>
<string name="media_output_dialog_connect_failed" msgid="3225190634236259010">"Nuk mund të lidhej. Provo sërish."</string>
<string name="media_output_dialog_pairing_new" msgid="9099497976087485862">"Çifto pajisjen e re"</string>
<string name="build_number_clip_data_label" msgid="3623176728412560914">"Numri i ndërtimit"</string>
diff --git a/packages/SystemUI/res/values-sr/strings.xml b/packages/SystemUI/res/values-sr/strings.xml
index bcd7bc8..efe4c3b 100644
--- a/packages/SystemUI/res/values-sr/strings.xml
+++ b/packages/SystemUI/res/values-sr/strings.xml
@@ -1117,7 +1117,7 @@
<string name="media_output_dialog_group" msgid="5571251347877452212">"Група"</string>
<string name="media_output_dialog_single_device" msgid="3102758980643351058">"Изабран је 1 уређај"</string>
<string name="media_output_dialog_multiple_devices" msgid="1093771040315422350">"Изабраних уређаја: <xliff:g id="COUNT">%1$d</xliff:g>"</string>
- <string name="media_output_dialog_disconnected" msgid="1834473104836986046">"<xliff:g id="DEVICE_NAME">%1$s</xliff:g> (веза је прекинута)"</string>
+ <string name="media_output_dialog_disconnected" msgid="7090512852817111185">"(веза је прекинута)"</string>
<string name="media_output_dialog_connect_failed" msgid="3225190634236259010">"Повезивање није успело. Пробајте поново."</string>
<string name="media_output_dialog_pairing_new" msgid="9099497976087485862">"Упари нови уређај"</string>
<string name="build_number_clip_data_label" msgid="3623176728412560914">"Број верзије"</string>
@@ -1161,7 +1161,7 @@
<string name="person_available" msgid="2318599327472755472">"Доступно"</string>
<string name="battery_state_unknown_notification_title" msgid="8464703640483773454">"Проблем са очитавањем мерача батерије"</string>
<string name="battery_state_unknown_notification_text" msgid="13720937839460899">"Додирните за више информација"</string>
- <string name="qs_alarm_tile_no_alarm" msgid="4826472008616807923">"Аларм није подешен"</string>
+ <string name="qs_alarm_tile_no_alarm" msgid="4826472008616807923">"Није подешен"</string>
<string name="accessibility_fingerprint_label" msgid="5255731221854153660">"Сензор за отисак прста"</string>
<string name="accessibility_udfps_disabled_button" msgid="4284034245130239384">"Сензор за отисак прста је онемогућен"</string>
<string name="accessibility_authenticate_hint" msgid="798914151813205721">"потврдите идентитет"</string>
diff --git a/packages/SystemUI/res/values-sv/strings.xml b/packages/SystemUI/res/values-sv/strings.xml
index 45666a2..cc773ef 100644
--- a/packages/SystemUI/res/values-sv/strings.xml
+++ b/packages/SystemUI/res/values-sv/strings.xml
@@ -297,8 +297,8 @@
<string name="accessibility_quick_settings_work_mode_changed_on" msgid="1105258550138313384">"Arbetsläget har aktiverats."</string>
<string name="accessibility_quick_settings_data_saver_changed_off" msgid="4910847127871603832">"Databesparing har inaktiverats."</string>
<string name="accessibility_quick_settings_data_saver_changed_on" msgid="6370606590802623078">"Databesparing har aktiverats."</string>
- <string name="accessibility_quick_settings_sensor_privacy_changed_off" msgid="7608378211873807353">"Sensorsekretess har inaktiverats."</string>
- <string name="accessibility_quick_settings_sensor_privacy_changed_on" msgid="4267393685085328801">"Sensorsekretess har aktiverats."</string>
+ <string name="accessibility_quick_settings_sensor_privacy_changed_off" msgid="7608378211873807353">"Sensorintegritet har inaktiverats."</string>
+ <string name="accessibility_quick_settings_sensor_privacy_changed_on" msgid="4267393685085328801">"Sensorintegritet har aktiverats."</string>
<string name="accessibility_brightness" msgid="5391187016177823721">"Skärmens ljusstyrka"</string>
<string name="accessibility_ambient_display_charging" msgid="7725523068728128968">"Laddas"</string>
<string name="data_usage_disabled_dialog_3g_title" msgid="5716594205739750015">"2G- och 3G-data har pausats"</string>
@@ -1111,7 +1111,7 @@
<string name="media_output_dialog_group" msgid="5571251347877452212">"Grupp"</string>
<string name="media_output_dialog_single_device" msgid="3102758980643351058">"1 enhet har valts"</string>
<string name="media_output_dialog_multiple_devices" msgid="1093771040315422350">"<xliff:g id="COUNT">%1$d</xliff:g> enheter har valts"</string>
- <string name="media_output_dialog_disconnected" msgid="1834473104836986046">"<xliff:g id="DEVICE_NAME">%1$s</xliff:g> (frånkopplad)"</string>
+ <string name="media_output_dialog_disconnected" msgid="7090512852817111185">"(frånkopplad)"</string>
<string name="media_output_dialog_connect_failed" msgid="3225190634236259010">"Det gick inte att ansluta. Försök igen."</string>
<string name="media_output_dialog_pairing_new" msgid="9099497976087485862">"Parkoppla en ny enhet"</string>
<string name="build_number_clip_data_label" msgid="3623176728412560914">"Versionsnummer"</string>
diff --git a/packages/SystemUI/res/values-sw/strings.xml b/packages/SystemUI/res/values-sw/strings.xml
index e976c92..4b20d91 100644
--- a/packages/SystemUI/res/values-sw/strings.xml
+++ b/packages/SystemUI/res/values-sw/strings.xml
@@ -1111,7 +1111,7 @@
<string name="media_output_dialog_group" msgid="5571251347877452212">"Kikundi"</string>
<string name="media_output_dialog_single_device" msgid="3102758980643351058">"Umechagua kifaa 1"</string>
<string name="media_output_dialog_multiple_devices" msgid="1093771040315422350">"Umechagua vifaa <xliff:g id="COUNT">%1$d</xliff:g>"</string>
- <string name="media_output_dialog_disconnected" msgid="1834473104836986046">"<xliff:g id="DEVICE_NAME">%1$s</xliff:g> (hakijaunganishwa)"</string>
+ <string name="media_output_dialog_disconnected" msgid="7090512852817111185">"(imetenganishwa)"</string>
<string name="media_output_dialog_connect_failed" msgid="3225190634236259010">"Imeshindwa kuunganisha. Jaribu tena."</string>
<string name="media_output_dialog_pairing_new" msgid="9099497976087485862">"Oanisha kifaa kipya"</string>
<string name="build_number_clip_data_label" msgid="3623176728412560914">"Nambari ya muundo"</string>
diff --git a/packages/SystemUI/res/values-sw360dp/dimens.xml b/packages/SystemUI/res/values-sw360dp/dimens.xml
index fc510bf..65ca70b 100644
--- a/packages/SystemUI/res/values-sw360dp/dimens.xml
+++ b/packages/SystemUI/res/values-sw360dp/dimens.xml
@@ -19,9 +19,6 @@
<!-- The width of the view containing navigation buttons -->
<dimen name="navigation_key_width">80dip</dimen>
- <!-- The width of the view containing the menu/ime navigation bar icons -->
- <dimen name="navigation_extra_key_width">40dip</dimen>
-
<!-- The padding on the side of the navigation bar. Must be greater than or equal to
navigation_extra_key_width -->
<dimen name="navigation_side_padding">40dip</dimen>
diff --git a/packages/SystemUI/res/values-sw392dp/dimens.xml b/packages/SystemUI/res/values-sw392dp/dimens.xml
index 4c9d02e..78279ca 100644
--- a/packages/SystemUI/res/values-sw392dp/dimens.xml
+++ b/packages/SystemUI/res/values-sw392dp/dimens.xml
@@ -20,16 +20,8 @@
<dimen name="global_actions_grid_horizontal_padding">3dp</dimen>
<dimen name="global_actions_grid_item_side_margin">10dp</dimen>
- <dimen name="global_actions_grid_item_vertical_margin">6dp</dimen>
- <dimen name="global_actions_grid_item_width">72dp</dimen>
<dimen name="global_actions_grid_item_height">72dp</dimen>
- <dimen name="global_actions_grid_item_icon_width">22dp</dimen>
- <dimen name="global_actions_grid_item_icon_height">22dp</dimen>
- <dimen name="global_actions_grid_item_icon_top_margin">14dp</dimen>
- <dimen name="global_actions_grid_item_icon_side_margin">22dp</dimen>
- <dimen name="global_actions_grid_item_icon_bottom_margin">4dp</dimen>
-
<!-- Home Controls -->
<dimen name="global_actions_side_margin">16dp</dimen>
</resources>
diff --git a/packages/SystemUI/res/values-sw410dp/config.xml b/packages/SystemUI/res/values-sw410dp/config.xml
deleted file mode 100644
index 8ace7bf..0000000
--- a/packages/SystemUI/res/values-sw410dp/config.xml
+++ /dev/null
@@ -1,24 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
-/*
-** Copyright 2016, 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.
-*/
--->
-
-<!-- These resources are around just to allow their values to be customized
- for different hardware and product builds. -->
-<resources>
- <bool name="quick_settings_show_full_alarm">true</bool>
-</resources>
diff --git a/packages/SystemUI/res/values-sw410dp/dimens.xml b/packages/SystemUI/res/values-sw410dp/dimens.xml
index 6780dca..d33ee99 100644
--- a/packages/SystemUI/res/values-sw410dp/dimens.xml
+++ b/packages/SystemUI/res/values-sw410dp/dimens.xml
@@ -27,14 +27,6 @@
<dimen name="global_actions_grid_horizontal_padding">4dp</dimen>
<dimen name="global_actions_grid_item_side_margin">12dp</dimen>
- <dimen name="global_actions_grid_item_vertical_margin">8dp</dimen>
- <dimen name="global_actions_grid_item_width">72dp</dimen>
<dimen name="global_actions_grid_item_height">72dp</dimen>
- <dimen name="global_actions_grid_item_icon_width">24dp</dimen>
- <dimen name="global_actions_grid_item_icon_height">24dp</dimen>
- <dimen name="global_actions_grid_item_icon_top_margin">18dp</dimen>
- <dimen name="global_actions_grid_item_icon_side_margin">24dp</dimen>
- <dimen name="global_actions_grid_item_icon_bottom_margin">4dp</dimen>
-
</resources>
diff --git a/packages/SystemUI/res/values-sw600dp-land/config.xml b/packages/SystemUI/res/values-sw600dp-land/config.xml
index ab159e1..040df86 100644
--- a/packages/SystemUI/res/values-sw600dp-land/config.xml
+++ b/packages/SystemUI/res/values-sw600dp-land/config.xml
@@ -32,4 +32,6 @@
<!-- Notifications are sized to match the width of two (of 4) qs tiles in landscape. -->
<bool name="config_skinnyNotifsInLandscape">false</bool>
+
+ <dimen name="keyguard_indication_margin_bottom">25dp</dimen>
</resources>
diff --git a/packages/SystemUI/res/values-sw600dp/config.xml b/packages/SystemUI/res/values-sw600dp/config.xml
index 45b5afa..f5dc7e3e 100644
--- a/packages/SystemUI/res/values-sw600dp/config.xml
+++ b/packages/SystemUI/res/values-sw600dp/config.xml
@@ -23,18 +23,12 @@
<!-- The maximum number of rows in the QuickSettings -->
<integer name="quick_settings_max_rows">4</integer>
- <!-- The number of columns that the top level tiles span in the QuickSettings -->
- <integer name="quick_settings_user_time_settings_tile_span">1</integer>
-
<!-- Nav bar button default ordering/layout -->
<string name="config_navBarLayout" translatable="false">left;back,home,recent;right</string>
<!-- orientation of the dead zone when touches have recently occurred elsewhere on screen -->
<integer name="navigation_bar_deadzone_orientation">0</integer>
- <!-- Whether wallet view is shown in landscape / seascape orientations -->
- <bool name="global_actions_show_landscape_wallet_view">true</bool>
-
<!-- Max number of columns for quick controls area -->
<integer name="controls_max_columns">4</integer>
diff --git a/packages/SystemUI/res/values-sw600dp/dimens.xml b/packages/SystemUI/res/values-sw600dp/dimens.xml
index 85f8f09..c527c5f 100644
--- a/packages/SystemUI/res/values-sw600dp/dimens.xml
+++ b/packages/SystemUI/res/values-sw600dp/dimens.xml
@@ -16,26 +16,6 @@
*/
-->
<resources>
-
- <!-- Diameter of outer shape drawable shown in navbar search-->
- <dimen name="navbar_search_outerring_diameter">430dip</dimen>
-
- <!-- Diameter of outer shape drawable shown in navbar search. Should be 1/2 of above value. -->
- <dimen name="navbar_search_outerring_radius">215dip</dimen>
-
- <!-- Height of search panel including navigation bar height -->
- <dimen name="navbar_search_panel_height">280dip</dimen>
-
- <!-- The width of the view containing the menu/ime navigation bar icons -->
- <dimen name="navigation_extra_key_width">48dip</dimen>
-
- <!-- Minimum fraction of the screen that should be taken up by the notification panel. -->
- <item type="dimen" name="notification_panel_min_height_frac">40%</item>
-
- <!-- How far to slide the panel out when you touch it -->
- <!-- On tablets this is just the close_handle_height -->
- <dimen name="peek_height">@dimen/close_handle_height</dimen>
-
<!-- Height of the status bar header bar when on Keyguard -->
<dimen name="status_bar_header_height_keyguard">60dp</dimen>
@@ -45,14 +25,8 @@
<dimen name="kg_framed_avatar_size">48dp</dimen>
<!-- The width of user avatar when on Keyguard -->
- <dimen name="multi_user_switch_width_keyguard">48dp</dimen>
-
- <!-- The width of user avatar when on Keyguard -->
<dimen name="multi_user_avatar_keyguard_size">30dp</dimen>
- <!-- end margin for multi user switch in collapsed quick settings -->
- <dimen name="multi_user_switch_keyguard_margin">6dp</dimen>
-
<!-- Margin on the left side of the carrier text on Keyguard -->
<dimen name="keyguard_carrier_text_margin">24dp</dimen>
@@ -60,13 +34,6 @@
<dimen name="keyguard_affordance_height">80dp</dimen>
<dimen name="keyguard_affordance_width">120dp</dimen>
- <!-- The width of the region on the left/right edge of the screen for performing the camera/
- phone hints. -->
- <dimen name="edge_tap_area_width">80dp</dimen>
-
- <!-- Margin on the right side of the system icon group on Keyguard. -->
- <dimen name="system_icons_keyguard_padding_end">2dp</dimen>
-
<!-- Screen pinning request width -->
<dimen name="screen_pinning_request_width">400dp</dimen>
<!-- Screen pinning request bottom button circle widths -->
@@ -78,10 +45,7 @@
(screen_pinning_request_width - 3 * screen_pinning_request_button_width) / 2 -->
<dimen name="screen_pinning_request_side_width">8dp</dimen>
- <dimen name="fab_margin">24dp</dimen>
-
<dimen name="navigation_key_width">128dp</dimen>
- <dimen name="navigation_key_padding">25dp</dimen>
<!-- Keyboard shortcuts helper -->
<dimen name="ksh_layout_width">488dp</dimen>
@@ -89,8 +53,6 @@
<!-- Text size for user name in user switcher -->
<dimen name="kg_user_switcher_text_size">18sp</dimen>
- <!-- TODO(himanshujaju) - add comments -->
- <dimen name="global_actions_wallet_top_margin">5dp</dimen>
<dimen name="controls_header_bottom_margin">12dp</dimen>
<dimen name="controls_top_margin">24dp</dimen>
@@ -105,5 +67,5 @@
<dimen name="qs_detail_margin_top">0dp</dimen>
<!-- The width of large/content heavy dialogs (e.g. Internet, Media output, etc) -->
- <dimen name="large_dialog_width">624dp</dimen>
+ <dimen name="large_dialog_width">504dp</dimen>
</resources>
diff --git a/packages/SystemUI/res/values-sw600dp/styles.xml b/packages/SystemUI/res/values-sw600dp/styles.xml
index ee2b82d..7a2602e 100644
--- a/packages/SystemUI/res/values-sw600dp/styles.xml
+++ b/packages/SystemUI/res/values-sw600dp/styles.xml
@@ -15,9 +15,6 @@
-->
<resources xmlns:android="http://schemas.android.com/apk/res/android">
- <style name="BrightnessDialogContainer" parent="@style/BaseBrightnessDialogContainer">
- <item name="android:layout_width">@dimen/notification_panel_width</item>
- </style>
<style name="UserDetailView">
<item name="numColumns">4</item>
diff --git a/packages/SystemUI/res/values-sw720dp/config.xml b/packages/SystemUI/res/values-sw720dp/config.xml
deleted file mode 100644
index 436f8d0..0000000
--- a/packages/SystemUI/res/values-sw720dp/config.xml
+++ /dev/null
@@ -1,26 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
-/*
-** Copyright 2011, 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.
-*/
--->
-
-<!-- These resources are around just to allow their values to be customized
- for different hardware and product builds. -->
-<resources>
- <integer name="status_bar_config_maxNotificationIcons">5</integer>
-
-</resources>
-
diff --git a/packages/SystemUI/res/values-sw720dp/dimens.xml b/packages/SystemUI/res/values-sw720dp/dimens.xml
index 8cf4adb..1564ee8 100644
--- a/packages/SystemUI/res/values-sw720dp/dimens.xml
+++ b/packages/SystemUI/res/values-sw720dp/dimens.xml
@@ -17,16 +17,7 @@
-->
<resources>
- <!-- ======================================== -->
- <!-- The following resources were recently moved from sw600dp; there may
- be situations where they don't sync up perfectly with PhoneStatusBar. -->
- <!-- ======================================== -->
-
<!-- gap on either side of status bar notification icons -->
<dimen name="status_bar_icon_padding">1dp</dimen>
- <!-- The minimum height of the notification panel window -->
- <dimen name="notification_panel_min_height">770dp</dimen>
- <!-- Bottom margin (from display edge) for status bar panels -->
- <dimen name="panel_float">56dp</dimen>
</resources>
diff --git a/packages/SystemUI/res/values-sw900dp/dimens.xml b/packages/SystemUI/res/values-sw900dp/dimens.xml
index 2cff976..ed8f20a 100644
--- a/packages/SystemUI/res/values-sw900dp/dimens.xml
+++ b/packages/SystemUI/res/values-sw900dp/dimens.xml
@@ -20,7 +20,6 @@
<dimen name="button_size">80dp</dimen>
<dimen name="navigation_side_padding">@dimen/button_size</dimen>
<dimen name="navigation_key_width">@dimen/button_size</dimen>
- <dimen name="navigation_extra_key_width">@dimen/button_size</dimen>
<!-- The maximum width of the navigation bar ripples. -->
<dimen name="key_button_ripple_max_width">76dp</dimen>
diff --git a/packages/SystemUI/res/values-ta/strings.xml b/packages/SystemUI/res/values-ta/strings.xml
index bfe399d..489777d 100644
--- a/packages/SystemUI/res/values-ta/strings.xml
+++ b/packages/SystemUI/res/values-ta/strings.xml
@@ -1111,7 +1111,7 @@
<string name="media_output_dialog_group" msgid="5571251347877452212">"குழு"</string>
<string name="media_output_dialog_single_device" msgid="3102758980643351058">"1 சாதனம் தேர்ந்தெடுக்கப்பட்டுள்ளது"</string>
<string name="media_output_dialog_multiple_devices" msgid="1093771040315422350">"<xliff:g id="COUNT">%1$d</xliff:g> சாதனங்கள் தேர்ந்தெடுக்கப்பட்டுள்ளன"</string>
- <string name="media_output_dialog_disconnected" msgid="1834473104836986046">"<xliff:g id="DEVICE_NAME">%1$s</xliff:g> (இணைப்பு துண்டிக்கப்பட்டது)"</string>
+ <string name="media_output_dialog_disconnected" msgid="7090512852817111185">"(துண்டிக்கப்பட்டது)"</string>
<string name="media_output_dialog_connect_failed" msgid="3225190634236259010">"இணைக்க முடியவில்லை. மீண்டும் முயலவும்."</string>
<string name="media_output_dialog_pairing_new" msgid="9099497976087485862">"புதிய சாதனத்தை இணைத்தல்"</string>
<string name="build_number_clip_data_label" msgid="3623176728412560914">"பதிப்பு எண்"</string>
diff --git a/packages/SystemUI/res/values-te/strings.xml b/packages/SystemUI/res/values-te/strings.xml
index e6d7de9..70a1aaa 100644
--- a/packages/SystemUI/res/values-te/strings.xml
+++ b/packages/SystemUI/res/values-te/strings.xml
@@ -1111,7 +1111,7 @@
<string name="media_output_dialog_group" msgid="5571251347877452212">"గ్రూప్"</string>
<string name="media_output_dialog_single_device" msgid="3102758980643351058">"1 పరికరం ఎంచుకోబడింది"</string>
<string name="media_output_dialog_multiple_devices" msgid="1093771040315422350">"<xliff:g id="COUNT">%1$d</xliff:g> పరికరాలు ఎంచుకోబడ్డాయి"</string>
- <string name="media_output_dialog_disconnected" msgid="1834473104836986046">"<xliff:g id="DEVICE_NAME">%1$s</xliff:g> (డిస్కనెక్ట్ అయ్యింది)"</string>
+ <string name="media_output_dialog_disconnected" msgid="7090512852817111185">"(డిస్కనెక్ట్ అయ్యింది)"</string>
<string name="media_output_dialog_connect_failed" msgid="3225190634236259010">"కనెక్ట్ చేయడం సాధ్యపడలేదు. మళ్లీ ట్రై చేయండి."</string>
<string name="media_output_dialog_pairing_new" msgid="9099497976087485862">"కొత్త పరికరాన్ని పెయిర్ చేయండి"</string>
<string name="build_number_clip_data_label" msgid="3623176728412560914">"బిల్డ్ నంబర్"</string>
diff --git a/packages/SystemUI/res/values-th/strings.xml b/packages/SystemUI/res/values-th/strings.xml
index 55329bd..dbc30ea 100644
--- a/packages/SystemUI/res/values-th/strings.xml
+++ b/packages/SystemUI/res/values-th/strings.xml
@@ -1111,7 +1111,7 @@
<string name="media_output_dialog_group" msgid="5571251347877452212">"กลุ่ม"</string>
<string name="media_output_dialog_single_device" msgid="3102758980643351058">"เลือกอุปกรณ์ไว้ 1 รายการ"</string>
<string name="media_output_dialog_multiple_devices" msgid="1093771040315422350">"เลือกอุปกรณ์ไว้ <xliff:g id="COUNT">%1$d</xliff:g> รายการ"</string>
- <string name="media_output_dialog_disconnected" msgid="1834473104836986046">"<xliff:g id="DEVICE_NAME">%1$s</xliff:g> (ยกเลิกการเชื่อมต่อแล้ว)"</string>
+ <string name="media_output_dialog_disconnected" msgid="7090512852817111185">"(ยกเลิกการเชื่อมต่อแล้ว)"</string>
<string name="media_output_dialog_connect_failed" msgid="3225190634236259010">"เชื่อมต่อไม่ได้ ลองใหม่"</string>
<string name="media_output_dialog_pairing_new" msgid="9099497976087485862">"จับคู่อุปกรณ์ใหม่"</string>
<string name="build_number_clip_data_label" msgid="3623176728412560914">"หมายเลขบิลด์"</string>
diff --git a/packages/SystemUI/res/values-tl/strings.xml b/packages/SystemUI/res/values-tl/strings.xml
index 264632b..e2f621a 100644
--- a/packages/SystemUI/res/values-tl/strings.xml
+++ b/packages/SystemUI/res/values-tl/strings.xml
@@ -1111,7 +1111,7 @@
<string name="media_output_dialog_group" msgid="5571251347877452212">"Grupo"</string>
<string name="media_output_dialog_single_device" msgid="3102758980643351058">"1 device ang napili"</string>
<string name="media_output_dialog_multiple_devices" msgid="1093771040315422350">"<xliff:g id="COUNT">%1$d</xliff:g> (na) device ang napili"</string>
- <string name="media_output_dialog_disconnected" msgid="1834473104836986046">"<xliff:g id="DEVICE_NAME">%1$s</xliff:g> (nakadiskonekta)"</string>
+ <string name="media_output_dialog_disconnected" msgid="7090512852817111185">"(nadiskonekta)"</string>
<string name="media_output_dialog_connect_failed" msgid="3225190634236259010">"Hindi makakonekta. Subukan ulit."</string>
<string name="media_output_dialog_pairing_new" msgid="9099497976087485862">"Magpares ng bagong device"</string>
<string name="build_number_clip_data_label" msgid="3623176728412560914">"Numero ng build"</string>
diff --git a/packages/SystemUI/res/values-tr/strings.xml b/packages/SystemUI/res/values-tr/strings.xml
index c691440..d010aaa 100644
--- a/packages/SystemUI/res/values-tr/strings.xml
+++ b/packages/SystemUI/res/values-tr/strings.xml
@@ -1111,7 +1111,7 @@
<string name="media_output_dialog_group" msgid="5571251347877452212">"Grup"</string>
<string name="media_output_dialog_single_device" msgid="3102758980643351058">"1 cihaz seçildi"</string>
<string name="media_output_dialog_multiple_devices" msgid="1093771040315422350">"<xliff:g id="COUNT">%1$d</xliff:g> cihaz seçildi"</string>
- <string name="media_output_dialog_disconnected" msgid="1834473104836986046">"<xliff:g id="DEVICE_NAME">%1$s</xliff:g> (bağlı değil)"</string>
+ <string name="media_output_dialog_disconnected" msgid="7090512852817111185">"(bağlantı kesildi)"</string>
<string name="media_output_dialog_connect_failed" msgid="3225190634236259010">"Bağlanılamadı. Tekrar deneyin."</string>
<string name="media_output_dialog_pairing_new" msgid="9099497976087485862">"Yeni cihaz eşle"</string>
<string name="build_number_clip_data_label" msgid="3623176728412560914">"Derleme numarası"</string>
@@ -1155,7 +1155,7 @@
<string name="person_available" msgid="2318599327472755472">"Müsait"</string>
<string name="battery_state_unknown_notification_title" msgid="8464703640483773454">"Pil ölçeriniz okunurken sorun oluştu"</string>
<string name="battery_state_unknown_notification_text" msgid="13720937839460899">"Daha fazla bilgi için dokunun"</string>
- <string name="qs_alarm_tile_no_alarm" msgid="4826472008616807923">"Alarm ayarlanmadı"</string>
+ <string name="qs_alarm_tile_no_alarm" msgid="4826472008616807923">"Alarm yok"</string>
<string name="accessibility_fingerprint_label" msgid="5255731221854153660">"Parmak izi sensörü"</string>
<string name="accessibility_udfps_disabled_button" msgid="4284034245130239384">"Parmak izi sensörü devre dışı bırakıldı"</string>
<string name="accessibility_authenticate_hint" msgid="798914151813205721">"kimlik doğrulaması yapın"</string>
diff --git a/packages/SystemUI/res/values-uk/strings.xml b/packages/SystemUI/res/values-uk/strings.xml
index 57b9d8a..028e2ad 100644
--- a/packages/SystemUI/res/values-uk/strings.xml
+++ b/packages/SystemUI/res/values-uk/strings.xml
@@ -1123,7 +1123,7 @@
<string name="media_output_dialog_group" msgid="5571251347877452212">"Група"</string>
<string name="media_output_dialog_single_device" msgid="3102758980643351058">"Вибрано 1 пристрій"</string>
<string name="media_output_dialog_multiple_devices" msgid="1093771040315422350">"Вибрано пристроїв: <xliff:g id="COUNT">%1$d</xliff:g>"</string>
- <string name="media_output_dialog_disconnected" msgid="1834473104836986046">"<xliff:g id="DEVICE_NAME">%1$s</xliff:g> (відключено)"</string>
+ <string name="media_output_dialog_disconnected" msgid="7090512852817111185">"(від’єднано)"</string>
<string name="media_output_dialog_connect_failed" msgid="3225190634236259010">"Не вдалося підключитися. Повторіть спробу."</string>
<string name="media_output_dialog_pairing_new" msgid="9099497976087485862">"Підключити новий пристрій"</string>
<string name="build_number_clip_data_label" msgid="3623176728412560914">"Номер складання"</string>
diff --git a/packages/SystemUI/res/values-ur/strings.xml b/packages/SystemUI/res/values-ur/strings.xml
index 788b162..3489001 100644
--- a/packages/SystemUI/res/values-ur/strings.xml
+++ b/packages/SystemUI/res/values-ur/strings.xml
@@ -1111,7 +1111,7 @@
<string name="media_output_dialog_group" msgid="5571251347877452212">"گروپ"</string>
<string name="media_output_dialog_single_device" msgid="3102758980643351058">"1 آلہ منتخب کیا گیا"</string>
<string name="media_output_dialog_multiple_devices" msgid="1093771040315422350">"<xliff:g id="COUNT">%1$d</xliff:g> آلات منتخب کیے گئے"</string>
- <string name="media_output_dialog_disconnected" msgid="1834473104836986046">"<xliff:g id="DEVICE_NAME">%1$s</xliff:g> (غیر منسلک ہو گیا)"</string>
+ <string name="media_output_dialog_disconnected" msgid="7090512852817111185">"(غیر منسلک ہے)"</string>
<string name="media_output_dialog_connect_failed" msgid="3225190634236259010">"منسلک نہیں ہو سکا۔ پھر کوشش کریں۔"</string>
<string name="media_output_dialog_pairing_new" msgid="9099497976087485862">"نئے آلہ کا جوڑا بنائیں"</string>
<string name="build_number_clip_data_label" msgid="3623176728412560914">"بلڈ نمبر"</string>
diff --git a/packages/SystemUI/res/values-uz/strings.xml b/packages/SystemUI/res/values-uz/strings.xml
index 1be13be..8f29c86 100644
--- a/packages/SystemUI/res/values-uz/strings.xml
+++ b/packages/SystemUI/res/values-uz/strings.xml
@@ -1111,7 +1111,7 @@
<string name="media_output_dialog_group" msgid="5571251347877452212">"Guruh"</string>
<string name="media_output_dialog_single_device" msgid="3102758980643351058">"1 ta qurilma tanlandi"</string>
<string name="media_output_dialog_multiple_devices" msgid="1093771040315422350">"<xliff:g id="COUNT">%1$d</xliff:g> ta qurilma tanlandi"</string>
- <string name="media_output_dialog_disconnected" msgid="1834473104836986046">"<xliff:g id="DEVICE_NAME">%1$s</xliff:g> (uzilgan)"</string>
+ <string name="media_output_dialog_disconnected" msgid="7090512852817111185">"(uzildi)"</string>
<string name="media_output_dialog_connect_failed" msgid="3225190634236259010">"Ulanmadi. Qayta urining."</string>
<string name="media_output_dialog_pairing_new" msgid="9099497976087485862">"Yangi qurilmani ulash"</string>
<string name="build_number_clip_data_label" msgid="3623176728412560914">"Nashr raqami"</string>
diff --git a/packages/SystemUI/res/values-vi/strings.xml b/packages/SystemUI/res/values-vi/strings.xml
index 2478ca4..4f258d2 100644
--- a/packages/SystemUI/res/values-vi/strings.xml
+++ b/packages/SystemUI/res/values-vi/strings.xml
@@ -1111,7 +1111,7 @@
<string name="media_output_dialog_group" msgid="5571251347877452212">"Nhóm"</string>
<string name="media_output_dialog_single_device" msgid="3102758980643351058">"Đã chọn 1 thiết bị"</string>
<string name="media_output_dialog_multiple_devices" msgid="1093771040315422350">"Đã chọn <xliff:g id="COUNT">%1$d</xliff:g> thiết bị"</string>
- <string name="media_output_dialog_disconnected" msgid="1834473104836986046">"<xliff:g id="DEVICE_NAME">%1$s</xliff:g> (đã ngắt kết nối)"</string>
+ <string name="media_output_dialog_disconnected" msgid="7090512852817111185">"(đã ngắt kết nối)"</string>
<string name="media_output_dialog_connect_failed" msgid="3225190634236259010">"Không thể kết nối. Hãy thử lại."</string>
<string name="media_output_dialog_pairing_new" msgid="9099497976087485862">"Ghép nối thiết bị mới"</string>
<string name="build_number_clip_data_label" msgid="3623176728412560914">"Số bản dựng"</string>
diff --git a/packages/SystemUI/res/values-zh-rCN/strings.xml b/packages/SystemUI/res/values-zh-rCN/strings.xml
index e6421a2..53ed610 100644
--- a/packages/SystemUI/res/values-zh-rCN/strings.xml
+++ b/packages/SystemUI/res/values-zh-rCN/strings.xml
@@ -1111,7 +1111,7 @@
<string name="media_output_dialog_group" msgid="5571251347877452212">"群组"</string>
<string name="media_output_dialog_single_device" msgid="3102758980643351058">"已选择 1 个设备"</string>
<string name="media_output_dialog_multiple_devices" msgid="1093771040315422350">"已选择 <xliff:g id="COUNT">%1$d</xliff:g> 个设备"</string>
- <string name="media_output_dialog_disconnected" msgid="1834473104836986046">"<xliff:g id="DEVICE_NAME">%1$s</xliff:g>(已断开连接)"</string>
+ <string name="media_output_dialog_disconnected" msgid="7090512852817111185">"(已断开连接)"</string>
<string name="media_output_dialog_connect_failed" msgid="3225190634236259010">"无法连接。请重试。"</string>
<string name="media_output_dialog_pairing_new" msgid="9099497976087485862">"与新设备配对"</string>
<string name="build_number_clip_data_label" msgid="3623176728412560914">"版本号"</string>
diff --git a/packages/SystemUI/res/values-zh-rHK/strings.xml b/packages/SystemUI/res/values-zh-rHK/strings.xml
index f94a46a..0012e76 100644
--- a/packages/SystemUI/res/values-zh-rHK/strings.xml
+++ b/packages/SystemUI/res/values-zh-rHK/strings.xml
@@ -1111,7 +1111,7 @@
<string name="media_output_dialog_group" msgid="5571251347877452212">"群組"</string>
<string name="media_output_dialog_single_device" msgid="3102758980643351058">"已選取 1 部裝置"</string>
<string name="media_output_dialog_multiple_devices" msgid="1093771040315422350">"已選取 <xliff:g id="COUNT">%1$d</xliff:g> 部裝置"</string>
- <string name="media_output_dialog_disconnected" msgid="1834473104836986046">"<xliff:g id="DEVICE_NAME">%1$s</xliff:g> (已中斷連線)"</string>
+ <string name="media_output_dialog_disconnected" msgid="7090512852817111185">"(已中斷連線)"</string>
<string name="media_output_dialog_connect_failed" msgid="3225190634236259010">"無法連線,請再試一次。"</string>
<string name="media_output_dialog_pairing_new" msgid="9099497976087485862">"配對新裝置"</string>
<string name="build_number_clip_data_label" msgid="3623176728412560914">"版本號碼"</string>
diff --git a/packages/SystemUI/res/values-zh-rTW/strings.xml b/packages/SystemUI/res/values-zh-rTW/strings.xml
index 48c6cda..d749abe 100644
--- a/packages/SystemUI/res/values-zh-rTW/strings.xml
+++ b/packages/SystemUI/res/values-zh-rTW/strings.xml
@@ -1111,7 +1111,7 @@
<string name="media_output_dialog_group" msgid="5571251347877452212">"群組"</string>
<string name="media_output_dialog_single_device" msgid="3102758980643351058">"已選取 1 部裝置"</string>
<string name="media_output_dialog_multiple_devices" msgid="1093771040315422350">"已選取 <xliff:g id="COUNT">%1$d</xliff:g> 部裝置"</string>
- <string name="media_output_dialog_disconnected" msgid="1834473104836986046">"<xliff:g id="DEVICE_NAME">%1$s</xliff:g> (已中斷連線)"</string>
+ <string name="media_output_dialog_disconnected" msgid="7090512852817111185">"(連線中斷)"</string>
<string name="media_output_dialog_connect_failed" msgid="3225190634236259010">"無法連線,請再試一次。"</string>
<string name="media_output_dialog_pairing_new" msgid="9099497976087485862">"配對新裝置"</string>
<string name="build_number_clip_data_label" msgid="3623176728412560914">"版本號碼"</string>
diff --git a/packages/SystemUI/res/values-zu/strings.xml b/packages/SystemUI/res/values-zu/strings.xml
index de88b05..ba07be3 100644
--- a/packages/SystemUI/res/values-zu/strings.xml
+++ b/packages/SystemUI/res/values-zu/strings.xml
@@ -1111,7 +1111,7 @@
<string name="media_output_dialog_group" msgid="5571251347877452212">"Iqembu"</string>
<string name="media_output_dialog_single_device" msgid="3102758980643351058">"idivayisi ekhethiwe e-1"</string>
<string name="media_output_dialog_multiple_devices" msgid="1093771040315422350">"amadivayisi akhethiwe angu-<xliff:g id="COUNT">%1$d</xliff:g>"</string>
- <string name="media_output_dialog_disconnected" msgid="1834473104836986046">"<xliff:g id="DEVICE_NAME">%1$s</xliff:g> (inqamukile)"</string>
+ <string name="media_output_dialog_disconnected" msgid="7090512852817111185">"(inqamukile)"</string>
<string name="media_output_dialog_connect_failed" msgid="3225190634236259010">"Ayikwazanga ukuxhumeka. Zama futhi."</string>
<string name="media_output_dialog_pairing_new" msgid="9099497976087485862">"Bhangqa idivayisi entsha"</string>
<string name="build_number_clip_data_label" msgid="3623176728412560914">"Yakha inombolo"</string>
diff --git a/packages/SystemUI/res/values/colors.xml b/packages/SystemUI/res/values/colors.xml
index 3cbbf97..d2ea789 100644
--- a/packages/SystemUI/res/values/colors.xml
+++ b/packages/SystemUI/res/values/colors.xml
@@ -18,22 +18,13 @@
-->
<resources xmlns:androidprv="http://schemas.android.com/apk/prv/res/android">
<drawable name="notification_number_text_color">#ffffffff</drawable>
- <drawable name="ticker_background_color">#ff1d1d1d</drawable>
<drawable name="system_bar_background">@color/system_bar_background_opaque</drawable>
<color name="system_bar_background_opaque">#ff000000</color>
<color name="system_bar_background_transparent">#00000000</color>
- <color name="notification_panel_solid_background">#ff000000</color>
- <drawable name="status_bar_notification_row_background_color">#ff090909</drawable>
- <color name="notification_list_shadow_top">#80000000</color>
- <drawable name="heads_up_notification_bg_pressed">#ff33B5E5</drawable>
- <color name="qs_batterymeter_frame_color">#FF404040</color>
<color name="qs_tile_divider">#29ffffff</color><!-- 16% white -->
- <color name="qs_subhead">#99FFFFFF</color><!-- 60% white -->
- <color name="qs_detail_button">@*android:color/quaternary_device_default_settings</color>
<color name="qs_detail_button_white">#B3FFFFFF</color><!-- 70% white -->
<color name="qs_detail_transition">#66FFFFFF</color>
<color name="status_bar_clock_color">#FFFFFFFF</color>
- <color name="qs_user_detail_icon_muted">#FFFFFFFF</color> <!-- not so muted after all -->
<color name="qs_tile_disabled_color">#9E9E9E</color> <!-- 38% black -->
<!-- The color of the background in the separated list of the Global Actions menu -->
@@ -42,16 +33,6 @@
<!-- The color of the background in the grid of the Global Actions menu -->
<color name="global_actions_grid_background">#F1F3F4</color>
- <!-- The color of the text in the Global Actions menu -->
- <color name="global_actions_text">@color/GM2_grey_700</color>
-
- <!-- The color of the text in the Global Actions menu -->
- <color name="global_actions_alert_text">@color/GM2_red_700</color>
-
- <!-- The color of the background of the emergency button when home controls are visible -->
- <color name="global_actions_emergency_background">@color/GM2_red_400</color>
- <color name="global_actions_emergency_text">@color/GM2_grey_100</color>
-
<!-- Colors for Power Menu Lite -->
<color name="global_actions_lite_background">#191C18</color>
<color name="global_actions_lite_button_background">#303030</color>
@@ -61,17 +42,9 @@
<color name="global_actions_shutdown_ui_text">@color/control_primary_text</color>
- <!-- Tint color for the content on the notification overflow card. -->
- <color name="keyguard_overflow_content_color">#ff686868</color>
-
- <color name="keyguard_affordance">#ffffffff</color>
-
<!-- Shadows under the clock, date and other keyguard text fields -->
<color name="keyguard_shadow_color">#B2000000</color>
- <!-- Color for the images in keyguard number pad buttons -->
- <color name="keyguard_keypad_image_color">?android:attr/textColorPrimaryInverse</color>
-
<!-- Color for rounded background for activated user in keyguard user switcher -->
<color name="kg_user_switcher_activated_background_color">#26000000</color>
<!-- Icon color for user avatars in keyguard user switcher -->
@@ -92,9 +65,6 @@
<!-- The color of the legacy notification background -->
<color name="notification_legacy_background_color">#ff1a1a1a</color>
- <!-- The color of the material notification background when dark -->
- <color name="notification_material_background_dark_color">#ff333333</color>
-
<!-- The color of the dividing line between grouped notifications. -->
<color name="notification_divider_color">@*android:color/background_device_default_light</color>
@@ -107,21 +77,14 @@
<!-- The color of the gear shown behind a notification -->
<color name="notification_gear_color">@color/GM2_grey_700</color>
- <!-- The color of the text inside a notification -->
- <color name="notification_primary_text_color">@*android:color/notification_primary_text_color_light</color>
-
-
<color name="notification_guts_link_icon_tint">@color/GM2_grey_700</color>
<color name="notification_guts_sub_text_color">@color/GM2_grey_700</color>
<color name="notification_guts_header_text_color">@color/GM2_grey_900</color>
- <color name="notification_silence_color">#FF32c1de</color>
- <color name="notification_alert_color">#FFF87B2B</color>
<color name="notification_guts_priority_button_content_color">@color/GM2_grey_700</color>
<color name="notification_guts_priority_button_bg_fill_color">@color/transparent</color>
<color name="notification_guts_priority_button_bg_fill_color_selected">#FFFFFF</color>
<color name="notification_guts_priority_button_bg_stroke_color">@color/GM2_grey_300</color>
- <color name="notification_section_header_label_color">@color/GM2_grey_900</color>
<color name="notification_section_clear_all_btn_color">@color/GM2_grey_700</color>
<color name="assist_orb_color">#ffffff</color>
@@ -139,8 +102,6 @@
<color name="screen_pinning_request_window_bg">#80000000</color>
- <color name="segmented_buttons_background">#14FFFFFF</color><!-- 8% white -->
-
<color name="dark_mode_icon_color_dual_tone_background">#3d000000</color>
<color name="dark_mode_icon_color_dual_tone_fill">#7a000000</color>
@@ -152,19 +113,7 @@
<!-- Chosen so fill over background matches single tone -->
<color name="dark_mode_qs_icon_color_dual_tone_fill">#99000000</color>
- <color name="docked_divider_handle">#ffffff</color>
- <drawable name="forced_resizable_background">#59000000</drawable>
- <color name="minimize_dock_shadow_start">#60000000</color>
- <color name="minimize_dock_shadow_end">#00000000</color>
-
- <color name="default_remote_input_background">@*android:color/notification_default_color</color>
<color name="notif_pill_text">@android:color/system_neutral1_900</color>
- <color name="remote_input_accent">?android:attr/colorAccent</color>
-
- <color name="quick_step_track_background_background_dark">#1F000000</color>
- <color name="quick_step_track_background_background_light">#33FFFFFF</color>
- <color name="quick_step_track_background_foreground_dark">#38000000</color>
- <color name="quick_step_track_background_foreground_light">#59FFFFFF</color>
<!-- Keyboard shortcuts colors -->
<color name="ksh_application_group_color">#fff44336</color>
@@ -192,47 +141,26 @@
<color name="udfps_enroll_progress">#ff669DF6</color> <!-- blue 400 -->
<color name="udfps_enroll_progress_help">#ffEE675C</color> <!-- red 400 -->
- <!-- Color for the Assistant invocation lights -->
- <color name="default_invocation_lights_color">#ffffffff</color> <!-- white -->
-
<!-- Global screenshot actions -->
<color name="screenshot_button_ripple">#1f000000</color>
<color name="screenshot_background_protection_start">#40000000</color> <!-- 25% black -->
<!-- GM2 colors -->
- <color name="GM2_grey_50">#F8F9FA</color>
<color name="GM2_grey_100">#F1F3F4</color>
<color name="GM2_grey_200">#E8EAED</color>
<color name="GM2_grey_300">#DADCE0</color>
- <color name="GM2_grey_400">#BDC1C6</color>
<color name="GM2_grey_500">#9AA0A6</color>
<color name="GM2_grey_600">#80868B</color>
- <color name="GM2_grey_650">#70757A</color>
<color name="GM2_grey_700">#5F6368</color>
<color name="GM2_grey_800">#3C4043</color>
<color name="GM2_grey_900">#202124</color>
- <color name="GM2_red_50">#FCE8E6</color>
- <color name="GM2_red_200">#F6AEA9</color>
<color name="GM2_red_300">#F28B82</color>
- <color name="GM2_red_400">#EE675C</color>
- <color name="GM2_red_500">#B71C1C</color>
<color name="GM2_red_700">#C5221F</color>
- <color name="GM2_blue_50">#E8F0FE</color>
- <color name="GM2_blue_200">#AECBFA</color>
<color name="GM2_blue_300">#8AB4F8</color>
- <color name="GM2_blue_500">#FF4285F4</color>
- <color name="GM2_blue_600">#1A73E8</color>
- <color name="GM2_blue_700">#1967D2</color>
- <color name="GM2_yellow_50">#FEF7E0</color>
<color name="GM2_yellow_200">#FDE293</color>
- <color name="GM2_yellow_500">#FFFBBC04</color>
-
- <color name="GM2_green_500">#FF34A853</color>
-
- <color name="GM2_orange_900">#B06000</color>
<!-- Window magnification colors -->
<color name="magnification_border_color">#FF9900</color>
@@ -244,7 +172,6 @@
<color name="volume_dialog_background_color_above_blur">@android:color/transparent</color>
<!-- media -->
- <color name="media_disabled">#80ffffff</color>
<color name="media_seamless_border">?android:attr/colorAccent</color>
<!-- controls -->
@@ -252,7 +179,6 @@
<color name="control_secondary_text">#99FFFFFF</color>
<color name="control_default_foreground">@color/GM2_grey_500</color>
<color name="control_default_background">@color/GM2_grey_900</color>
- <color name="control_list_popup_background">@*android:color/background_floating_material_dark</color>
<color name="control_spinner_dropdown">@*android:color/foreground_material_dark</color>
<color name="control_more_vert">@*android:color/foreground_material_dark</color>
<color name="control_enabled_light_background">#413C2D</color>
@@ -285,8 +211,6 @@
<!-- Internet Dialog -->
<!-- Material next state on color-->
<color name="settingslib_state_on_color">@color/settingslib_state_on</color>
- <!-- Material next state off color-->
- <color name="settingslib_state_off_color">@color/settingslib_state_off</color>
<!-- Material next track on color-->
<color name="settingslib_track_on_color">@color/settingslib_track_on</color>
<!-- Material next track off color-->
diff --git a/packages/SystemUI/res/values/config.xml b/packages/SystemUI/res/values/config.xml
index 2eaf098..9878e0d 100644
--- a/packages/SystemUI/res/values/config.xml
+++ b/packages/SystemUI/res/values/config.xml
@@ -20,14 +20,6 @@
<!-- These resources are around just to allow their values to be customized
for different hardware and product builds. -->
<resources>
- <!-- Whether to clip notification contents with a rounded rectangle. Might be expensive on
- certain GPU's and thus can be turned off with only minimal visual impact. -->
- <bool name="config_notifications_round_rect_clipping">true</bool>
-
- <!-- Component to be used as the status bar service. Must implement the IStatusBar
- interface. This name is in the ComponentName flattened format (package/class) -->
- <string name="config_statusBarComponent" translatable="false">com.android.systemui.statusbar.phone.StatusBar</string>
-
<!-- Component to be used as the recents implementation. Must implement the
RecentsImplementation interface. This name is in the ComponentName flattened format
(package/class) -->
@@ -45,31 +37,12 @@
<item>400</item>
</integer-array>
- <!-- How many icons may be shown at once in the system bar. Includes any
- slots that may be reused for things like IME control. -->
- <integer name="config_maxNotificationIcons">5</integer>
-
- <!-- Show phone (voice) signal strength instead of data in mobile RSSI. -->
- <bool name="config_showPhoneRSSIForData">false</bool>
-
- <!-- Show rotation lock toggle in System UI-->
- <bool name="config_showRotationLock">true</bool>
-
- <!-- Vibration duration for GlowPadView used in SearchPanelView -->
- <integer translatable="false" name="config_vibration_duration">0</integer>
-
- <!-- Vibration duration for GlowPadView used in SearchPanelView -->
- <integer translatable="false" name="config_search_panel_view_vibration_duration">20</integer>
-
<!-- Show mic or phone affordance on Keyguard -->
<bool name="config_keyguardShowLeftAffordance">false</bool>
<!-- Show camera affordance on Keyguard -->
<bool name="config_keyguardShowCameraAffordance">false</bool>
- <!-- The length of the vibration when the notification pops open. -->
- <integer name="one_finger_pop_duration_ms">10</integer>
-
<!-- decay duration (from size_max -> size), in ms -->
<integer name="navigation_bar_deadzone_hold">333</integer>
<integer name="navigation_bar_deadzone_decay">333</integer>
@@ -98,7 +71,6 @@
<integer name="quick_settings_max_rows">4</integer>
<!-- The number of columns that the top level tiles span in the QuickSettings -->
- <integer name="quick_settings_user_time_settings_tile_span">1</integer>
<!-- The default tiles to display in QuickSettings -->
<string name="quick_settings_tiles_default" translatable="false">
@@ -128,13 +100,6 @@
<item>accessibility_display_inversion_enabled:inversion</item>
</string-array>
- <!-- Whether or not the RSSI tile is capitalized or not. -->
- <bool name="quick_settings_rssi_tile_capitalization">true</bool>
-
- <!-- Timeouts for brightness dialog to disappear -->
- <integer name="quick_settings_brightness_dialog_short_timeout">2000</integer>
- <integer name="quick_settings_brightness_dialog_long_timeout">4000</integer>
-
<!-- Show indicator for Wifi on but not connected. -->
<bool name="config_showWifiIndicatorWhenEnabled">false</bool>
@@ -164,10 +129,6 @@
card. -->
<integer name="keyguard_max_notification_count">-1</integer>
- <!-- Defines the implementation of the velocity tracker to be used for the panel expansion. Can
- be 'platform' or 'noisy' (i.e. for noisy touch screens). -->
- <string name="velocity_tracker_impl" translatable="false">platform</string>
-
<!-- Doze: does this device support STATE_DOZE? -->
<bool name="doze_display_state_supported">false</bool>
@@ -206,9 +167,6 @@
low powered state yet. -->
<bool name="doze_long_press_uses_prox">true</bool>
- <!-- Doze: should notifications be used as a pulse signal? -->
- <bool name="doze_pulse_on_notifications">true</bool>
-
<!-- Doze: duration to avoid false pickup gestures triggered by notification vibrations -->
<integer name="doze_pickup_vibration_threshold">2000</integer>
@@ -311,18 +269,9 @@
<!-- Doze: whether the double tap sensor reports 2D touch coordinates -->
<bool name="doze_double_tap_reports_touch_coordinates">false</bool>
- <!-- Hotspot tile: number of days to show after feature is used. -->
- <integer name="days_to_show_hotspot_tile">30</integer>
-
- <!-- Color inversion tile: number of days to show after feature is used. -->
- <integer name="days_to_show_color_inversion_tile">7</integer>
-
<!-- Number of times to show the strong alarm warning text in the volume dialog -->
<integer name="zen_mode_alarm_warning_threshold">5</integer>
- <!-- Maximum number of total conditions to display in the zen mode selection panel -->
- <integer name="zen_mode_max_conditions">5</integer>
-
<!-- Enable the default volume dialog -->
<bool name="enable_volume_ui">true</bool>
@@ -332,12 +281,6 @@
<!-- Whether to show operator name in the status bar -->
<bool name="config_showOperatorNameInStatusBar">false</bool>
- <!-- Duration of the full carrier network change icon animation. -->
- <integer name="carrier_network_change_anim_time">3000</integer>
-
- <!-- Duration of the expansion animation in the volume dialog -->
- <item name="volume_expand_animation_duration" type="integer">300</item>
-
<!-- Whether to show the full screen user switcher. -->
<bool name="config_enableFullscreenUserSwitcher">false</bool>
@@ -395,19 +338,12 @@
<string name="config_navBarLayoutQuickstep" translatable="false">back[1.7WC];home;contextual[1.7WC]</string>
<string name="config_navBarLayoutHandle" translatable="false">back[70AC];home_handle;ime_switcher[70AC]</string>
- <bool name="quick_settings_show_full_alarm">false</bool>
-
<!-- Whether to show a warning notification when device's skin temperature is high. -->
<integer name="config_showTemperatureWarning">0</integer>
<!-- Whether to show a alarm dialog when device's usb port is overheating. -->
<integer name="config_showUsbPortAlarm">0</integer>
- <!-- Accessibility actions -->
- <item type="id" name="action_split_task_to_left" />
- <item type="id" name="action_split_task_to_right" />
- <item type="id" name="action_split_task_to_top" />
-
<item type="id" name="action_toggle_overview"/>
<!-- Whether or not to show notifications to the user. If disabled, SystemUI will still be
@@ -486,11 +422,6 @@
<!-- Notifications are sized to match the width of two (of 4) qs tiles in landscape. -->
<bool name="config_skinnyNotifsInLandscape">true</bool>
- <!-- If true, enable the advance anti-falsing classifier on the lockscreen. On some devices it
- does not work well, particularly with noisy touchscreens. Note that disabling it may
- increase the rate of unintentional unlocks. -->
- <bool name="config_lockscreenAntiFalsingClassifierEnabled">true</bool>
-
<!-- Snooze: default notificaiton snooze time. -->
<integer name="config_notification_snooze_time_default">60</integer>
@@ -547,8 +478,6 @@
<item>com.android.systemui</item>
</string-array>
- <integer name="ongoing_appops_dialog_max_apps">5</integer>
-
<!-- Launcher package name for overlaying icons. -->
<string name="launcher_overlayable_package" translatable="false">com.android.launcher3</string>
@@ -568,9 +497,6 @@
<!-- Preferred max refresh rate at keyguard, if supported by the display. -->
<integer name="config_keyguardMaxRefreshRate">-1</integer>
- <!-- Whether or not to add a "people" notifications section -->
- <bool name="config_usePeopleFiltering">false</bool>
-
<!-- Defines system icons to be excluded from the display. That is to say, the icons in the
status bar that are part of this list are never displayed. Each item in the list must be a
string defined in core/res/res/config.xml to properly exclude the icon.
@@ -617,8 +543,6 @@
<!-- Max number of columns for quick controls area -->
<integer name="controls_max_columns">2</integer>
- <!-- Max number of columns for power menu -->
- <integer name="power_menu_max_columns">3</integer>
<!-- Max number of columns for power menu lite -->
<integer name="power_menu_lite_max_columns">2</integer>
<!-- Max number of rows for power menu lite -->
@@ -647,9 +571,6 @@
<!-- content URL in a notification when ACTION_BATTERY_CHANGED.EXTRA_PRESENT field is false -->
<string translatable="false" name="config_batteryStateUnknownUrl"></string>
- <!-- Whether wallet view is shown in landscape / seascape orientations -->
- <bool name="global_actions_show_landscape_wallet_view">false</bool>
-
<!-- Package name of the preferred system app to perform eSOS action -->
<string name="config_preferredEmergencySosPackage" translatable="false"></string>
diff --git a/packages/SystemUI/res/values/dimens.xml b/packages/SystemUI/res/values/dimens.xml
index a108b42..150bd7c 100644
--- a/packages/SystemUI/res/values/dimens.xml
+++ b/packages/SystemUI/res/values/dimens.xml
@@ -21,15 +21,8 @@
<dimen name="remote_input_view_text_stroke">2dp</dimen>
- <!-- Amount to offset bottom of notification peek window from top of status bar. -->
- <dimen name="peek_window_y_offset">-12dp</dimen>
-
<!-- thickness (height) of the navigation bar on phones that require it -->
<dimen name="navigation_bar_size">@*android:dimen/navigation_bar_height</dimen>
- <!-- Minimum swipe distance to catch the swipe gestures to invoke assist or switch tasks. -->
- <dimen name="navigation_bar_min_swipe_distance">48dp</dimen>
- <dimen name="navigation_bar_default_edge_height">500dp</dimen>
-
<!-- thickness (height) of the dead zone at the top of the navigation bar,
reducing false presses on navbar buttons; approx 2mm -->
<dimen name="navigation_bar_deadzone_size">12dp</dimen>
@@ -39,7 +32,6 @@
<!-- dimensions for the navigation bar handle -->
<dimen name="navigation_handle_radius">1dp</dimen>
<dimen name="navigation_handle_bottom">6dp</dimen>
- <dimen name="navigation_handle_horizontal_margin">30dp</dimen>
<dimen name="navigation_handle_sample_horizontal_margin">10dp</dimen>
<dimen name="navigation_home_handle_width">72dp</dimen>
@@ -56,11 +48,6 @@
<!-- The amount by which the arrow is shifted to avoid the finger-->
<dimen name="navigation_edge_finger_offset">48dp</dimen>
- <dimen name="floating_rotation_button_diameter">40dp</dimen>
- <dimen name="floating_rotation_button_min_margin">20dp</dimen>
- <dimen name="floating_rotation_button_taskbar_left_margin">20dp</dimen>
- <dimen name="floating_rotation_button_taskbar_bottom_margin">10dp</dimen>
-
<!-- Height of notification icons in the status bar -->
<dimen name="status_bar_icon_size">@*android:dimen/status_bar_icon_size</dimen>
@@ -108,9 +95,6 @@
<dimen name="group_overflow_number_padding">@*android:dimen/notification_content_margin_end
</dimen>
- <!-- max height of a notification such that the content can still fade out when closing -->
- <dimen name="max_notification_fadeout_height">100dp</dimen>
-
<!-- End margin for the RSSI status icon of a device connected via bluetooth. -->
<dimen name="status_bar_connected_device_signal_margin_end">16dp</dimen>
@@ -187,10 +171,6 @@
<!-- the padding of the shelf icon container -->
<dimen name="shelf_icon_container_padding">13dp</dimen>
- <!-- The padding of a notification icon on top to the start of the notification. Used for custom
- views where the distance can't be measured -->
- <dimen name="notification_icon_appear_padding">15dp</dimen>
-
<!-- Vertical translation of the shelf during animation that happens after the
notification panel collapses -->
<dimen name="shelf_appear_translation">42dp</dimen>
@@ -227,48 +207,14 @@
<!-- Extra horizontal space for properly aligning guts buttons with the notification content -->
<dimen name="notification_guts_button_side_margin">8dp</dimen>
-
- <!-- The vertical padding a notification guts button has to fulfill the 48dp touch target -->
- <dimen name="notification_guts_button_vertical_padding">14dp</dimen>
-
- <!-- The horizontal padding for notification guts buttons-->
- <dimen name="notification_guts_button_horizontal_padding">8dp</dimen>
-
- <!-- The horizontal space around the buttons in the inline settings -->
- <dimen name="notification_guts_button_horizontal_spacing">8dp</dimen>
-
- <dimen name="notification_guts_conversation_header_height">84dp</dimen>
<dimen name="notification_guts_conversation_icon_size">56dp</dimen>
- <dimen name="notification_guts_conversation_action_height">56dp</dimen>
- <dimen name="notification_guts_conversation_action_text_padding_start">32dp</dimen>
- <dimen name="conversation_onboarding_bullet_gap_width">6dp</dimen>
-
<dimen name="notification_guts_header_top_padding">12dp</dimen>
-
- <!-- The height of the header in inline settings -->
- <dimen name="notification_guts_header_height">24dp</dimen>
-
- <!-- The text size of the header in inline settings -->
- <dimen name="notification_guts_header_text_size">16sp</dimen>
-
- <!-- The horizontal space between items in the alert selections in the inline settings -->
- <dimen name="notification_guts_option_horizontal_padding">15dp</dimen>
-
<!-- The vertical space between items in the alert selections in the inline settings -->
<dimen name="notification_guts_option_vertical_padding">16dp</dimen>
- <!-- The vertical space between the alert selections in the inline settings -->
- <dimen name="notification_guts_option_vertical_margin">6dp</dimen>
-
<dimen name="notification_importance_toggle_size">48dp</dimen>
- <dimen name="notification_importance_toggle_marginTop">28dp</dimen>
- <dimen name="notification_importance_toggle_marginBottom">28dp</dimen>
- <dimen name="notification_importance_text_marginTop">20dp</dimen>
<dimen name="notification_importance_button_separation">8dp</dimen>
- <dimen name="notification_importance_button_width">178dp</dimen>
- <dimen name="notification_importance_button_horiz_padding">28dp</dimen>
<dimen name="notification_importance_drawable_padding">8dp</dimen>
- <dimen name="notification_importance_description_padding">20dp</dimen>
<dimen name="notification_importance_header_text">12sp</dimen>
<dimen name="notification_importance_description_text">14sp</dimen>
<dimen name="notification_importance_channel_text">16sp</dimen>
@@ -281,12 +227,6 @@
<!-- The minimum height for the snackbar shown after the snooze option has been chosen. -->
<dimen name="snooze_snackbar_min_height">56dp</dimen>
- <!-- The text size of options in the snooze menu. -->
- <dimen name="snooze_option_text_size">14sp</dimen>
-
- <!-- The padding around options int the snooze menu. -->
- <dimen name="snooze_option_padding">8dp</dimen>
-
<!-- size at which Notification icons will be drawn in the status bar -->
<dimen name="status_bar_icon_drawing_size">15dp</dimen>
@@ -295,9 +235,6 @@
@*android:dimen/notification_header_icon_size_ambient
</dimen>
- <!-- size of notification icons when the notifications are hidden -->
- <dimen name="hidden_shelf_icon_size">16dp</dimen>
-
<!-- opacity at which Notification icons will be drawn in the status bar -->
<item type="dimen" name="status_bar_icon_drawing_alpha">90%</item>
@@ -360,40 +297,19 @@
<dimen name="navigation_key_padding">0dp</dimen>
- <!-- The width of the view containing the menu/ime navigation bar icons -->
- <dimen name="navigation_extra_key_width">36dp</dimen>
-
<!-- The padding on the side of the navigation bar. Must be greater than or equal to
navigation_extra_key_width -->
<dimen name="navigation_side_padding">36dp</dimen>
- <!-- Default distance beyond which snaps to the matching target -->
- <dimen name="navbar_search_snap_margin">40dip</dimen>
-
- <!-- Diameter of outer shape drawable shown in navbar search-->
- <dimen name="navbar_search_outerring_diameter">340dp</dimen>
-
- <!-- Diameter of outer shape drawable shown in navbar search. Should be 1/2 of above value -->
- <dimen name="navbar_search_outerring_radius">170dp</dimen>
-
- <!-- Height of search panel including navigation bar height -->
- <dimen name="navbar_search_panel_height">230dip</dimen>
-
<!-- Move the back button drawable for 3 button layout upwards in ime mode and in portrait -->
<dimen name="navbar_back_button_ime_offset">2dp</dimen>
- <!-- Height of the draggable handle at the bottom of the phone notification panel -->
- <dimen name="close_handle_height">36dp</dimen>
-
<!-- Amount of close_handle that will NOT overlap the notification list -->
<dimen name="close_handle_underlap">32dp</dimen>
<!-- Height of the status bar header bar in the car setting. -->
<dimen name="car_status_bar_header_height">128dp</dimen>
- <!-- The bottom padding of the status bar header. -->
- <dimen name="status_bar_header_padding_bottom">48dp</dimen>
-
<!-- The height of the container that holds the battery and time in the quick settings header.
Preferred over using "@*android:dimen/quick_qs_offset_height" as system icons are not always
present in quick settings (e.g. in split shade) and it's useful to be able to override this
@@ -401,9 +317,6 @@
-->
<dimen name="qs_header_system_icons_area_height">@*android:dimen/quick_qs_offset_height</dimen>
- <!-- How far the quick-quick settings panel extends below the status bar -->
- <dimen name="qs_quick_header_panel_height">128dp</dimen>
-
<!-- The height of the container that holds the system icons in the quick settings header in the
car setting. -->
<dimen name="car_qs_header_system_icons_area_height">54dp</dimen>
@@ -428,26 +341,17 @@
<!-- 3/4 of icon width 20dpx20dp -->
<dimen name="qs_footer_tuner_icon_translation">15dp</dimen>
- <!-- The padding between the notifications and the quick settings container -->
- <dimen name="qs_notification_padding">@dimen/notification_side_paddings</dimen>
-
<!-- In split shade mode notifications should be aligned to QS header so the value should be
adjusted to qs header height and height of centered content inside of it:
(quick_qs_offset_height (60dp) - ongoing_appops_chip_height (24dp) ) / 2 -->
<dimen name="notifications_top_padding_split_shade">18dp</dimen>
- <!-- Height of the status bar header bar when expanded -->
- <dimen name="status_bar_header_height_expanded">124dp</dimen>
-
<!-- Height of the status bar header bar when on Keyguard -->
<dimen name="status_bar_header_height_keyguard">40dp</dimen>
<!-- Margin start of the system icons super container -->
<dimen name="system_icons_super_container_margin_start">16dp</dimen>
- <!-- Margin end of the system icons super container when the avatar is missing. -->
- <dimen name="system_icons_super_container_avatarless_margin_end">6dp</dimen>
-
<!-- Width for the notification panel and related windows -->
<dimen name="match_parent">-1px</dimen>
@@ -484,8 +388,6 @@
<dimen name="volume_dialog_slider_corner_radius">21dp</dimen>
- <dimen name="volume_dialog_slider_height">116dp</dimen>
-
<!-- (volume_dialog_panel_width - rounded_slider_icon_size) / 2 -->
<dimen name="volume_slider_icon_inset">11dp</dimen>
@@ -503,10 +405,6 @@
<dimen name="volume_dialog_spacer">4dp</dimen>
- <dimen name="volume_dialog_slider_margin_top">14dp</dimen>
-
- <dimen name="volume_dialog_slider_margin_bottom">-2dp</dimen>
-
<dimen name="volume_dialog_row_margin_bottom">8dp</dimen>
<dimen name="volume_dialog_elevation">9dp</dimen>
@@ -515,8 +413,6 @@
<dimen name="volume_tool_tip_right_margin">76dp</dimen>
- <dimen name="volume_tool_tip_bottom_margin">32dp</dimen>
-
<dimen name="volume_tool_tip_arrow_corner_radius">2dp</dimen>
<!-- Size of each item in the ringer selector drawer. -->
@@ -532,29 +428,14 @@
<!-- Padding for the lock icon on the keyguard. In pixels - should not scale with display size. -->
<dimen name="lock_icon_padding">48px</dimen>
- <!-- Height of the carrier/wifi name label -->
- <dimen name="carrier_label_height">24dp</dimen>
-
- <!-- The distance you can pull a notification before it pops open -->
- <dimen name="one_finger_pop_limit">0dp</dimen>
-
- <!-- Minimum fraction of the screen that should be taken up by the notification panel.
- Not used at this screen size. -->
- <item type="dimen" name="notification_panel_min_height_frac">0%</item>
-
- <dimen name="blinds_pop_threshold">0dp</dimen>
-
<!-- The size of the gesture span needed to activate the "pull" notification expansion -->
<dimen name="pull_span_min">25dp</dimen>
<dimen name="qs_corner_radius">28dp</dimen>
<dimen name="qs_tile_height">84dp</dimen>
- <!--notification_side_paddings + notification_content_margin_start - (qs_quick_tile_size - qs_tile_background_size) / 2 -->
- <dimen name="qs_tile_layout_margin_side">18dp</dimen>
<dimen name="qs_tile_margin_horizontal">8dp</dimen>
<dimen name="qs_tile_margin_vertical">@dimen/qs_tile_margin_horizontal</dimen>
<dimen name="qs_tile_margin_top_bottom">4dp</dimen>
- <dimen name="qs_tile_margin_top_bottom_negative">-4dp</dimen>
<dimen name="qs_brightness_margin_top">8dp</dimen>
<dimen name="qs_brightness_margin_bottom">24dp</dimen>
<dimen name="qqs_layout_margin_top">16dp</dimen>
@@ -564,8 +445,6 @@
-->
<dimen name="qs_customize_header_min_height">68dp</dimen>
<dimen name="qs_customize_internal_side_paddings">8dp</dimen>
- <dimen name="qs_tile_icon_background_stroke_width">-1dp</dimen>
- <dimen name="qs_tile_background_size">56dp</dimen>
<dimen name="qs_icon_size">20dp</dimen>
<dimen name="qs_side_view_size">28dp</dimen>
<dimen name="qs_label_container_margin">10dp</dimen>
@@ -573,8 +452,6 @@
<dimen name="qs_tile_padding">12dp</dimen>
<dimen name="qs_tile_start_padding">16dp</dimen>
<dimen name="qs_drawable_end_margin">4dp</dimen>
- <dimen name="qs_header_gear_translation">16dp</dimen>
- <dimen name="qs_header_tile_margin_bottom">18dp</dimen>
<dimen name="qs_page_indicator_width">16dp</dimen>
<dimen name="qs_page_indicator_height">8dp</dimen>
<!-- The size of a single dot in relation to the whole animation.
@@ -582,18 +459,10 @@
-->
<dimen name="qs_page_indicator_dot_width">6.4dp</dimen>
<dimen name="qs_tile_text_size">14sp</dimen>
- <dimen name="qs_tile_divider_height">1dp</dimen>
<dimen name="qs_panel_padding">16dp</dimen>
- <dimen name="qs_dual_tile_height">112dp</dimen>
- <dimen name="qs_dual_tile_padding_vertical">8dp</dimen>
<dimen name="qs_dual_tile_padding_horizontal">6dp</dimen>
- <dimen name="qs_tile_padding_top">14dp</dimen>
- <dimen name="qs_tile_padding_top_large_text">4dp</dimen>
- <dimen name="qs_tile_padding_bottom">16dp</dimen>
- <dimen name="qs_tile_spacing">4dp</dimen>
<dimen name="qs_panel_padding_bottom">0dp</dimen>
<dimen name="qs_panel_padding_top">48dp</dimen>
- <dimen name="qs_detail_header_height">56dp</dimen>
<dimen name="qs_detail_header_padding">0dp</dimen>
<dimen name="qs_detail_image_width">56dp</dimen>
<dimen name="qs_detail_image_height">56dp</dimen>
@@ -605,27 +474,19 @@
<dimen name="qs_detail_item_secondary_text_size">14sp</dimen>
<dimen name="qs_detail_empty_text_size">14sp</dimen>
<dimen name="qs_detail_header_margin_top">28dp</dimen>
- <dimen name="qs_detail_back_margin_end">16dp</dimen>
<dimen name="qs_detail_header_text_padding">16dp</dimen>
<dimen name="qs_data_usage_text_size">14sp</dimen>
<dimen name="qs_data_usage_usage_text_size">36sp</dimen>
- <dimen name="qs_battery_padding">2dp</dimen>
<dimen name="qs_detail_padding_start">16dp</dimen>
<dimen name="qs_detail_items_padding_top">4dp</dimen>
<dimen name="qs_detail_item_icon_size">24dp</dimen>
<dimen name="qs_detail_item_icon_width">32dp</dimen>
<dimen name="qs_detail_item_icon_marginStart">0dp</dimen>
<dimen name="qs_detail_item_icon_marginEnd">20dp</dimen>
- <dimen name="qs_header_alarm_icon_size">@dimen/status_bar_icon_drawing_size</dimen>
<dimen name="qs_header_mobile_icon_size">@dimen/status_bar_icon_drawing_size</dimen>
- <dimen name="qs_header_alarm_text_margin_start">6dp</dimen>
- <dimen name="qs_header_separator_width">8dp</dimen>
<dimen name="qs_header_carrier_separator_width">6dp</dimen>
- <dimen name="qs_status_separator">32dp</dimen>
<dimen name="qs_carrier_margin_width">4dp</dimen>
<dimen name="qs_footer_icon_size">20dp</dimen>
- <dimen name="qs_header_top_padding">15dp</dimen>
- <dimen name="qs_header_bottom_padding">14dp</dimen>
<dimen name="qs_header_row_min_height">48dp</dimen>
<dimen name="qs_footer_padding">20dp</dimen>
@@ -635,8 +496,6 @@
<dimen name="qs_security_footer_background_inset">0dp</dimen>
<dimen name="qs_security_footer_corner_radius">28dp</dimen>
- <dimen name="qs_notif_collapsed_space">64dp</dimen>
-
<!-- Desired qs icon overlay size. -->
<dimen name="qs_detail_icon_overlay_size">24dp</dimen>
@@ -648,24 +507,11 @@
<!-- How far the expanded QS panel peeks from the header in collapsed state. -->
<dimen name="qs_peek_height">0dp</dimen>
- <!-- How large the icons in the quick settings footer dialog are -->
- <dimen name="qs_footer_dialog_icon_size">24sp</dimen>
- <!-- Left and right margin of the icons -->
- <dimen name="qs_footer_dialog_icon_margin">8sp</dimen>
<!-- Padding between subtitles and the following text in the QSFooter dialog -->
<dimen name="qs_footer_dialog_subtitle_padding">20dp</dimen>
<dimen name="qs_detail_margin_top">@*android:dimen/quick_qs_offset_height</dimen>
- <dimen name="seek_bar_height">3dp</dimen>
- <dimen name="seek_bar_corner_radius">3dp</dimen>
-
- <!-- Zen mode panel: condition item button padding -->
- <dimen name="zen_mode_condition_detail_button_padding">8dp</dimen>
-
- <!-- Zen mode panel: spacing between condition items -->
- <dimen name="zen_mode_condition_detail_item_spacing">12dp</dimen>
-
<!-- Zen mode panel: spacing between two-line condition upper and lower lines -->
<dimen name="zen_mode_condition_detail_item_interline_spacing">4dp</dimen>
@@ -675,12 +521,6 @@
<!-- used by DessertCase -->
<dimen name="dessert_case_cell_size">192dp</dimen>
- <!-- Default glow radius for GlowPadView -->
- <dimen name="glowpadview_glow_radius">75dip</dimen>
-
- <!-- Default distance from each snap target that GlowPadView considers a "hit" -->
- <dimen name="glowpadview_inner_radius">15dip</dimen>
-
<!-- Z distance between notifications if they are in the stack -->
<dimen name="z_distance_between_notifications">0.5dp</dimen>
@@ -708,9 +548,6 @@
@*android:dimen/notification_content_margin_top
</dimen>
- <!-- The height of a notification header -->
- <dimen name="notification_header_height">@*android:dimen/notification_header_height</dimen>
-
<!-- The height of the gap between adjacent notification sections. -->
<dimen name="notification_section_divider_height">@dimen/notification_side_paddings</dimen>
@@ -729,9 +566,6 @@
<!-- The minimum amount of top overscroll to go to the quick settings. -->
<dimen name="min_top_overscroll_to_qs">36dp</dimen>
- <!-- The height of the speed bump view. -->
- <dimen name="speed_bump_height">16dp</dimen>
-
<!-- Lockscreen unlocking falsing threshold. -->
<dimen name="unlock_falsing_threshold">80dp</dimen>
@@ -760,7 +594,6 @@
<!-- Burmese line spacing multiplier between hours and minutes of the keyguard clock -->
<item name="keyguard_clock_line_spacing_scale_burmese" type="dimen" format="float">1</item>
- <item name="scrim_behind_alpha" format="float" type="dimen">0.62</item>
<dimen name="notification_scrim_corner_radius">32dp</dimen>
<!-- The minimum amount the user needs to swipe to go to the camera / phone. -->
@@ -778,61 +611,23 @@
<!-- Distance between notifications and header when they are considered to be colliding. -->
<dimen name="header_notifications_collide_distance">48dp</dimen>
- <!-- Distance the user needs to drag vertically such that a swipe is accepted to unlock the
- device. -->
- <dimen name="unlock_move_distance">75dp</dimen>
-
<!-- Move distance for the unlock hint animation on the lockscreen -->
<dimen name="hint_move_distance">75dp</dimen>
<!-- The overshoot amount when the panel flings open -->
<dimen name="panel_overshoot_amount">16dp</dimen>
- <!-- The width of the region on the left/right edge of the screen for performing the camera/
- phone hints. -->
- <dimen name="edge_tap_area_width">48dp</dimen>
-
<!-- The padding between notification children when collapsed -->
<dimen name="notification_children_padding">4dp</dimen>
<!-- The padding on top of the first notification to the children container -->
<dimen name="notification_children_container_top_padding">8dp</dimen>
- <!-- end margin for multi user switch in expanded quick settings -->
- <dimen name="multi_user_switch_expanded_margin">8dp</dimen>
-
- <!-- end margin for multi user switch in collapsed quick settings -->
- <dimen name="multi_user_switch_collapsed_margin">13dp</dimen>
-
- <!-- end margin for multi user switch in collapsed quick settings -->
- <dimen name="multi_user_switch_keyguard_margin">3dp</dimen>
-
<!-- end margin for system icons if multi user switch is hidden -->
<dimen name="system_icons_switcher_hidden_expanded_margin">16dp</dimen>
<dimen name="data_usage_graph_marker_width">4dp</dimen>
- <!-- The padding bottom of the clock group when QS is expanded. -->
- <dimen name="clock_expanded_bottom_margin">20dp</dimen>
-
- <!-- The padding bottom of the clock group when QS is collapsed. -->
- <dimen name="clock_collapsed_bottom_margin">10dp</dimen>
-
- <!-- The padding bottom of the clock group when QS is collapsed for large text -->
- <dimen name="clock_collapsed_bottom_margin_large_text">6dp</dimen>
-
- <!-- The width of the multi user switch on keyguard and collapsed QS header. -->
- <dimen name="multi_user_switch_width_collapsed">34dp</dimen>
-
- <!-- The width of the multi user switch in expanded QS header. -->
- <dimen name="multi_user_switch_width_expanded">48dp</dimen>
-
- <!-- The width of user avatar when on Keyguard -->
- <dimen name="multi_user_switch_width_keyguard">34dp</dimen>
-
- <!-- The width of user avatar when collapsed -->
- <dimen name="multi_user_avatar_collapsed_size">22dp</dimen>
-
<!-- The width of user avatar when on Keyguard -->
<dimen name="multi_user_avatar_keyguard_size">22dp</dimen>
@@ -848,19 +643,10 @@
<!-- The font size of the "emergency calls only" label in QS -->
<dimen name="qs_emergency_calls_only_text_size">12sp</dimen>
- <!-- The font size of the date in QS -->
- <dimen name="qs_date_collapsed_size">14sp</dimen>
- <!-- Amount the date/time move when emergency calls only is present -->
- <dimen name="qs_date_time_translation">8dp</dimen>
-
<!-- Padding before battery level text in status bar, QS, and Keyguard -->
<dimen name="battery_level_padding_start">4dp</dimen>
- <!-- The top padding of the clear all button -->
- <dimen name="clear_all_padding_top">12dp</dimen>
-
<dimen name="notification_section_header_height">48dp</dimen>
- <dimen name="notification_section_header_padding_left">16dp</dimen>
<!-- Largest size an avatar might need to be drawn in the user picker, status bar, or
quick settings header -->
@@ -874,15 +660,6 @@
<!-- Margin on the left side of the carrier text on Keyguard -->
<dimen name="keyguard_carrier_text_margin">16dp</dimen>
- <!-- Margin on the left side of the battery % in the header. -->
- <dimen name="header_battery_margin_expanded">6dp</dimen>
-
- <!-- Margin on the left side of the battery % when on Keyguard. -->
- <dimen name="header_battery_margin_keyguard">6dp</dimen>
-
- <!-- Margin on the right side of the system icon group on Keyguard. -->
- <dimen name="system_icons_keyguard_padding_end">4dp</dimen>
-
<!-- Additional translation (downwards) for appearing notifications when going to the full shade
from Keyguard. -->
<dimen name="go_to_full_shade_appearing_translation">200dp</dimen>
@@ -922,49 +699,20 @@
<!-- The width/height of the unlock icon view on keyguard. -->
<dimen name="keyguard_lock_height">42dp</dimen>
- <dimen name="keyguard_lock_width">42dp</dimen>
<dimen name="keyguard_lock_padding">20dp</dimen>
<dimen name="keyguard_indication_margin_bottom">32dp</dimen>
<dimen name="lock_icon_margin_bottom">98dp</dimen>
- <!-- The text size for battery level -->
- <dimen name="battery_level_text_size">12sp</dimen>
-
- <!-- TrustDrawable: Minimum inner radius of the breathing animation -->
- <dimen name="trust_circle_inner_radius_visible_min">22dp</dimen>
- <!-- TrustDrawable: Maximum inner radius of the breathing animation -->
- <dimen name="trust_circle_inner_radius_visible_max">24dp</dimen>
- <!-- TrustDrawable: Inner radius at the end of the exit animation -->
- <dimen name="trust_circle_inner_radius_exit">38dp</dimen>
- <!-- TrustDrawable: Inner radius at the beginning of the enter animation -->
- <dimen name="trust_circle_inner_radius_enter">18dp</dimen>
- <!-- TrustDrawable: Thickness of the circle -->
- <dimen name="trust_circle_thickness">2dp</dimen>
-
<!-- How much two taps can be apart to still be recognized as a double tap on the lockscreen -->
<dimen name="double_tap_slop">32dp</dimen>
<dimen name="battery_margin_bottom">0dp</dimen>
- <!-- Padding at the end of the view that displays the mobile signal icons. If the view is
- empty, then this padding will not be added to that view. -->
- <dimen name="mobile_signal_group_end_padding">0dp</dimen>
-
- <!-- Padding between the mobile data type and the strength indicator. -->
- <dimen name="mobile_data_icon_start_padding">0dp</dimen>
-
- <!-- Extra padding between the mobile data type icon and the strength indicator when the data
- type icon is wide. -->
- <dimen name="wide_type_icon_start_padding">2dp</dimen>
-
<!-- Padding between the mobile signal indicator and the start icon when the roaming icon
is displayed in the upper left corner. -->
<dimen name="roaming_icon_start_padding">2dp</dimen>
- <!-- Extra padding between multiple phone signal icons. -->
- <dimen name="secondary_telephony_padding">2dp</dimen>
-
<!-- Extra padding between the mobile data type icon and the strength indicator when the data
type icon is wide for the tile in quick settings. -->
<dimen name="wide_type_icon_start_padding_qs">3dp</dimen>
@@ -974,21 +722,11 @@
<!-- The maximum width of the navigation bar ripples. -->
<dimen name="key_button_ripple_max_width">95dp</dimen>
- <!-- Inset shadow for FakeShadowDrawable. It is used to avoid gaps between the card
- and the shadow. -->
- <dimen name="fake_shadow_inset">1dp</dimen>
-
- <dimen name="fake_shadow_size">8dp</dimen>
-
<!-- Starting margin before the signal cluster -->
- <dimen name="signal_cluster_margin_start">2.5dp</dimen>
<!-- Padding between signal cluster and battery icon -->
<dimen name="signal_cluster_battery_padding">6dp</dimen>
- <!-- Padding for signal cluster and battery icon when there are not icons in signal cluster -->
- <dimen name="no_signal_cluster_battery_padding">3dp</dimen>
-
<!-- Screen pinning request width -->
<dimen name="screen_pinning_request_width">@dimen/match_parent</dimen>
<!-- Screen pinning request nav button circle heights -->
@@ -1019,36 +757,10 @@
<!-- Screen pinning description bullet gap width -->
<dimen name="screen_pinning_description_bullet_gap_width">6sp</dimen>
- <!-- Padding to be used on the bottom of the fingerprint icon on Keyguard so it better aligns
- with the other icons. -->
- <dimen name="fingerprint_icon_additional_padding">4dp</dimen>
-
<!-- Minimum margin of the notification panel on the side, when being positioned dynamically -->
<dimen name="notification_panel_min_side_margin">48dp</dimen>
- <!-- Vertical spacing between multiple volume slider rows -->
- <dimen name="volume_slider_interspacing">8dp</dimen>
-
- <!-- Volume dialog vertical offset from the top of the screen -->
- <dimen name="volume_offset_top">0dp</dimen>
-
- <!-- Standard image button size for volume dialog buttons -->
- <dimen name="volume_button_size">48dp</dimen>
-
- <!-- Volume dialog root view bottom margin, at rest -->
- <dimen name="volume_dialog_margin_bottom">4dp</dimen>
- <dimen name="volume_dialog_padding_top">8dp</dimen>
- <dimen name="volume_dialog_padding_end">40dp</dimen>
-
- <dimen name="volume_row_padding_bottom">9.4dp</dimen>
- <dimen name="volume_row_padding_start">4dp</dimen>
- <dimen name="volume_row_header_padding_start">16dp</dimen>
- <dimen name="volume_row_height">64dp</dimen>
<dimen name="volume_row_slider_height">192dp</dimen>
- <dimen name="volume_row_slider_padding_start">12dp</dimen>
-
- <dimen name="volume_expander_margin_end">2dp</dimen>
- <dimen name="volume_expander_margin_top">6dp</dimen>
<!-- Thickness of the assist disclosure beams -->
<dimen name="assist_disclosure_thickness">2.5dp</dimen>
@@ -1056,14 +768,6 @@
<!-- Thickness of the shadows of the assist disclosure beams -->
<dimen name="assist_disclosure_shadow_thickness">1.5dp</dimen>
- <dimen name="fab_size">56dp</dimen>
- <dimen name="fab_margin">16dp</dimen>
- <dimen name="fab_elevation">12dp</dimen>
- <dimen name="fab_press_translation_z">9dp</dimen>
-
- <dimen name="battery_detail_graph_space_top">27dp</dimen>
- <dimen name="battery_detail_graph_space_bottom">27dp</dimen>
-
<!-- Keyboard shortcuts helper -->
<dimen name="ksh_layout_width">@dimen/match_parent</dimen>
<dimen name="ksh_item_text_size">14sp</dimen>
@@ -1072,15 +776,10 @@
<!-- The size of corner radius of the arrow in the onboarding toast. -->
<dimen name="recents_onboarding_toast_arrow_corner_radius">2dp</dimen>
- <!-- The start margin of quick scrub onboarding toast. -->
- <dimen name="recents_quick_scrub_onboarding_margin_start">8dp</dimen>
<dimen name="default_gear_space">18dp</dimen>
- <dimen name="cell_overlay_padding">18dp</dimen>
<!-- Global actions power menu -->
- <dimen name="global_actions_panel_width">120dp</dimen>
- <dimen name="global_actions_padding">12dp</dimen>
<dimen name="global_actions_translate">9dp</dimen>
<!-- Distance from the top of screen in pixels, to position the power menu near the button. -->
@@ -1101,25 +800,14 @@
<dimen name="global_actions_grid_item_layout_height">98dp</dimen>
<dimen name="global_actions_grid_item_side_margin">5dp</dimen>
- <dimen name="global_actions_grid_item_vertical_margin">4dp</dimen>
- <dimen name="global_actions_grid_item_width">64dp</dimen>
<dimen name="global_actions_grid_item_height">64dp</dimen>
- <dimen name="global_actions_grid_item_icon_width">20dp</dimen>
- <dimen name="global_actions_grid_item_icon_height">20dp</dimen>
- <dimen name="global_actions_grid_item_icon_top_margin">12dp</dimen>
- <dimen name="global_actions_grid_item_icon_side_margin">22dp</dimen>
- <dimen name="global_actions_grid_item_icon_bottom_margin">4dp</dimen>
-
<!-- Margins at the left and right of the power menu and home controls widgets. -->
<dimen name="global_actions_side_margin">10dp</dimen>
<!-- Amount to shift the layout when exiting/entering for controls activities -->
<dimen name="global_actions_controls_y_translation">20dp</dimen>
- <!-- Shift quick access wallet down in Global Actions when Controls are unavailable -->
- <dimen name="global_actions_wallet_top_margin">40dp</dimen>
-
<!-- Shutdown and restart actions are larger in power options dialog -->
<dimen name="global_actions_power_dialog_item_height">190dp</dimen>
<dimen name="global_actions_power_dialog_item_width">255dp</dimen>
@@ -1156,17 +844,9 @@
<dimen name="udfps_burn_in_offset_x">7px</dimen>
<dimen name="udfps_burn_in_offset_y">28px</dimen>
- <dimen name="corner_size">8dp</dimen>
- <dimen name="top_padding">0dp</dimen>
- <dimen name="bottom_padding">48dp</dimen>
- <dimen name="edge_margin">8dp</dimen>
-
<!-- The absolute side margins of quick settings -->
<dimen name="quick_settings_bottom_margin_media">8dp</dimen>
- <dimen name="rounded_corner_content_padding">0dp</dimen>
<dimen name="nav_content_padding">0dp</dimen>
- <dimen name="nav_quick_scrub_track_edge_padding">24dp</dimen>
- <dimen name="nav_quick_scrub_track_thickness">10dp</dimen>
<!-- Navigation bar shadow params. -->
<dimen name="nav_key_button_shadow_offset_x">0dp</dimen>
@@ -1211,14 +891,6 @@
<!-- Y translation for credential contents when animating in -->
<dimen name="biometric_dialog_credential_translation_offset">60dp</dimen>
- <!-- Wireless Charging Animation values -->
- <dimen name="wireless_charging_dots_radius_start">0dp</dimen>
- <dimen name="wireless_charging_dots_radius_end">4dp</dimen>
- <dimen name="wireless_charging_circle_radius_start">28dp</dimen>
- <dimen name="wireless_charging_circle_radius_end">84dp</dimen>
- <integer name="wireless_charging_angle_offset">20</integer>
- <integer name="wireless_charging_scale_dots_duration">83</integer>
- <integer name="wireless_charging_num_dots">16</integer>
<!-- Starting text size in sp of batteryLevel for wireless charging animation -->
<item name="wireless_charging_anim_battery_level_text_size_start" format="float" type="dimen">
0
@@ -1281,7 +953,6 @@
<dimen name="ongoing_appops_dialog_side_padding">16dp</dimen>
<!-- Size of the RAT type for CellularTile -->
- <dimen name="celltile_rat_type_size">10sp</dimen>
<!-- Size of media cards in the QSPanel carousel -->
<dimen name="qs_media_padding">16dp</dimen>
@@ -1298,7 +969,6 @@
<dimen name="qs_media_action_margin">12dp</dimen>
<dimen name="qs_seamless_height">24dp</dimen>
<dimen name="qs_seamless_icon_size">12dp</dimen>
- <dimen name="qs_footer_horizontal_margin">22dp</dimen>
<dimen name="qs_media_disabled_seekbar_height">1dp</dimen>
<dimen name="qs_media_enabled_seekbar_height">2dp</dimen>
<dimen name="qs_media_enabled_seekbar_vertical_padding">28dp</dimen>
@@ -1332,7 +1002,6 @@
<dimen name="magnification_max_frame_size">300dp</dimen>
<!-- Home Controls -->
- <dimen name="controls_header_side_margin">4dp</dimen>
<dimen name="controls_header_menu_size">48dp</dimen>
<dimen name="controls_header_bottom_margin">24dp</dimen>
<dimen name="controls_header_app_icon_size">24dp</dimen>
@@ -1358,7 +1027,6 @@
<dimen name="control_base_item_margin">4dp</dimen>
<dimen name="control_status_padding">3dp</dimen>
<fraction name="controls_toggle_bg_intensity">5%</fraction>
- <fraction name="controls_dimmed_alpha">40%</fraction>
<dimen name="controls_setup_top_margin">16dp</dimen>
<dimen name="controls_setup_title">22sp</dimen>
<dimen name="controls_setup_subtitle">14sp</dimen>
@@ -1366,9 +1034,6 @@
<dimen name="controls_detail_dialog_header_height">52dp</dimen>
<!-- Home Controls activity view detail panel-->
- <dimen name="controls_activity_view_top_offset">100dp</dimen>
- <dimen name="controls_activity_view_side_offset">12dp</dimen>
- <dimen name="controls_activity_view_text_size">17sp</dimen>
<dimen name="controls_activity_view_corner_radius">@*android:dimen/config_bottomDialogCornerRadius</dimen>
<!-- Home Controls management screens -->
@@ -1394,12 +1059,7 @@
<dimen name="controls_app_icon_size">24dp</dimen>
<dimen name="controls_app_icon_frame_side_padding">16dp</dimen>
- <dimen name="controls_app_icon_frame_top_padding">4dp</dimen>
- <dimen name="controls_app_icon_frame_bottom_padding">@dimen/controls_app_icon_frame_top_padding</dimen>
- <dimen name="controls_app_bottom_margin">8dp</dimen>
- <dimen name="controls_app_text_padding">8dp</dimen>
<dimen name="controls_app_divider_height">2dp</dimen>
- <dimen name="controls_app_divider_side_margin">32dp</dimen>
<item name="controls_thumbnail_shadow_x" type="dimen" format="float">2.0</item>
<item name="controls_thumbnail_shadow_y" type="dimen" format="float">2.0</item>
@@ -1428,11 +1088,6 @@
<!-- Opacity at which the background for the shutdown UI will be drawn. -->
<item name="shutdown_scrim_behind_alpha" format="float" type="dimen">0.95</item>
- <!-- Allow CornerHandleView and PathSpecCornerPathRenderer to decouple from corner-radius -->
- <dimen name="config_rounded_mask_size">@*android:dimen/rounded_corner_radius</dimen>
- <dimen name="config_rounded_mask_size_top">@*android:dimen/rounded_corner_radius_top</dimen>
- <dimen name="config_rounded_mask_size_bottom">@*android:dimen/rounded_corner_radius_bottom</dimen>
-
<!-- Output switcher panel related dimensions -->
<dimen name="media_output_dialog_list_margin">12dp</dimen>
<dimen name="media_output_dialog_list_max_height">364dp</dimen>
@@ -1541,18 +1196,10 @@
<!-- rounded_slider_corner_radius + rounded_slider_background_padding -->
<dimen name="rounded_slider_background_rounded_corner">32dp</dimen>
- <!-- inset for ic_lock_open within a DisabledUdfpsView -->
- <dimen name="udfps_unlock_icon_inset">16dp</dimen>
-
<!-- Location on the screen of the center of the physical power button. This is a reasonable
default that should be overridden by device-specific overlays. -->
<dimen name="physical_power_button_center_screen_location_y">620px</dimen>
- <!-- Location on the screen of the center of the physical volume up/down buttons. This is a
- reasonable default that should be overridden by device-specific overlays. -->
- <dimen name="physical_volume_up_button_center_screen_location_y">950px</dimen>
- <dimen name="physical_volume_down_button_center_screen_location_y">1150px</dimen>
-
<!-- Location on the screen of the center of the fingerprint sensor. For devices with under
display fingerprint sensors, this directly corresponds to the fingerprint sensor's location.
For devices with sensors on the back of the device, this corresponds to the location on the
@@ -1598,7 +1245,6 @@
<dimen name="ongoing_call_chip_corner_radius">28dp</dimen>
<!-- Internet panel related dimensions -->
- <dimen name="internet_dialog_list_margin">12dp</dimen>
<dimen name="internet_dialog_list_max_height">662dp</dimen>
<!-- The width of large/content heavy dialogs (e.g. Internet, Media output, etc) -->
@@ -1612,13 +1258,8 @@
<!-- End margin of network layout -->
<dimen name="internet_dialog_network_layout_margin">16dp</dimen>
<!-- Size of switch bar in internet dialog -->
- <dimen name="settingslib_switchbar_margin">16dp</dimen>
<!-- Minimum width of switch -->
<dimen name="settingslib_min_switch_width">52dp</dimen>
- <!-- Size of layout margin left -->
- <dimen name="settingslib_switchbar_padding_left">20dp</dimen>
- <!-- Size of layout margin right -->
- <dimen name="settingslib_switchbar_padding_right">20dp</dimen>
<!-- Radius of switch bar -->
<dimen name="settingslib_switch_bar_radius">35dp</dimen>
<!-- Margin of switch thumb -->
diff --git a/packages/SystemUI/res/values/ids.xml b/packages/SystemUI/res/values/ids.xml
index f4f881f..926734c 100644
--- a/packages/SystemUI/res/values/ids.xml
+++ b/packages/SystemUI/res/values/ids.xml
@@ -46,17 +46,11 @@
<item type="id" name="height_animator_start_value_tag"/>
<item type="id" name="x_animator_tag_start_value"/>
<item type="id" name="y_animator_tag_start_value"/>
- <item type="id" name="doze_saved_filter_tag"/>
<item type="id" name="qs_icon_tag"/>
<item type="id" name="qs_slash_tag"/>
<item type="id" name="scrim"/>
<item type="id" name="scrim_alpha_start"/>
<item type="id" name="scrim_alpha_end"/>
- <item type="id" name="notification_power"/>
- <item type="id" name="notification_screenshot"/>
- <item type="id" name="notification_hidden"/>
- <item type="id" name="notification_temperature"/>
- <item type="id" name="notification_plugin"/>
<item type="id" name="transformation_start_x_tag"/>
<item type="id" name="doze_intensity_tag"/>
<item type="id" name="transformation_start_y_tag"/>
diff --git a/packages/SystemUI/res/values/integers.xml b/packages/SystemUI/res/values/integers.xml
index 116403c..f0f7a19 100644
--- a/packages/SystemUI/res/values/integers.xml
+++ b/packages/SystemUI/res/values/integers.xml
@@ -17,11 +17,6 @@
<resources>
<integer name="biometric_dialog_text_gravity">8388611</integer> <!-- gravity start -->
- <!-- Action footer width used for layout_width to indicate WRAP_CONTENT (along with a weight of
- 0) as we can allow the carrier text to stretch as far as needed in the QS footer. -->
- <integer name="qs_footer_actions_width">0</integer>
- <integer name="qs_footer_actions_weight">1</integer>
-
<integer name="qs_security_footer_maxLines">2</integer>
<integer name="magnification_default_scale">2</integer>
diff --git a/packages/SystemUI/res/values/internal.xml b/packages/SystemUI/res/values/internal.xml
index c29a51f..649e59e 100644
--- a/packages/SystemUI/res/values/internal.xml
+++ b/packages/SystemUI/res/values/internal.xml
@@ -18,6 +18,5 @@
<dimen name="status_bar_height">@*android:dimen/status_bar_height</dimen>
<dimen name="navigation_bar_height">@*android:dimen/navigation_bar_height</dimen>
<dimen name="navigation_bar_frame_height">@*android:dimen/navigation_bar_frame_height</dimen>
- <dimen name="navigation_bar_height_car_mode">@*android:dimen/navigation_bar_height_car_mode</dimen>
</resources>
diff --git a/packages/SystemUI/res/values/mland_config.xml b/packages/SystemUI/res/values/mland_config.xml
index 0ca88ae..6cd3409 100644
--- a/packages/SystemUI/res/values/mland_config.xml
+++ b/packages/SystemUI/res/values/mland_config.xml
@@ -30,7 +30,6 @@
<dimen name="cloud_size_min">10dp</dimen>
<dimen name="cloud_size_max">100dp</dimen>
<dimen name="sun_size">45dp</dimen>
- <dimen name="moon_size">30dp</dimen>
<dimen name="star_size_min">3dp</dimen>
<dimen name="star_size_max">5dp</dimen>
<dimen name="G">30dp</dimen>
diff --git a/packages/SystemUI/res/values/mland_strings.xml b/packages/SystemUI/res/values/mland_strings.xml
deleted file mode 100644
index fada1ae..0000000
--- a/packages/SystemUI/res/values/mland_strings.xml
+++ /dev/null
@@ -1,20 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
- Copyright (C) 2015 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 xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <!-- Name of the easter egg. DO NOT TRANSLATE -->
- <string name="mland">Marshmallow Land</string>
-</resources>
diff --git a/packages/SystemUI/res/values/strings.xml b/packages/SystemUI/res/values/strings.xml
index 2de8b49..dee886a 100644
--- a/packages/SystemUI/res/values/strings.xml
+++ b/packages/SystemUI/res/values/strings.xml
@@ -20,24 +20,6 @@
<!-- Name of the status bar as seen in the applications info settings page. [CHAR LIMIT=12] -->
<string name="app_label">System UI</string>
- <!-- The text for the button in the notification window-shade that clears
- all of the currently visible notifications. [CHAR LIMIT=10]-->
- <string name="status_bar_clear_all_button">Clear</string>
-
- <!-- The label in the bar at the top of the status bar when there are no notifications
- showing. [CHAR LIMIT=40]-->
- <string name="status_bar_no_notifications_title">No notifications</string>
-
- <!-- The label for the group of notifications for ongoing events in the opened version of
- the status bar. An ongoing call is the prime example of this. The MP3 music player
- might be another example. [CHAR LIMIT=40] -->
- <string name="status_bar_ongoing_events_title">Ongoing</string>
-
- <!-- The label for the group of notifications for recent events in the opened version of
- the status bar. Recently received text messsages (SMS), emails, calendar alerts, etc.
- [CHAR LIMIT=40] -->
- <string name="status_bar_latest_events_title">Notifications</string>
-
<!-- When the battery is low, this is displayed to the user in a dialog. The title of the low battery alert. [CHAR LIMIT=NONE]-->
<string name="battery_low_title">Battery may run out soon</string>
@@ -49,22 +31,18 @@
<!-- A message that appears when the battery remaining estimate is low in a dialog. This is
appended to the subtitle of the low battery alert. "percentage" is the percentage of battery
remaining. "time" is the amount of time remaining before the phone runs out of battery [CHAR LIMIT=none]-->
- <string name="battery_low_percent_format_hybrid"><xliff:g id="percentage">%1$s</xliff:g> remaining, about <xliff:g id="time">%2$s</xliff:g> left based on your usage</string>
<!-- A message that appears when the battery remaining estimate is low in a dialog and insufficient
data was present to say it is customized to the user. This is appended to the subtitle of the
low battery alert. "percentage" is the percentage of battery remaining. "time" is the amount
of time remaining before the phone runs out of battery [CHAR LIMIT=none]-->
- <string name="battery_low_percent_format_hybrid_short"><xliff:g id="percentage">%1$s</xliff:g> remaining, about <xliff:g id="time">%2$s</xliff:g> left</string>
<!-- Same as battery_low_percent_format, with a notice about battery saver if on. [CHAR LIMIT=none]-->
- <string name="battery_low_percent_format_saver_started"><xliff:g id="percentage">%s</xliff:g> remaining. Battery Saver is on.</string>
<!-- A message that appears when a USB charger is plugged in and the device does not
support charging on it. That is, a charger that fits into the USB port and goes into
a wall socket, not into a computer. (This happens because some devices require more
current than the USB spec allows. [CHAR LIMIT=NONE] -->
- <string name="invalid_charger">Can\'t charge via USB. Use the charger that came with your device.</string>
<!-- First line of invalid_charger, used in the notification form. [CHAR LIMIT=NONE]-->
<string name="invalid_charger_title">Can\'t charge via USB</string>
@@ -72,10 +50,6 @@
<!-- Second line of invalid_charger, used in the notification form. [CHAR LIMIT=NONE]-->
<string name="invalid_charger_text">Use the charger that came with your device</string>
- <!-- When the battery is low, this is the label of the button to go to the
- power usage activity to find out what drained the battery. [CHAR LIMIT=30] -->
- <string name="battery_low_why">Settings</string>
-
<!-- Battery saver confirmation dialog title [CHAR LIMIT=NONE]-->
<string name="battery_saver_confirmation_title">Turn on Battery Saver?</string>
@@ -89,34 +63,15 @@
<string name="battery_saver_start_action">Turn on Battery Saver</string>
<!-- Name of the button that links to the Settings app. [CHAR LIMIT=NONE] -->
- <string name="status_bar_settings_settings_button">Settings</string>
<!-- Name of the button that links to the Wifi settings screen. [CHAR LIMIT=NONE] -->
- <string name="status_bar_settings_wifi_button">Wi-Fi</string>
<!-- Label in system panel saying the device will use the orientation sensor to rotate [CHAR LIMIT=30] -->
<string name="status_bar_settings_auto_rotation">Auto-rotate screen</string>
- <!-- Abbreviation / label for mute brightness mode button. Should be all caps. [CHAR LIMIT=6] -->
- <string name="status_bar_settings_mute_label">MUTE</string>
-
- <!-- Abbreviation / label for automatic brightness mode button. Should be all caps. [CHAR LIMIT=6] -->
- <string name="status_bar_settings_auto_brightness_label">AUTO</string>
-
- <!-- Label in system panel saying the device will show notifications [CHAR LIMIT=30] -->
- <string name="status_bar_settings_notifications">Notifications</string>
-
<!-- Separator for PLMN and SPN in network name. -->
<string name="status_bar_network_name_separator" translatable="false"> - </string>
- <!-- Network connection string for Bluetooth Reverse Tethering -->
- <string name="bluetooth_tethered">Bluetooth tethered</string>
- <!-- Title of a button to open the settings for input methods [CHAR LIMIT=30] -->
- <string name="status_bar_input_method_settings_configure_input_methods">Set up input methods</string>
-
- <!-- Label of a toggle switch to disable use of the physical keyboard in favor of the IME. [CHAR LIMIT=25] -->
- <string name="status_bar_use_physical_keyboard">Physical keyboard</string>
-
<!-- Prompt for the USB device permission dialog [CHAR LIMIT=80] -->
<string name="usb_device_permission_prompt">Allow <xliff:g id="application" example= "Usb Mega Player">%1$s</xliff:g> to access <xliff:g id="usb_device" example="USB Headphones">%2$s</xliff:g>?</string>
@@ -201,14 +156,6 @@
<!-- Button text to disable contaminant detection [CHAR LIMIT=NONE] -->
<string name="learn_more">Learn more</string>
- <!-- Checkbox label for application compatibility mode ON (zooming app to look like it's running
- on a phone). [CHAR LIMIT=25] -->
- <string name="compat_mode_on">Zoom to fill screen</string>
-
- <!-- Checkbox label for application compatibility mode OFF (normal mode on tablets).
- [CHAR LIMIT=25] -->
- <string name="compat_mode_off">Stretch to fill screen</string>
-
<!-- Power menu item for taking a screenshot [CHAR LIMIT=20]-->
<string name="global_action_screenshot">Screenshot</string>
<!-- Message shown in power menu when smart lock has been disabled [CHAR_LIMIT=NONE] -->
@@ -218,14 +165,10 @@
[CHAR LIMIT=50] -->
<string name="remote_input_image_insertion_text">sent an image</string>
- <!-- Notification ticker displayed when a screenshot is being saved to the Gallery. [CHAR LIMIT=30] -->
- <string name="screenshot_saving_ticker">Saving screenshot\u2026</string>
<!-- Informs the user that a screenshot is being saved. [CHAR LIMIT=50] -->
<string name="screenshot_saving_title">Saving screenshot\u2026</string>
<!-- Notification title displayed when a screenshot is saved to the Gallery. [CHAR LIMIT=50] -->
<string name="screenshot_saved_title">Screenshot saved</string>
- <!-- Notification text displayed when a screenshot is saved to the Gallery. [CHAR LIMIT=100] -->
- <string name="screenshot_saved_text">Tap to view your screenshot</string>
<!-- Notification title displayed when we fail to take a screenshot. [CHAR LIMIT=50] -->
<string name="screenshot_failed_title">Couldn\'t save screenshot</string>
<!-- Notification text displayed when we fail to save a screenshot due to locked storage. [CHAR LIMIT=100] -->
@@ -240,7 +183,6 @@
<!-- Label for UI element which allows editing the screenshot [CHAR LIMIT=30] -->
<string name="screenshot_edit_label">Edit</string>
<!-- Content description indicating that tapping the element will allow editing the screenshot [CHAR LIMIT=NONE] -->
- <string name="screenshot_edit_description">Edit screenshot</string>
<!-- Label for UI element which allows the user to capture additional off-screen content in a screenshot. [CHAR LIMIT=30] -->
<string name="screenshot_scroll_label">Capture more</string>
<!-- Content description indicating that tapping a button will dismiss the screenshots UI [CHAR LIMIT=NONE] -->
@@ -285,19 +227,11 @@
<!-- Label for the checkbox to enable showing location of touches during screen recording [CHAR LIMIT=NONE]-->
<string name="screenrecord_taps_label">Show touches on screen</string>
<!-- Label for notification that the user can tap to stop and save the screen recording [CHAR LIMIT=NONE] -->
- <string name="screenrecord_stop_text">Tap to stop</string>
<!-- Label for notification action to stop and save the screen recording [CHAR LIMIT=35] -->
<string name="screenrecord_stop_label">Stop</string>
- <!-- Label for notification action to pause screen recording [CHAR LIMIT=35] -->
- <string name="screenrecord_pause_label">Pause</string>
- <!-- Label for notification action to resume screen recording [CHAR LIMIT=35] -->
- <string name="screenrecord_resume_label">Resume</string>
- <!-- Label for notification action to cancel and discard screen recording [CHAR LIMIT=35] -->
- <string name="screenrecord_cancel_label">Cancel</string>
<!-- Label for notification action to share screen recording [CHAR LIMIT=35] -->
<string name="screenrecord_share_label">Share</string>
<!-- A toast message shown after successfully canceling a screen recording [CHAR LIMIT=NONE] -->
- <string name="screenrecord_cancel_success">Screen recording canceled</string>
<!-- Notification text shown after saving a screen recording [CHAR LIMIT=100] -->
<string name="screenrecord_save_title">Screen recording saved</string>
<!-- Subtext for a notification shown after saving a screen recording to prompt the user to view it [CHAR_LIMIT=100] -->
@@ -305,19 +239,9 @@
<!-- A toast message shown when there is an error deleting a screen recording [CHAR LIMIT=NONE] -->
<string name="screenrecord_delete_error">Error deleting screen recording</string>
<!-- A toast message shown when the screen recording cannot be started due to insufficient permissions [CHAR LIMIT=NONE] -->
- <string name="screenrecord_permission_error">Failed to get permissions</string>
<!-- A toast message shown when the screen recording cannot be started due to a generic error [CHAR LIMIT=NONE] -->
<string name="screenrecord_start_error">Error starting screen recording</string>
- <!-- Title for the USB function chooser in UsbPreferenceActivity. [CHAR LIMIT=30] -->
- <string name="usb_preference_title">USB file transfer options</string>
- <!-- Label for the MTP USB function in UsbPreferenceActivity. [CHAR LIMIT=50] -->
- <string name="use_mtp_button_title">Mount as a media player (MTP)</string>
- <!-- Label for the PTP USB function in UsbPreferenceActivity. [CHAR LIMIT=50] -->
- <string name="use_ptp_button_title">Mount as a camera (PTP)</string>
- <!-- Label for the installer CD image option in UsbPreferenceActivity. [CHAR LIMIT=50] -->
- <string name="installer_cd_button_title">Install Android File Transfer app for Mac</string>
-
<!-- Content description of the back button for accessibility (not shown on the screen). [CHAR LIMIT=NONE] -->
<string name="accessibility_back">Back</string>
<!-- Content description of the home button for accessibility (not shown on the screen). [CHAR LIMIT=NONE] -->
@@ -331,7 +255,6 @@
<!-- Content description of the recents button for accessibility (not shown on the screen). [CHAR LIMIT=NONE] -->
<string name="accessibility_recent">Overview</string>
<!-- Content description of the search button for accessibility. [CHAR LIMIT=NONE] -->
- <string name="accessibility_search_light">Search</string>
<!-- Content description of the camera button for accessibility (not shown on the screen). [CHAR LIMIT=NONE] -->
<string name="accessibility_camera_button">Camera</string>
<!-- Content description of the phone button for accessibility (not shown on the screen). [CHAR LIMIT=NONE] -->
@@ -345,15 +268,12 @@
<!-- Content description of the lock icon for accessibility (not shown on the screen). [CHAR LIMIT=NONE] -->
<string name="accessibility_lock_icon">Device locked</string>
<!-- Content description hint of the unlock button when fingerprint is on (not shown on the screen). [CHAR LIMIT=NONE] -->
- <string name="accessibility_waiting_for_fingerprint">Waiting for fingerprint</string>
<!-- Accessibility action of the unlock button when fingerpint is on (not shown on the screen). [CHAR LIMIT=NONE] -->
- <string name="accessibility_unlock_without_fingerprint">Unlock without using your fingerprint</string>
<!-- Content description of the Trusted Face icon for accessibility. [CHAR LIMIT=NONE] -->
<string name="accessibility_scanning_face">Scanning face</string>
<!-- Click action label for accessibility for the smart reply buttons (not shown on-screen).". [CHAR LIMIT=NONE] -->
<string name="accessibility_send_smart_reply">Send</string>
<!-- Content description of the manage notification button for accessibility (not shown on the screen). [CHAR LIMIT=NONE] -->
- <string name="accessibility_manage_notification">Manage notifications</string>
<!-- Click action label for accessibility for the phone button. [CHAR LIMIT=NONE] -->
<string name="phone_label">open phone</string>
<!-- Click action label for accessibility for the voice assist button. This is not shown on-screen and is an accessibility label for the icon which launches the voice assist from the lock screen.[CHAR LIMIT=NONE] -->
@@ -399,7 +319,6 @@
<!-- Error string shown when the user enters an incorrect PIN/pattern/password and it counts towards the max attempts before the data on the device is wiped. [CHAR LIMIT=NONE]-->
<string name="biometric_dialog_credential_attempts_before_wipe">Try again. Attempt <xliff:g id="attempts" example="1">%1$d</xliff:g> of <xliff:g id="max_attempts" example="3">%2$d</xliff:g>.</string>
-
<!-- Title of a dialog shown when the user only has one attempt left to provide the correct PIN/pattern/password before the device, one of its users, or a work profile is wiped. [CHAR LIMIT=NONE] -->
<string name="biometric_dialog_last_attempt_before_wipe_dialog_title">Your data will be deleted</string>
<!-- Content of a dialog shown when the user only has one attempt left to provide the correct lock pattern before the device is wiped. [CHAR LIMIT=NONE] -->
@@ -436,127 +355,36 @@
<string name="accessibility_fingerprint_dialog_fingerprint_icon">Fingerprint icon</string>
<!-- Message shown to inform the user a face cannot be recognized and fingerprint should instead be used.[CHAR LIMIT=50] -->
<string name="fingerprint_dialog_use_fingerprint_instead">Can\u2019t recognize face. Use fingerprint instead.</string>
- <!-- Message shown to ask the user to use fingerprint to continue.[CHAR LIMIT=50] -->
- <string name="fingerprint_dialog_use_fingerprint">Use your fingerprint to continue</string>
- <!-- Message shown to ask the user to use screenlock to continue.[CHAR LIMIT=NONE] -->
- <string name="fingerprint_dialog_cant_recognize_fp_use_screenlock">Can\u2019t recognize fingerprint. Use screen lock instead.</string>
<!-- Message shown to inform the user a face cannot be recognized and fingerprint should instead be used.[CHAR LIMIT=50] -->
<string name="keyguard_face_failed_use_fp">@string/fingerprint_dialog_use_fingerprint_instead</string>
- <!-- Message shown when the system-provided face dialog is shown, asking for authentication [CHAR LIMIT=30] -->
- <string name="face_dialog_looking_for_face">Looking for you\u2026</string>
- <!-- Content description of the face icon when the system-provided face dialog is showing, for accessibility (not shown on the screen). [CHAR LIMIT=NONE] -->
- <string name="accessibility_face_dialog_face_icon">Face icon</string>
-
- <!-- Content description of the compatibility zoom button for accessibility (not shown on the screen). [CHAR LIMIT=NONE] -->
- <string name="accessibility_compatibility_zoom_button">Compatibility zoom button.</string>
-
- <!-- Content description of picture of the compatibility zoom example for accessibility (not shown on the screen). [CHAR LIMIT=NONE] -->
- <string name="accessibility_compatibility_zoom_example">Zoom smaller to larger screen.</string>
-
<!-- Content description of the bluetooth icon when connected for accessibility (not shown on the screen). [CHAR LIMIT=NONE] -->
<string name="accessibility_bluetooth_connected">Bluetooth connected.</string>
<!-- Content description of the bluetooth icon when connecting for accessibility (not shown on the screen). [CHAR LIMIT=NONE] -->
- <string name="accessibility_bluetooth_disconnected">Bluetooth disconnected.</string>
- <!-- Content description of the battery when no battery for accessibility (not shown on the screen). [CHAR LIMIT=NONE] -->
- <string name="accessibility_no_battery">No battery.</string>
- <!-- Content description of the battery when it is one bar for accessibility (not shown on the screen). [CHAR LIMIT=NONE] -->
- <string name="accessibility_battery_one_bar">Battery one bar.</string>
- <!-- Content description of the battery when it is two bars for accessibility (not shown on the screen). [CHAR LIMIT=NONE] -->
- <string name="accessibility_battery_two_bars">Battery two bars.</string>
- <!-- Content description of the battery when it is three bars for accessibility (not shown on the screen). [CHAR LIMIT=NONE] -->
- <string name="accessibility_battery_three_bars">Battery three bars.</string>
- <!-- Content description of the battery when it is full for accessibility (not shown on the screen). [CHAR LIMIT=NONE] -->
- <string name="accessibility_battery_full">Battery full.</string>
<!-- Content description of the battery when battery state is unknown for accessibility (not shown on the screen). [CHAR LIMIT=NONE] -->
<string name="accessibility_battery_unknown">Battery percentage unknown.</string>
- <!-- Content description of the wifi label showing what we are connected to. [CHAR LIMIT=NONE] -->
- <string name="accessibility_wifi_name">Connected to <xliff:g id="wifi" example="Home Network">%s</xliff:g>.</string>
-
<!-- Content description of the bluetooth label showing what we are connected to. [CHAR LIMIT=NONE] -->
<string name="accessibility_bluetooth_name">Connected to <xliff:g id="bluetooth" example="Car Audio">%s</xliff:g>.</string>
<!-- Content description of the cast label showing what we are connected to. [CHAR LIMIT=NONE] -->
<string name="accessibility_cast_name">Connected to <xliff:g id="cast" example="TV">%s</xliff:g>.</string>
-
- <!-- Content description of the WiMAX signal when no signal for accessibility (not shown on the screen). [CHAR LIMIT=NONE] -->
- <string name="accessibility_no_wimax">No WiMAX.</string>
- <!-- Content description of the WiMAX signal when it is one bar for accessibility (not shown on the screen). [CHAR LIMIT=NONE] -->
- <string name="accessibility_wimax_one_bar">WiMAX one bar.</string>
- <!-- Content description of the WiMAX signal when it is two bars for accessibility (not shown on the screen). [CHAR LIMIT=NONE] -->
- <string name="accessibility_wimax_two_bars">WiMAX two bars.</string>
- <!-- Content description of the WiMAX signal when it is three bars for accessibility (not shown on the screen). [CHAR LIMIT=NONE] -->
- <string name="accessibility_wimax_three_bars">WiMAX three bars.</string>
- <!-- Content description of the WiMAX signal when it is full for accessibility (not shown on the screen). [CHAR LIMIT=NONE] -->
- <string name="accessibility_wimax_signal_full">WiMAX signal full.</string>
-
- <!-- Content description of an item with no signal for accessibility (not shown on the screen). [CHAR LIMIT=NONE] -->
- <string name="accessibility_no_signal">No signal.</string>
<!-- Content description of an item with no signal and no connection for accessibility (not shown on the screen) [CHAR LIMIT=NONE] -->
<string name="accessibility_not_connected">Not connected.</string>
- <!-- Content description of an item with zero signal bars for accessibility (not shown on the screen). [CHAR LIMIT=NONE] -->
- <string name="accessibility_zero_bars">Zero bars.</string>
- <!-- Content description of an item with one signal bar for accessibility (not shown on the screen). [CHAR LIMIT=NONE] -->
- <string name="accessibility_one_bar">One bar.</string>
- <!-- Content description of an item with two signal bars for accessibility (not shown on the screen). [CHAR LIMIT=NONE] -->
- <string name="accessibility_two_bars">Two bars.</string>
- <!-- Content description of an item with three signal bars for accessibility (not shown on the screen). [CHAR LIMIT=NONE] -->
- <string name="accessibility_three_bars">Three bars.</string>
- <!-- Content description of an item with full signal for accessibility (not shown on the screen). [CHAR LIMIT=NONE] -->
- <string name="accessibility_signal_full">Signal full.</string>
-
- <!-- Content description of an item that is turned on for accessibility (not shown on the screen). [CHAR LIMIT=NONE] -->
- <string name="accessibility_desc_on">On.</string>
- <!-- Content description of an item that is turned off for accessibility (not shown on the screen). [CHAR LIMIT=NONE] -->
- <string name="accessibility_desc_off">Off.</string>
- <!-- Content description of an item that is connected for accessibility (not shown on the screen). [CHAR LIMIT=NONE] -->
- <string name="accessibility_desc_connected">Connected.</string>
- <!-- Content description of an item that is connecting for accessibility (not shown on the screen). [CHAR LIMIT=NONE] -->
- <string name="accessibility_desc_connecting">Connecting.</string>
-
- <!-- Content description of the data connection type HSPA and its variants. [CHAR LIMIT=NONE] -->
- <string name="data_connection_hspa">HSPA</string>
-
- <!-- Content description of the data connection type 5Ge. [CHAR LIMIT=NONE] -->
- <string name="data_connection_5ge" translatable="false">5Ge</string>
-
-
<!-- Content description of the roaming data connection type. [CHAR LIMIT=NONE] -->
<string name="data_connection_roaming">Roaming</string>
- <!-- Content description of the data connection type WiFi for accessibility (not shown on the screen). [CHAR LIMIT=NONE] -->
- <string name="accessibility_data_connection_wifi">Wi-Fi</string>
-
- <!-- Content description of the data connection with no SIM for accessibility (not shown on the screen). [CHAR LIMIT=NONE] -->
- <string name="accessibility_no_sim">No SIM.</string>
-
- <!-- Content description of the cell data. [CHAR LIMIT=NONE] -->
- <string name="accessibility_cell_data">Mobile Data</string>
-
- <!-- Content description of the cell data being enabled. [CHAR LIMIT=NONE] -->
- <string name="accessibility_cell_data_on">Mobile Data On</string>
-
<!-- Content description of the cell data being disabled but shortened. [CHAR LIMIT=20] -->
<string name="cell_data_off">Off</string>
- <!-- Content description of the bluetooth tethering icon for accessibility (not shown on the screen). [CHAR LIMIT=NONE] -->
- <string name="accessibility_bluetooth_tether">Bluetooth tethering.</string>
-
<!-- Content description of the airplane mode icon for accessibility (not shown on the screen). [CHAR LIMIT=NONE] -->
<string name="accessibility_airplane_mode">Airplane mode.</string>
<!-- Content description of the VPN icon for accessibility (not shown on the screen). [CHAR LIMIT=NONE] -->
<string name="accessibility_vpn_on">VPN on.</string>
- <!-- Content description of the no sim icon for accessibility (not shown on the screen). [CHAR LIMIT=NONE] -->
- <string name="accessibility_no_sims">No SIM card.</string>
-
- <!-- Content description of button to open battery details icon for accessibility (not shown on the screen). [CHAR LIMIT=NONE] -->
- <string name="accessibility_battery_details">Open battery details</string>
-
<!-- Content description of the battery level icon for accessibility (not shown on the screen). [CHAR LIMIT=NONE] -->
<string name="accessibility_battery_level">Battery <xliff:g id="number">%d</xliff:g> percent.</string>
@@ -566,24 +394,9 @@
<!-- Content description of the battery level icon for accessibility while the device is charging (not shown on the screen). [CHAR LIMIT=NONE] -->
<string name="accessibility_battery_level_charging">Battery charging, <xliff:g id="battery_percentage">%d</xliff:g> percent.</string>
- <!-- Content description of the button for showing a settings panel in the notification panel for accessibility (not shown on the screen). [CHAR LIMIT=NONE] -->
- <string name="accessibility_settings_button">System settings.</string>
-
- <!-- Content description of the button for showing a notifications panel in the notification panel for accessibility (not shown on the screen). [CHAR LIMIT=NONE] -->
- <string name="accessibility_notifications_button">Notifications.</string>
-
<!-- Content description of overflow icon container of the notifications for accessibility (not shown on the screen)[CHAR LIMIT=NONE] -->
<string name="accessibility_overflow_action">See all notifications</string>
- <!-- Content description of the button for removing a notification in the notification panel for accessibility (not shown on the screen). [CHAR LIMIT=NONE] -->
- <string name="accessibility_remove_notification">Clear notification.</string>
-
- <!-- Content description of the enabled GPS icon in the notification panel for accessibility (not shown on the screen). [CHAR LIMIT=NONE] -->
- <string name="accessibility_gps_enabled">GPS enabled.</string>
-
- <!-- Content description of the acquiring GPS icon in the notification panel for accessibility (not shown on the screen). [CHAR LIMIT=NONE] -->
- <string name="accessibility_gps_acquiring">GPS acquiring.</string>
-
<!-- Content description of the TeleTypewriter(TTY) enabled icon in the notification panel for accessibility (not shown on the screen). [CHAR LIMIT=NONE] -->
<string name="accessibility_tty_enabled">TeleTypewriter enabled.</string>
@@ -596,41 +409,21 @@
<!-- Content description of the cast icon in the notification panel for accessibility (not shown on the screen). [CHAR LIMIT=NONE] -->
<string name="accessibility_casting">@string/quick_settings_casting</string>
- <!-- Content description of the work mode icon in the notification panel for accessibility (not shown on the screen). [CHAR LIMIT=NONE] -->
- <string name="accessibility_work_mode">@string/quick_settings_work_mode_label</string>
-
- <!-- Content description to tell the user a notification has been removed from the notification shade -->
- <string name="accessibility_notification_dismissed">Notification dismissed.</string>
-
<!-- Content description for the notification shade panel (not shown on the screen). [CHAR LIMIT=NONE] -->
<string name="accessibility_desc_notification_shade">Notification shade.</string>
<!-- Content description for the quick settings panel (not shown on the screen). [CHAR LIMIT=NONE] -->
<string name="accessibility_desc_quick_settings">Quick settings.</string>
<!-- Content description for the lock screen (not shown on the screen). [CHAR LIMIT=NONE] -->
<string name="accessibility_desc_lock_screen">Lock screen.</string>
- <!-- Content description for the settings button in the status bar header. [CHAR LIMIT=NONE] -->
- <string name="accessibility_desc_settings">Settings</string>
- <!-- Content description for the recent apps panel (not shown on the screen). [CHAR LIMIT=NONE] -->
- <string name="accessibility_desc_recent_apps">Overview.</string>
<!-- Content description for the work profile lock screen. This prevents work profile apps from being used, but personal apps can be used as normal (not shown on the screen). [CHAR LIMIT=NONE] -->
<string name="accessibility_desc_work_lock">Work lock screen</string>
<!-- Content description for the close button in the zen mode panel introduction message. [CHAR LIMIT=NONE] -->
<string name="accessibility_desc_close">Close</string>
- <!-- Content description of the wifi tile in quick settings (not shown on the screen). [CHAR LIMIT=NONE] -->
- <string name="accessibility_quick_settings_wifi"><xliff:g id="signal" example="Three bars">%1$s</xliff:g>.</string>
<!-- Announcement made when the wifi is turned off (not shown on the screen). [CHAR LIMIT=NONE] -->
<string name="accessibility_quick_settings_wifi_changed_off">Wifi turned off.</string>
<!-- Announcement made when the wifi is turned on (not shown on the screen). [CHAR LIMIT=NONE] -->
<string name="accessibility_quick_settings_wifi_changed_on">Wifi turned on.</string>
- <!-- Content description of the mobile data tile in quick settings (not shown on the screen). [CHAR LIMIT=NONE] -->
- <string name="accessibility_quick_settings_mobile">Mobile <xliff:g id="signal" example="Three bars">%1$s</xliff:g>. <xliff:g id="type" example="4G">%2$s</xliff:g>. <xliff:g id="network" example="T-Mobile">%3$s</xliff:g>.</string>
- <!-- Content description of the battery tile in quick settings (not shown on the screen). [CHAR LIMIT=NONE] -->
- <string name="accessibility_quick_settings_battery">Battery <xliff:g id="state" example="50% charging">%s</xliff:g>.</string>
- <!-- Content description of the airplane mode tile in quick settings when off (not shown on the screen). [CHAR LIMIT=NONE] -->
- <string name="accessibility_quick_settings_airplane_off">Airplane mode off.</string>
- <!-- Content description of the airplane mode tile in quick settings when on (not shown on the screen). [CHAR LIMIT=NONE] -->
- <string name="accessibility_quick_settings_airplane_on">Airplane mode on.</string>
<!-- Announcement made when the airplane mode changes to off (not shown on the screen). [CHAR LIMIT=NONE] -->
<string name="accessibility_quick_settings_airplane_changed_off">Airplane mode turned off.</string>
<!-- Announcement made when the airplane mode changes to on (not shown on the screen). [CHAR LIMIT=NONE] -->
@@ -647,40 +440,22 @@
<string name="accessibility_quick_settings_dnd_changed_on">Do Not Disturb turned on.</string>
<!-- Content description of the bluetooth tile in quick settings (not shown on the screen). [CHAR LIMIT=NONE] -->
<string name="accessibility_quick_settings_bluetooth">Bluetooth.</string>
- <!-- Content description of the bluetooth tile in quick settings when off (not shown on the screen). [CHAR LIMIT=NONE] -->
- <string name="accessibility_quick_settings_bluetooth_off">Bluetooth off.</string>
<!-- Content description of the bluetooth tile in quick settings when on (not shown on the screen). [CHAR LIMIT=NONE] -->
<string name="accessibility_quick_settings_bluetooth_on">Bluetooth on.</string>
- <!-- Content description of the bluetooth tile in quick settings when connecting (not shown on the screen). [CHAR LIMIT=NONE] -->
- <string name="accessibility_quick_settings_bluetooth_connecting">Bluetooth connecting.</string>
- <!-- Content description of the bluetooth tile in quick settings when connected (not shown on the screen). [CHAR LIMIT=NONE] -->
- <string name="accessibility_quick_settings_bluetooth_connected">Bluetooth connected.</string>
<!-- Announcement made when the bluetooth is turned off (not shown on the screen). [CHAR LIMIT=NONE] -->
<string name="accessibility_quick_settings_bluetooth_changed_off">Bluetooth turned off.</string>
<!-- Announcement made when the bluetooth is turned on (not shown on the screen). [CHAR LIMIT=NONE] -->
<string name="accessibility_quick_settings_bluetooth_changed_on">Bluetooth turned on.</string>
- <!-- Content description of the location tile in quick settings when off (not shown on the screen). [CHAR LIMIT=NONE] -->
- <string name="accessibility_quick_settings_location_off">Location reporting off.</string>
- <!-- Content description of the location tile in quick settings when on (not shown on the screen). [CHAR LIMIT=NONE] -->
- <string name="accessibility_quick_settings_location_on">Location reporting on.</string>
<!-- Announcement made when the location tile changes to off (not shown on the screen). [CHAR LIMIT=NONE] -->
<string name="accessibility_quick_settings_location_changed_off">Location reporting turned off.</string>
<!-- Announcement made when the location tile changes to on (not shown on the screen). [CHAR LIMIT=NONE] -->
<string name="accessibility_quick_settings_location_changed_on">Location reporting turned on.</string>
<!-- Content description of the alarm tile in quick settings (not shown on the screen). [CHAR LIMIT=NONE] -->
<string name="accessibility_quick_settings_alarm">Alarm set for <xliff:g id="time" example="Wed 3:30 PM">%s</xliff:g>.</string>
- <!-- Content description of quick settings detail panel close button (not shown on the screen). [CHAR LIMIT=NONE] -->
- <string name="accessibility_quick_settings_close">Close panel.</string>
<!-- Content description of zen mode time condition plus button (not shown on the screen). [CHAR LIMIT=NONE] -->
<string name="accessibility_quick_settings_more_time">More time.</string>
<!-- Content description of zen mode time condition minus button (not shown on the screen). [CHAR LIMIT=NONE] -->
<string name="accessibility_quick_settings_less_time">Less time.</string>
- <!-- Content description of the flashlight tile in quick settings when off (not shown on the screen). [CHAR LIMIT=NONE] -->
- <string name="accessibility_quick_settings_flashlight_off">Flashlight off.</string>
- <!-- Content description of the flashlight tile in quick settings when unavailable (not shown on the screen). [CHAR LIMIT=NONE] -->
- <string name="accessibility_quick_settings_flashlight_unavailable">Flashlight unavailable.</string>
- <!-- Content description of the flashlight tile in quick settings when on (not shown on the screen). [CHAR LIMIT=NONE] -->
- <string name="accessibility_quick_settings_flashlight_on">Flashlight on.</string>
<!-- Announcement made when the flashlight state changes to off (not shown on the screen). [CHAR LIMIT=NONE] -->
<string name="accessibility_quick_settings_flashlight_changed_off">Flashlight turned off.</string>
<!-- Announcement made when the flashlight state changes to on (not shown on the screen). [CHAR LIMIT=NONE] -->
@@ -696,28 +471,19 @@
<!-- Announcement made when the screen stopped casting (not shown on the screen). [CHAR LIMIT=NONE] -->
<string name="accessibility_casting_turned_off">Screen casting stopped.</string>
<!-- Announcement made when the work mode changes to off (not shown on the screen). Paused is used as a verb. [CHAR LIMIT=NONE] -->
- <string name="accessibility_quick_settings_work_mode_changed_off">Work mode paused.</string>
<!-- Announcement made when the work mode changes to on (not shown on the screen). [CHAR LIMIT=NONE] -->
- <string name="accessibility_quick_settings_work_mode_changed_on">Work mode turned on.</string>
<!-- Announcement made when the Data Saver changes to off (not shown on the screen). [CHAR LIMIT=NONE] -->
<string name="accessibility_quick_settings_data_saver_changed_off">Data Saver turned off.</string>
<!-- Announcement made when the Data Saver changes to on (not shown on the screen). [CHAR LIMIT=NONE] -->
<string name="accessibility_quick_settings_data_saver_changed_on">Data Saver turned on.</string>
<!-- Announcement made when the Sensor Privacy changes to off (not shown on the screen). [CHAR LIMIT=NONE] -->
- <string name="accessibility_quick_settings_sensor_privacy_changed_off">Sensor Privacy turned off.</string>
<!-- Announcement made when the Sensor Privacy changes to on (not shown on the screen). [CHAR LIMIT=NONE] -->
- <string name="accessibility_quick_settings_sensor_privacy_changed_on">Sensor Privacy turned on.</string>
<!-- Content description of the display brightness slider (not shown on the screen). [CHAR LIMIT=NONE] -->
<string name="accessibility_brightness">Display brightness</string>
<!-- Content description of the charging indicator on Ambient Display (lower-power version of the lock screen). [CHAR LIMIT=NONE] -->
- <string name="accessibility_ambient_display_charging">Charging</string>
- <!-- Title of dialog shown when 2G-3G data usage has exceeded limit and has been disabled. [CHAR LIMIT=48] -->
- <string name="data_usage_disabled_dialog_3g_title">2G-3G data is paused</string>
- <!-- Title of dialog shown when 4G data usage has exceeded limit and has been disabled. [CHAR LIMIT=48] -->
- <string name="data_usage_disabled_dialog_4g_title">4G data is paused</string>
<!-- Title of dialog shown when mobile data usage has exceeded limit and has been disabled. [CHAR LIMIT=48] -->
<string name="data_usage_disabled_dialog_mobile_title">Mobile data is paused</string>
<!-- Title of dialog shown when data usage has exceeded limit and has been disabled. [CHAR LIMIT=48] -->
@@ -727,12 +493,6 @@
<!-- Dialog button indicating that data connection should be re-enabled. [CHAR LIMIT=28] -->
<string name="data_usage_disabled_dialog_enable">Resume</string>
- <!-- Notification text: when GPS is getting a fix [CHAR LIMIT=50] -->
- <string name="gps_notification_searching_text">Searching for GPS</string>
-
- <!-- Notification text: when GPS has found a fix [CHAR LIMIT=50] -->
- <string name="gps_notification_found_text">Location set by GPS</string>
-
<!-- Accessibility text describing the presence of active location requests by one or more apps -->
<string name="accessibility_location_active">Location requests active</string>
@@ -752,18 +512,14 @@
</plurals>
<!-- Format to use to summarize a message from a contact in a single line of text. For example: "Julia: How's it going?". [CHAR LIMIT=NONE] -->
- <string name="notification_summary_message_format"><xliff:g id="contact_name" example="Julia">%1$s</xliff:g>: <xliff:g id="message_content" example="How is it going?">%2$s</xliff:g></string>
<!-- Content description of button in notification inspector for system settings relating to
notifications from this application [CHAR LIMIT=NONE] -->
- <string name="status_bar_notification_inspect_item_title">Notification settings</string>
<!-- Content description of button in notification inspetor for application-provided settings
for its own notifications [CHAR LIMIT=NONE] -->
- <string name="status_bar_notification_app_settings_title"><xliff:g id="app_name" example="Calendar">%s</xliff:g> settings</string>
<!-- Description of the button in the phone-style notification panel that controls auto-rotation, when auto-rotation is on. [CHAR LIMIT=NONE] -->
- <string name="accessibility_rotation_lock_off">Screen will rotate automatically.</string>
<!-- Description of the button in the phone-style notification panel that controls auto-rotation, when auto-rotation is off. [CHAR LIMIT=NONE] -->
<string name="accessibility_rotation_lock_on_landscape">Screen is locked in landscape orientation.</string>
@@ -772,13 +528,10 @@
<string name="accessibility_rotation_lock_on_portrait">Screen is locked in portrait orientation.</string>
<!-- Announcement made when the screen is rotating automatically again (not shown on the screen). [CHAR LIMIT=NONE] -->
- <string name="accessibility_rotation_lock_off_changed">Screen will now rotate automatically.</string>
<!-- Announcement made when the rotation lock state changes to landscape only (not shown on the screen). [CHAR LIMIT=NONE] -->
- <string name="accessibility_rotation_lock_on_landscape_changed">Screen is now locked in landscape orientation.</string>
<!-- Announcement made when the rotation lock state changes to portrait only (not shown on the screen). [CHAR LIMIT=NONE] -->
- <string name="accessibility_rotation_lock_on_portrait_changed">Screen is now locked in portrait orientation.</string>
<!-- Name of the K-release easter egg: a display case for all our tastiest desserts. [CHAR LIMIT=30] -->
<string name="dessert_case">Dessert Case</string>
@@ -790,21 +543,15 @@
<string name="ethernet_label">Ethernet</string>
<!-- QuickSettings: Onboarding text that introduces users to long press on an option in order to view the option's menu in Settings [CHAR LIMIT=NONE] -->
- <string name="quick_settings_header_onboarding_text">Touch & hold icons for more options</string>
<!-- QuickSettings: Do not disturb [CHAR LIMIT=NONE] -->
<string name="quick_settings_dnd_label">Do Not Disturb</string>
<!-- QuickSettings: Do not disturb - Priority only [CHAR LIMIT=NONE] -->
- <string name="quick_settings_dnd_priority_label">Priority only</string>
<!-- QuickSettings: Do not disturb - Alarms only [CHAR LIMIT=NONE] -->
- <string name="quick_settings_dnd_alarms_label">Alarms only</string>
<!-- QuickSettings: Do not disturb - Total silence [CHAR LIMIT=NONE] -->
- <string name="quick_settings_dnd_none_label">Total silence</string>
<!-- QuickSettings: Bluetooth [CHAR LIMIT=NONE] -->
<string name="quick_settings_bluetooth_label">Bluetooth</string>
<!-- QuickSettings: Bluetooth (Multiple) [CHAR LIMIT=NONE] -->
- <string name="quick_settings_bluetooth_multiple_devices_label">Bluetooth (<xliff:g id="number">%d</xliff:g> Devices)</string>
<!-- QuickSettings: Bluetooth (Off) [CHAR LIMIT=NONE] -->
- <string name="quick_settings_bluetooth_off_label">Bluetooth Off</string>
<!-- QuickSettings: Bluetooth detail panel, text when there are no items [CHAR LIMIT=NONE] -->
<string name="quick_settings_bluetooth_detail_empty_text">No paired devices available</string>
<!-- QuickSettings: Bluetooth secondary label for the battery level of a connected device [CHAR LIMIT=20]-->
@@ -820,25 +567,18 @@
<!-- QuickSettings: Bluetooth secondary label shown when bluetooth is being enabled [CHAR LIMIT=NONE] -->
<string name="quick_settings_bluetooth_secondary_label_transient">Turning on…</string>
<!-- QuickSettings: Brightness [CHAR LIMIT=NONE] -->
- <string name="quick_settings_brightness_label">Brightness</string>
<!-- QuickSettings: Rotation Unlocked [CHAR LIMIT=NONE] -->
<string name="quick_settings_rotation_unlocked_label">Auto-rotate</string>
<!-- Accessibility label for Auto-ratate QuickSettings tile [CHAR LIMIT=NONE] -->
<string name="accessibility_quick_settings_rotation">Auto-rotate screen</string>
<!-- Accessibility label for value of Auto-ratate QuickSettings tile [CHAR LIMIT=NONE] -->
- <string name="accessibility_quick_settings_rotation_value"><xliff:g name="rotation" example="Portrait">%s</xliff:g> mode</string>
<!-- QuickSettings: Rotation Locked [CHAR LIMIT=NONE] -->
- <string name="quick_settings_rotation_locked_label">Rotation locked</string>
<!-- QuickSettings: Locked to Portrait [CHAR LIMIT=NONE] -->
- <string name="quick_settings_rotation_locked_portrait_label">Portrait</string>
<!-- QuickSettings: Locked to Landscape [CHAR LIMIT=NONE] -->
- <string name="quick_settings_rotation_locked_landscape_label">Landscape</string>
<!-- QuickSettings: IME [CHAR LIMIT=NONE] -->
- <string name="quick_settings_ime_label">Input Method</string>
<!-- QuickSettings: Location [CHAR LIMIT=NONE] -->
<string name="quick_settings_location_label">Location</string>
<!-- QuickSettings: Location (Off) [CHAR LIMIT=NONE] -->
- <string name="quick_settings_location_off_label">Location Off</string>
<!-- QuickSettings: Camera [CHAR LIMIT=NONE] -->
<string name="quick_settings_camera_label">Camera access</string>
<!-- QuickSettings: Microphone [CHAR LIMIT=NONE] -->
@@ -850,19 +590,13 @@
<!-- QuickSettings: Media device [CHAR LIMIT=NONE] -->
<string name="quick_settings_media_device_label">Media device</string>
<!-- QuickSettings: RSSI [CHAR LIMIT=NONE] -->
- <string name="quick_settings_rssi_label">RSSI</string>
<!-- QuickSettings: RSSI (No network) [CHAR LIMIT=NONE] -->
- <string name="quick_settings_rssi_emergency_only">Emergency Calls Only</string>
<!-- QuickSettings: Settings [CHAR LIMIT=NONE] -->
- <string name="quick_settings_settings_label">Settings</string>
<!-- QuickSettings: Time [CHAR LIMIT=NONE] -->
- <string name="quick_settings_time_label">Time</string>
<!-- QuickSettings: User [CHAR LIMIT=NONE] -->
- <string name="quick_settings_user_label">Me</string>
<!-- QuickSettings: Title of the user detail panel [CHAR LIMIT=NONE] -->
<string name="quick_settings_user_title">User</string>
<!-- QuickSettings: Label on the item for adding a new user [CHAR LIMIT=NONE] -->
- <string name="quick_settings_user_new_user">New user</string>
<!-- QuickSettings: Wifi [CHAR LIMIT=NONE] -->
<string name="quick_settings_wifi_label">Wi-Fi</string>
<!-- QuickSettings: Internet [CHAR LIMIT=NONE] -->
@@ -872,13 +606,9 @@
<!-- QuickSettings: networks unavailable [CHAR LIMIT=NONE] -->
<string name="quick_settings_networks_unavailable">Networks unavailable</string>
<!-- QuickSettings: Wifi (Not connected) [CHAR LIMIT=NONE] -->
- <string name="quick_settings_wifi_not_connected">Not Connected</string>
<!-- QuickSettings: Wifi (No network) [CHAR LIMIT=NONE] -->
- <string name="quick_settings_wifi_no_network">No Network</string>
<!-- QuickSettings: Wifi (Off) [CHAR LIMIT=NONE] -->
- <string name="quick_settings_wifi_off_label">Wi-Fi Off</string>
<!-- QuickSettings: Wifi (On) [CHAR LIMIT=NONE] -->
- <string name="quick_settings_wifi_on_label">Wi-Fi On</string>
<!-- QuickSettings: Wifi detail panel, text when there are no items [CHAR LIMIT=NONE] -->
<string name="quick_settings_wifi_detail_empty_text">No Wi-Fi networks available</string>
<!-- QuickSettings: Wifi secondary label shown when the wifi is being enabled [CHAR LIMIT=NONE] -->
@@ -890,19 +620,15 @@
<!-- QuickSettings: Cast detail panel, default device name [CHAR LIMIT=NONE] -->
<string name="quick_settings_cast_device_default_name">Unnamed device</string>
<!-- QuickSettings: Cast detail panel, default device description [CHAR LIMIT=NONE] -->
- <string name="quick_settings_cast_device_default_description">Ready to cast</string>
<!-- QuickSettings: Cast detail panel, text when there are no items [CHAR LIMIT=NONE] -->
<string name="quick_settings_cast_detail_empty_text">No devices available</string>
<!-- QuickSettings: Cast unavailable, text when not connected to WiFi [CHAR LIMIT=NONE] -->
<string name="quick_settings_cast_no_wifi">Wi\u2011Fi not connected</string>
<!-- QuickSettings: Brightness dialog title [CHAR LIMIT=NONE] -->
<string name="quick_settings_brightness_dialog_title">Brightness</string>
- <!-- QuickSettings: Brightness dialog auto brightness button [CHAR LIMIT=NONE] -->
- <string name="quick_settings_brightness_dialog_auto_brightness_label">AUTO</string>
<!-- QuickSettings: Label for the toggle that controls whether display inversion is enabled. [CHAR LIMIT=NONE] -->
<string name="quick_settings_inversion_label">Invert colors</string>
<!-- QuickSettings: Label for the toggle that controls whether display color correction is enabled. [CHAR LIMIT=NONE] -->
- <string name="quick_settings_color_space_label">Color correction mode</string>
<!-- QuickSettings: Control panel: Label for button that navigates to settings. [CHAR LIMIT=NONE] -->
<string name="quick_settings_more_settings">More settings</string>
<!-- QuickSettings: Control panel: Label for button that navigates to user settings. [CHAR LIMIT=NONE] -->
@@ -918,7 +644,6 @@
<!-- QuickSettings: Control panel: Label for connecting device. [CHAR LIMIT=NONE] -->
<string name="quick_settings_connecting">Connecting...</string>
<!-- QuickSettings: Tethering. [CHAR LIMIT=NONE] -->
- <string name="quick_settings_tethering_label">Tethering</string>
<!-- QuickSettings: Hotspot. [CHAR LIMIT=NONE] -->
<string name="quick_settings_hotspot_label">Hotspot</string>
<!-- QuickSettings: Hotspot. Secondary label shown when the hotspot is being enabled [CHAR LIMIT=NONE] -->
@@ -932,7 +657,6 @@
<item quantity="other">%d devices</item>
</plurals>
<!-- QuickSettings: Notifications [CHAR LIMIT=NONE] -->
- <string name="quick_settings_notifications_label">Notifications</string>
<!-- QuickSettings: Flashlight [CHAR LIMIT=NONE] -->
<string name="quick_settings_flashlight_label">Flashlight</string>
<!-- QuickSettings: Flashlight, used when it's not available due to camera in use [CHAR LIMIT=NONE] -->
@@ -1013,31 +737,6 @@
<!-- QuickStep: Accessibility to toggle overview [CHAR LIMIT=40] -->
<string name="quick_step_accessibility_toggle_overview">Toggle Overview</string>
- <!-- Expanded Status Bar Header: Battery Charged [CHAR LIMIT=40] -->
- <string name="expanded_header_battery_charged">Charged</string>
-
- <!-- Expanded Status Bar Header: Charging, no known time [CHAR LIMIT=40] -->
- <string name="expanded_header_battery_charging">Charging</string>
-
- <!-- Expanded Status Bar Header: Charging, showing time left until charged [CHAR LIMIT=40] -->
- <string name="expanded_header_battery_charging_with_time"><xliff:g id="charging_time" example="2 hrs 25 min">%s</xliff:g> until full</string>
-
- <!-- Expanded Status Bar Header: Not charging [CHAR LIMIT=40] -->
- <string name="expanded_header_battery_not_charging">Not charging</string>
-
- <!-- Shows up when there is a user SSL CA Cert installed on the
- device. Indicates to the user that SSL traffic can be intercepted.
- If the text fits on one line (~14 chars), it should start with a
- linebreak to position it correctly. [CHAR LIMIT=45] -->
- <string name="ssl_ca_cert_warning">Network may\nbe monitored</string>
-
- <!-- Description of the unlock target in the Slide unlock screen. [CHAR LIMIT=NONE] -->
- <string name="description_target_search">Search</string>
- <!-- Description of the up direction in which one can to slide the handle in the Slide unlock screen. [CHAR LIMIT=NONE] -->
- <string name="description_direction_up">Slide up for <xliff:g id="target_description" example="Unlock">%s</xliff:g>.</string>
- <!-- Description of the left direction in which one can to slide the handle in the Slide unlock screen. [CHAR LIMIT=NONE] -->
- <string name="description_direction_left">"Slide left for <xliff:g id="target_description" example="Unlock">%s</xliff:g>.</string>
-
<!-- Zen mode: Priority only introduction message on first use -->
<string name="zen_priority_introduction">You won\'t be disturbed by sounds and vibrations, except from alarms, reminders, events, and callers you specify. You\'ll still hear anything you choose to play including music, videos, and games.</string>
@@ -1053,12 +752,6 @@
<!-- Zen mode: Total silence introduction message on first use (non-voice capable devices) -->
<string name="zen_silence_introduction">This blocks ALL sounds and vibrations, including from alarms, music, videos, and games.</string>
- <!-- Text for overflow card on Keyguard when there is not enough space for all notifications on Keyguard. [CHAR LIMIT=1] -->
- <string name="keyguard_more_overflow_text">+<xliff:g id="number_of_notifications" example="5">%d</xliff:g></string>
-
- <!-- An explanation for the visual speed bump in the notifications, which will appear when you click on it. [CHAR LIMIT=50] -->
- <string name="speed_bump_explanation">Less urgent notifications below</string>
-
<!-- Shows to explain the double tap interaction with notifications: After tapping a notification on Keyguard, this will explain users to tap again to launch a notification. [CHAR LIMIT=60] -->
<string name="notification_tap_again">Tap again to open</string>
@@ -1134,13 +827,10 @@
<string name="accessibility_multi_user_switch_switcher">Switch user</string>
<!-- Accessibility label for the button that opens the user switcher and announces the current user. -->
- <string name="accessibility_multi_user_switch_switcher_with_current">Switch user, current user <xliff:g id="current_user_name" example="John Doe">%s</xliff:g></string>
<!-- Accessibility label for the user icon on the lock screen. -->
- <string name="accessibility_multi_user_switch_inactive">Current user <xliff:g id="current_user_name" example="John Doe">%s</xliff:g></string>
<!-- Accessibility label for the button that opens the quick contact of the user. -->
- <string name="accessibility_multi_user_switch_quick_contact">Show profile</string>
<!-- Label for the adding a new user in the user switcher [CHAR LIMIT=35] -->
<string name="user_add_user">Add user</string>
@@ -1169,24 +859,6 @@
<!-- Notification when resuming an existing guest session: Action that continues with the current session [CHAR LIMIT=35] -->
<string name="guest_wipe_session_dontwipe">Yes, continue</string>
- <!-- Title of the notification shown to a new guest user [CHAR LIMIT=60] -->
- <string name="guest_notification_title">Guest user</string>
-
- <!-- Text of the notification shown to a new guest user [CHAR LIMIT=60] -->
- <string name="guest_notification_text">To delete apps and data, remove guest user</string>
-
- <!-- Remove action in the notification shown to a new guest user [CHAR LIMIT=30] -->
- <string name="guest_notification_remove_action">REMOVE GUEST</string>
-
- <!-- Title of the notification shown to logout the current user [CHAR LIMIT=60] -->
- <string name="user_logout_notification_title">Logout user</string>
-
- <!-- Text of the notification shown to logout the current user [CHAR LIMIT=60] -->
- <string name="user_logout_notification_text">Logout current user</string>
-
- <!-- Logout action in the notification shown to logout the current user [CHAR LIMIT=30] -->
- <string name="user_logout_notification_action">LOGOUT USER</string>
-
<!-- Title for add user confirmation dialog [CHAR LIMIT=30] -->
<string name="user_add_user_title" msgid="2108112641783146007">Add new user?</string>
@@ -1211,15 +883,6 @@
<!-- Label for button in confirmation dialog when exiting guest session [CHAR LIMIT=35] -->
<string name="user_remove_user_remove">Remove</string>
- <!-- Battery saver notification title. [CHAR LIMIT=60]-->
- <string name="battery_saver_notification_title">Battery Saver is on</string>
-
- <!-- Battery saver notification text. [CHAR LIMIT=60] -->
- <string name="battery_saver_notification_text">Reduces performance and background data</string>
-
- <!-- Battery saver notification action text. [CHAR LIMIT=60] -->
- <string name="battery_saver_notification_action_text">Turn off Battery Saver</string>
-
<!-- Media projection permission dialog warning text. [CHAR LIMIT=NONE] -->
<string name="media_projection_dialog_text"><xliff:g id="app_seeking_permission" example="Hangouts">%s</xliff:g> will have access to all of the information that is visible on your screen or played from your device while recording or casting. This includes information such as passwords, payment details, photos, messages, and audio that you play.</string>
@@ -1233,7 +896,6 @@
<string name="media_projection_dialog_title">Start recording or casting with <xliff:g id="app_seeking_permission" example="Hangouts">%s</xliff:g>?</string>
<!-- Media projection permission dialog permanent grant check box. [CHAR LIMIT=NONE] -->
- <string name="media_projection_remember_text">Don\'t show again</string>
<!-- The text to clear all notifications. [CHAR LIMIT=60] -->
<string name="clear_all_notifications_text">Clear all</string>
@@ -1268,15 +930,6 @@
<!-- Text which is shown in the notification shade when there are no notifications. [CHAR LIMIT=30] -->
<string name="empty_shade_text">No notifications</string>
- <!-- Footer profile owned text [CHAR LIMIT=50] -->
- <string name="profile_owned_footer">Profile may be monitored</string>
-
- <!-- Footer vpn present text [CHAR LIMIT=50] -->
- <string name="vpn_footer">Network may be monitored</string>
-
- <!-- Footer vpn present text [CHAR LIMIT=50] -->
- <string name="branded_vpn_footer">Network may be monitored</string>
-
<!-- Disclosure at the bottom of Quick Settings that indicates that parental controls are enabled. [CHAR LIMIT=100] -->
<string name="quick_settings_disclosure_parental_controls">This device is managed by your parent</string>
@@ -1337,12 +990,6 @@
<!-- Monitoring dialog title for device owned devices [CHAR LIMIT=35] -->
<string name="monitoring_title_device_owned">Device management</string>
- <!-- Monitoring dialog title for profile owned devices [CHAR LIMIT=35] -->
- <string name="monitoring_title_profile_owned">Profile monitoring</string>
-
- <!-- Monitoring dialog title for normal devices [CHAR LIMIT=35]-->
- <string name="monitoring_title">Network monitoring</string>
-
<!-- STOPSHIP Monitoring strings still need to be finalized and approved -->
<!-- Monitoring dialog subtitle for the section describing VPN [CHAR LIMIT=35]-->
<string name="monitoring_subtitle_vpn">VPN</string>
@@ -1353,12 +1000,6 @@
<!-- Monitoring dialog subtitle for the section describing certificate authorities [CHAR LIMIT=35]-->
<string name="monitoring_subtitle_ca_certificate">CA certificates</string>
- <!-- Monitoring dialog disable vpn button [CHAR LIMIT=30] -->
- <string name="disable_vpn">Disable VPN</string>
-
- <!-- Monitoring dialog disconnect vpn button [CHAR LIMIT=30] -->
- <string name="disconnect_vpn">Disconnect VPN</string>
-
<!-- Monitoring dialog label for button opening a page with more information on the admin's abilities [CHAR LIMIT=30] -->
<string name="monitoring_button_view_policies">View Policies</string>
@@ -1401,113 +1042,27 @@
<!-- Monitoring dialog: Description of an active VPN in the personal profile (as opposed to the work profile). [CHAR LIMIT=NONE]-->
<string name="monitoring_description_personal_profile_named_vpn">Your personal profile is connected to <xliff:g id="vpn_app" example="Foo VPN App">%1$s</xliff:g>, which can monitor your network activity, including emails, apps, and websites.</string>
- <!-- Monitoring dialog: Header indicating that the device is managed by a Device Owner app [CHAR LIMIT=80] -->
- <string name="monitoring_description_do_header_generic">Your device is managed by <xliff:g id="device_owner_app" example="Google Mobile Management">%1$s</xliff:g>.</string>
-
- <!-- Monitoring dialog: Header indicating that the device is managed by a Device Owner app [CHAR LIMIT=60] -->
- <string name="monitoring_description_do_header_with_name"><xliff:g id="organization_name" example="Foo, Inc.">%1$s</xliff:g> uses <xliff:g id="device_owner_app" example="Google Mobile Management">%2$s</xliff:g> to manage your device.</string>
-
- <!-- Monitoring dialog: Part of text body explaining what a Device Owner app can do [CHAR LIMIT=130] -->
- <string name="monitoring_description_do_body">Your admin can monitor and manage settings, corporate access, apps, data associated with your device, and your device\'s location information.</string>
-
- <!-- Monitoring dialog: Space that separates the body text and the "learn more" link that follows it. [CHAR LIMIT=5] -->
- <string name="monitoring_description_do_learn_more_separator">" "</string>
-
- <!-- Monitoring dialog: Link to learn more about what a Device Owner app can do [CHAR LIMIT=55] -->
- <string name="monitoring_description_do_learn_more">Learn more</string>
-
- <!-- Monitoring dialog: Part of text body explaining that a VPN is connected and what it can do, for devices managed by a Device Owner app [CHAR LIMIT=130] -->
- <string name="monitoring_description_do_body_vpn">You\'re connected to <xliff:g id="vpn_app">%1$s</xliff:g>, which can monitor your network activity, including emails, apps, and websites.</string>
-
<!-- Monitoring dialog: Space that separates the VPN body text and the "Open VPN Settings" link that follows it. [CHAR LIMIT=5] -->
<string name="monitoring_description_vpn_settings_separator">" "</string>
<!-- Monitoring dialog: Link to open the VPN settings page [CHAR LIMIT=60] -->
<string name="monitoring_description_vpn_settings">Open VPN settings</string>
- <!-- Monitoring dialog: Space that separates the CA certs body text and the "Open trusted credentials" link that follows it. [CHAR LIMIT=5] -->
- <string name="monitoring_description_ca_cert_settings_separator">" "</string>
-
- <!-- Monitoring dialog: Link to open the settings page containing CA certificates [CHAR LIMIT=NONE] -->
- <string name="monitoring_description_ca_cert_settings">Open trusted credentials</string>
-
- <!-- Monitoring dialog: Network logging text [CHAR LIMIT=400] -->
- <string name="monitoring_description_network_logging">Your admin has turned on network logging, which monitors traffic on your device.\n\nFor more information, contact your admin.</string>
-
- <!-- Monitoring dialog VPN text [CHAR LIMIT=400] -->
- <string name="monitoring_description_vpn">You gave an app permission to set up a VPN connection.\n\nThis app can monitor your device and network activity, including emails, apps, and websites.</string>
-
- <!-- Monitoring dialog VPN with profile owner text [CHAR LIMIT=400] -->
- <string name="monitoring_description_vpn_profile_owned">Your work profile is managed by <xliff:g id="organization">%1$s</xliff:g>.\n\nYour admin is capable of monitoring your network activity including emails, apps, and websites.\n\nFor more information, contact your admin.\n\nYou\'re also connected to a VPN, which can monitor your network activity.</string>
-
<!-- Dialog that a user can access via Quick Settings. [CHAR LIMIT=NONE]-->
<string name="monitoring_description_parental_controls">This device is managed by your parent. Your parent can see and manage information such as the apps you use, your location, and your screen time.</string>
-
<!-- Name for a generic legacy VPN connection [CHAR LIMIT=20] -->
<string name="legacy_vpn_name">VPN</string>
- <!-- Monitoring dialog text for single app (no profile or device owner) [CHAR LIMIT=400] -->
- <string name="monitoring_description_app">You\'re connected to
- <xliff:g id="application">%1$s</xliff:g>, which can monitor your network activity,
- including emails, apps, and websites.</string>
-
- <!-- Monitoring dialog text for single app (inside personal profile) [CHAR LIMIT=400] -->
- <string name="monitoring_description_app_personal">You\'re connected to <xliff:g id="application">%1$s</xliff:g>, which can monitor your personal network activity, including emails, apps, and websites.</string>
-
- <!-- Monitoring dialog text for single app (inside personal profile) [CHAR LIMIT=400] -->
- <string name="branded_monitoring_description_app_personal">You\'re connected to <xliff:g id="application">%1$s</xliff:g>, which can monitor your personal network activity, including emails, apps, and websites.</string>
-
- <!-- Monitoring dialog text for single app (inside work profile) [CHAR LIMIT=400] -->
- <string name="monitoring_description_app_work">Your work profile is managed by
- <xliff:g id="organization">%1$s</xliff:g>. The profile is connected to
- <xliff:g id="application">%2$s</xliff:g>, which can monitor your work network activity,
- including emails, apps, and websites.\n\nFor more information, contact your admin.</string>
-
- <!-- Monitoring dialog text for multiple apps (in personal and work profiles) [CHAR LIMIT=400] -->
- <string name="monitoring_description_app_personal_work">Your work profile is managed by
- <xliff:g id="organization">%1$s</xliff:g>. The profile is connected to
- <xliff:g id="application_work">%2$s</xliff:g>, which can monitor your work network activity,
- including emails, apps, and websites.\n\nYou\'re also connected to
- <xliff:g id="application_personal">%3$s</xliff:g>, which can monitor your personal network
- activity.</string>
-
<!-- Indication on the keyguard that appears when a trust agents unlocks the device. [CHAR LIMIT=40] -->
<string name="keyguard_indication_trust_unlocked">Kept unlocked by TrustAgent</string>
- <!-- Indication on the keyguard that appears when the user disables trust agents until the next time they unlock manually. [CHAR LIMIT=NONE] -->
- <string name="keyguard_indication_trust_disabled">Device will stay locked until you manually unlock</string>
-
- <!-- Indication on the keyguard that appears when trust agents unlocks the device and device is plugged in. [CHAR LIMIT=NONE] -->
- <string name="keyguard_indication_trust_unlocked_plugged_in"><xliff:g id="keyguard_indication" example="Kept unlocked by TrustAgent">%1$s</xliff:g>\n<xliff:g id="power_indication" example="Charging Slowly">%2$s</xliff:g></string>
-
- <!-- Title of notification educating the user about enabling notifications on the lockscreen. [CHAR LIMIT=40] -->
- <string name="hidden_notifications_title">Get notifications faster</string>
-
- <!-- Body of notification educating the user about enabling notifications on the lockscreen. [CHAR LIMIT=60] -->
- <string name="hidden_notifications_text">See them before you unlock</string>
-
- <!-- Cancel action for notification educating the user about enabling notifications on the lockscreen. [CHAR LIMIT=20] -->
- <string name="hidden_notifications_cancel">No thanks</string>
-
- <!-- continue action for notification educating the user about enabling notifications on the lockscreen. [CHAR LIMIT=20] -->
- <string name="hidden_notifications_setup">Set up</string>
-
<!-- Accessibility string for current zen mode and selected exit condition. A template that simply concatenates existing mode string and the current condition description. [CHAR LIMIT=20] -->
<string name="zen_mode_and_condition"><xliff:g id="zen_mode" example="Priority interruptions only">%1$s</xliff:g>. <xliff:g id="exit_condition" example="For one hour">%2$s</xliff:g></string>
- <!-- Button label for ending zen mode in the volume dialog -->
- <string name="volume_zen_end_now">Turn off now</string>
-
<!-- Content description for accessibility (not shown on the screen): volume dialog settings button. [CHAR LIMIT=NONE] -->
<string name="accessibility_volume_settings">Sound settings</string>
- <!-- Content description for accessibility (not shown on the screen): volume dialog expand button. [CHAR LIMIT=NONE] -->
- <string name="accessibility_volume_expand">Expand</string>
-
- <!-- Content description for accessibility (not shown on the screen): volume dialog collapse button. [CHAR LIMIT=NONE] -->
- <string name="accessibility_volume_collapse">Collapse</string>
-
<!-- Label for the odi caption initial tool tip. [CHAR LIMIT=28] -->
<string name="volume_odi_captions_tip">Automatically caption media</string>
@@ -1523,7 +1078,6 @@
<string name="volume_odi_captions_hint_disable">disable</string>
<!-- content description for audio output chooser [CHAR LIMIT=NONE]-->
- <string name="accessibility_output_chooser">Switch output device</string>
<!-- Screen pinning dialog title. -->
<string name="screen_pinning_title">App is pinned</string>
@@ -1555,13 +1109,10 @@
<!-- Hide quick settings tile confirmation title -->
- <string name="quick_settings_reset_confirmation_title">Hide <xliff:g id="tile_label" example="Hotspot">%1$s</xliff:g>?</string>
<!-- Hide quick settings tile confirmation message -->
- <string name="quick_settings_reset_confirmation_message">It will reappear the next time you turn it on in settings.</string>
<!-- Hide quick settings tile confirmation button -->
- <string name="quick_settings_reset_confirmation_button">Hide</string>
<!-- volume stream names. All nouns. -->
<string name="stream_voice_call">Call</string> <!-- STREAM_VOICE_CALL -->
@@ -1576,22 +1127,12 @@
<string name="stream_tts" translatable="false">Transmitted Through Speaker</string> <!-- STREAM_TTS -->
<string name="stream_accessibility">Accessibility</string> <!-- STREAM_ACCESSIBILITY -->
- <string name="ring_toggle_title">Calls</string>
<string name="volume_ringer_status_normal">Ring</string>
<string name="volume_ringer_status_vibrate">Vibrate</string>
<string name="volume_ringer_status_silent">Mute</string>
<!-- Shown in the header of quick settings to indicate to the user that their phone ringer is on vibrate. [CHAR_LIMIT=NONE] -->
- <string name="qs_status_phone_vibrate">Phone on vibrate</string>
<!-- Shown in the header of quick settings to indicate to the user that their phone ringer is on silent (muted). [CHAR_LIMIT=NONE] -->
- <string name="qs_status_phone_muted">Phone muted</string>
-
- <string name="volume_stream_muted" translatable="false">%s silent</string>
- <string name="volume_stream_vibrate" translatable="false">%s vibrate</string>
- <string name="volume_stream_suppressed" translatable="false">%1$s silent — %2$s</string>
- <string name="volume_stream_muted_dnd" translatable="false">%s silent — Total silence</string>
- <string name="volume_stream_limited_dnd" translatable="false">%s — Priority only</string>
- <string name="volume_stream_vibrate_dnd" translatable="false">%s vibrate — Priority only</string>
<string name="volume_stream_content_description_unmute">%1$s. Tap to unmute.</string>
<string name="volume_stream_content_description_vibrate">%1$s. Tap to set to vibrate. Accessibility services may be muted.</string>
@@ -1612,32 +1153,12 @@
<string name="volume_dialog_ringer_guidance_ring">Calls and notifications will ring (<xliff:g id="volume level" example="56">%1$s</xliff:g>)</string>
- <string name="output_title">Media output</string>
- <string name="output_calls_title">Phone call output</string>
- <string name="output_none_found">No devices found</string>
- <string name="output_none_found_service_off">No devices found. Try turning on <xliff:g id="service" example="Bluetooth">%1$s</xliff:g></string>
- <string name="output_service_bt">Bluetooth</string>
- <string name="output_service_wifi">Wi-Fi</string>
- <string name="output_service_bt_wifi">Bluetooth and Wi-Fi</string>
-
<!-- Name of special SystemUI debug settings -->
<string name="system_ui_tuner">System UI Tuner</string>
- <!-- Preference to show/hide embedded battery percentage [CHAR LIMIT=50] -->
- <string name="show_battery_percentage">Show embedded battery percentage</string>
-
- <!-- Summary for battery percentage preference [CHAR LIMIT=NONE] -->
- <string name="show_battery_percentage_summary">Show battery level percentage inside the status bar icon when not charging</string>
-
- <!-- Name of quick settings -->
- <string name="quick_settings">Quick Settings</string>
-
<!-- Name of status bar -->
<string name="status_bar">Status bar</string>
- <!-- Name of overview -->
- <string name="overview">Overview</string>
-
<!-- Name of System UI demo mode (mode with preset icons for screenshots) -->
<string name="demo_mode">System UI demo mode</string>
@@ -1661,7 +1182,6 @@
<!-- Label of the button at the bottom prompting user enter wallet app. [CHAR LIMIT=NONE] -->
<string name="wallet_app_button_label">Show all</string>
<!-- Label of the button underneath the card carousel prompting user unlock device. [CHAR LIMIT=NONE] -->
- <string name="wallet_action_button_label_unlock">Unlock to pay</string>
<!-- Secondary label of the quick access wallet tile if no card. [CHAR LIMIT=NONE] -->
<string name="wallet_secondary_label_no_card">Add a card</string>
<!-- Secondary label of the quick access wallet tile if wallet is still updating. [CHAR LIMIT=NONE] -->
@@ -1680,15 +1200,10 @@
<string name="status_bar_airplane">Airplane mode</string>
<!-- Description for adding a quick settings tile -->
- <string name="add_tile">Add tile</string>
<!-- Name of a quick settings tile controlled by broadcast -->
- <string name="broadcast_tile">Broadcast Tile</string>
<!-- For preview release. DO NOT TRANSLATE -->
- <string name="regrettable_lack_of_easter_egg">
- ¯\\_(ツ)_/¯
- </string>
<!-- Warning text when an alarm might be silenced by Do Not Disturb [CHAR LIMIT=NONE] -->
<string name="zen_alarm_warning_indef">You won\'t hear your next alarm <xliff:g id="when" example="at 7:00 AM">%1$s</xliff:g> unless you turn this off before then</string>
@@ -1732,29 +1247,7 @@
<!-- Dialog asking if the tuner should really be removed from settings [CHAR LIMIT=NONE]-->
<string name="remove_from_settings_prompt">Remove System UI Tuner from Settings and stop using all of its features?"</string>
- <!-- Displayed when user launches an app that was uninstalled [CHAR LIMIT=NONE] -->
- <string name="activity_not_found">Application is not installed on your device</string>
-
- <!-- Name of setting to show clock seconds [CHAR LIMIT=40] -->
- <string name="clock_seconds">Show clock seconds</string>
- <!-- Description of setting to show clock seconds [CHAR LIMIT=NONE] -->
- <string name="clock_seconds_desc">Show clock seconds in the status bar. May impact battery life.</string>
-
- <!-- Button that leads to page to rearrange quick settings tiles [CHAR LIMIT=60] -->
- <string name="qs_rearrange">Rearrange Quick Settings</string>
- <!-- Option to show brightness bar in quick settings [CHAR LIMIT=60] -->
- <string name="show_brightness">Show brightness in Quick Settings</string>
- <!-- Option to use new paging layout in quick settings [CHAR LIMIT=60] -->
- <string name="qs_paging" translatable="false">Use the new Quick Settings</string>
-
- <!-- Category in the System UI Tuner settings, where new/experimental
- settings are -->
- <string name="experimental">Experimental</string>
-
- <string name="qs_customize" translatable="false">Allow long-press customize in Quick Settings</string>
- <string name="qs_customize_info" translatable="false">Info</string>
<string name="qs_customize_remove" translatable="false">Remove</string>
- <string name="no_tiles_add" translatable="false">No tiles to add</string>
<!-- Dialog title asking if Bluetooth should be enabled [CHAR LIMIT=NONE] -->
<string name="enable_bluetooth_title">Turn on Bluetooth?</string>
@@ -1766,19 +1259,8 @@
<!-- Bluetooth enablement ok text [CHAR LIMIT=40] -->
<string name="enable_bluetooth_confirmation_ok">Turn on</string>
- <!-- [CHAR LIMIT=100] Notification importance option -->
- <string name="show_silently">Show notifications silently</string>
- <!-- [CHAR LIMIT=100] Notification importance option -->
- <string name="block">Block all notifications</string>
- <!-- [CHAR LIMIT=100] Notification importance option -->
- <string name="do_not_silence">Don\'t silence</string>
- <!-- [CHAR LIMIT=100] Notification importance option -->
- <string name="do_not_silence_block">Don\'t silence or block</string>
-
<!-- [CHAR LIMIT=NONE] Importance Tuner setting title -->
<string name="tuner_full_importance_settings">Power notification controls</string>
- <string name="tuner_full_importance_settings_on">On</string>
- <string name="tuner_full_importance_settings_off">Off</string>
<string name="power_notification_controls_description">With power notification controls, you can set an importance level from 0 to 5 for an app\'s notifications.
\n\n<b>Level 5</b>
\n- Show at the top of the notification list
@@ -1804,67 +1286,15 @@
\n- Block all notifications from the app
</string>
- <!-- Notification Inline Controls: Header for apps that are not yet using notification channels. -->
- <string name="notification_header_default_channel">Notifications</string>
-
- <!-- Notification Inline Controls: Shown when a channel's notifications are currently blocked -->
- <string name="notification_channel_disabled">You won\'t see these notifications anymore</string>
-
- <!-- Notification inline controls: Shown when a channel's notifications are minimized -->
- <string name="notification_channel_minimized">These notifications will be minimized</string>
-
- <!-- Notification inline controls: Shown when a channel's notifications are silenced [CHAR_LIMIT=100] -->
- <string name="notification_channel_silenced">These notifications will be shown silently</string>
-
- <!-- Notification inline controls: Shown when a channel's notifications are set to alert [CHAR_LIMIT=100] -->
- <string name="notification_channel_unsilenced">These notifications will alert you</string>
-
- <!-- Notification Inline controls: continue receiving notifications prompt, channel level -->
- <string name="inline_blocking_helper">You usually dismiss these notifications.
- \nKeep showing them?</string>
-
<!-- Notification Inline controls: button to dismiss the blocking helper [CHAR_LIMIT=20] -->
<string name="inline_done_button">Done</string>
<!-- Notification Inline controls: button to dismiss the blocking helper [CHAR_LIMIT=20] -->
<string name="inline_ok_button">Apply</string>
- <!-- Notification Inline controls: continue receiving notifications prompt, channel level -->
- <string name="inline_keep_showing">Keep showing these notifications?</string>
-
- <!-- Notification inline controls: block notifications button [CHAR_LIMIT=25] -->
- <string name="inline_stop_button">Stop notifications</string>
-
- <!-- Notification inline controls: button to deliver notifications silently from this channel [CHAR_LIMIT=30] -->
- <string name="inline_deliver_silently_button">Deliver Silently</string>
-
- <!-- Notification inline controls: button to block notifications from this channel [CHAR_LIMIT=20] -->
- <string name="inline_block_button">Block</string>
-
- <!-- Notification inline controls: keep getting notifications button [CHAR_LIMIT=25] -->
- <string name="inline_keep_button">Keep showing</string>
-
- <!-- Notification inline controls: minimize notifications button [CHAR_LIMIT=20] -->
- <string name="inline_minimize_button">Minimize</string>
-
- <!-- Notification inline controls: button to show notifications silently, without alerting the user [CHAR_LIMIT=35] -->
- <string name="inline_silent_button_silent">Silent</string>
-
- <!-- Notification inline controls: button to continue showing notifications silently [CHAR_LIMIT=35] -->
- <string name="inline_silent_button_stay_silent">Stay silent</string>
-
- <!-- Notification inline controls: button to make notifications alert the user [CHAR_LIMIT=35] -->
- <string name="inline_silent_button_alert">Alerting</string>
-
- <!-- Notification inline controls: button to continue alerting the user when notifications arrive [CHAR_LIMIT=35] -->
- <string name="inline_silent_button_keep_alerting">Keep alerting</string>
-
<!-- Notification inline controls: button to show block screen [CHAR_LIMIT=35] -->
<string name="inline_turn_off_notifications">Turn off notifications</string>
- <!-- Notification Inline controls: continue receiving notifications prompt, app level -->
- <string name="inline_keep_showing_app">Keep showing notifications from this app?</string>
-
<!-- [CHAR LIMIT=100] Notification Importance title -->
<string name="notification_silence_title">Silent</string>
@@ -1886,9 +1316,6 @@
<!-- [CHAR LIMIT=150] Conversation Notification Importance title: normal conversation level, with bubbling summary -->
<string name="notification_channel_summary_default_with_bubbles">May ring or vibrate based on phone settings. Conversations from <xliff:g id="app_name" example="YouTube">%1$s</xliff:g> bubble by default.</string>
- <!-- [CHAR LIMIT=150] Notification Importance title: bubble level summary -->
- <string name="notification_channel_summary_bubble">Keeps your attention with a floating shortcut to this content.</string>
-
<!-- [CHAR LIMIT=150] Notification Importance title: automatic importance level summary -->
<string name="notification_channel_summary_automatic">Have the system determine if this notification should make sound or vibration</string>
@@ -1910,9 +1337,6 @@
<string name="notification_channel_summary_priority_dnd">Shows at the top of conversation notifications and as a profile picture on lock screen, interrupts Do Not Disturb</string>
<string name="notification_channel_summary_priority_all">Shows at the top of conversation notifications and as a profile picture on lock screen, appears as a bubble, interrupts Do Not Disturb</string>
- <!--[CHAR LIMIT=30] Linkable text to Settings app -->
- <string name="notification_conversation_channel_settings">Settings</string>
-
<!-- [CHAR LIMIT=150] Notification Importance title: important conversation level -->
<string name="notification_priority_title">Priority</string>
@@ -1935,22 +1359,12 @@
<string name="see_more_title">See more</string>
<!-- Notification Inline controls: describes what the app is doing in the background [CHAR_LIMIT=NONE] -->
- <string name="appops_camera">This app is using the camera.</string>
<!-- Notification Inline controls: describes what the app is doing in the background [CHAR_LIMIT=NONE] -->
- <string name="appops_microphone">This app is using the microphone.</string>
<!-- Notification Inline controls: describes what the app is doing in the background [CHAR_LIMIT=NONE] -->
- <string name="appops_overlay">This app is displaying over other apps on your screen.</string>
<!-- Notification Inline controls: describes what the app is doing in the background [CHAR_LIMIT=NONE] -->
- <string name="appops_camera_mic">This app is using the microphone and camera.</string>
<!-- Notification Inline controls: describes what the app is doing in the background [CHAR_LIMIT=NONE] -->
- <string name="appops_camera_overlay">This app is displaying over other apps on your screen and using the camera.</string>
<!-- Notification Inline controls: describes what the app is doing in the background [CHAR_LIMIT=NONE] -->
- <string name="appops_mic_overlay">This app is displaying over other apps on your screen and using the microphone.</string>
<!-- Notification Inline controls: describes what the app is doing in the background [CHAR_LIMIT=NONE] -->
- <string name="appops_camera_mic_overlay">This app is displaying over other apps on your screen and using the microphone and camera.</string>
-
- <string name="notification_appops_settings">Settings</string>
- <string name="notification_appops_ok">OK</string>
<!-- Notification Inline controls: describes how the notification was adjusted [CHAR_LIMIT=NONE] -->
<string name="feedback_alerted">This notification was automatically <b>promoted to Default</b> by the system.</string>
@@ -1963,8 +1377,6 @@
<!-- Notification Inline controls: prompts the user for feedback [CHAR_LIMIT=NONE] -->
<string name="feedback_prompt">Let the developer know your feedback. Was this correct?</string>
<!-- Notification Inline controls: responds to user provided feedback [CHAR_LIMIT=NONE] -->
- <string name="feedback_response">Thanks for your feedback!</string>
- <string name="feedback_ok">OK</string>
<!-- Notification: Control panel: Accessibility description for expanded inline controls view, used
to control settings about notifications related to the current notification. -->
@@ -1974,31 +1386,12 @@
<string name="notification_channel_controls_closed_accessibility">Notification controls for <xliff:g id="app_name" example="YouTube">%1$s</xliff:g> closed</string>
<!-- Notification: Control panel: Accessibility description for switch that is used to enable
or disable notifications from this channel -->
- <string name="notification_channel_switch_accessibility">Allow notifications from this channel</string>
<!-- Notification: Control panel: Label for button that launches notification settings. Used
when this app has only defined a single channel for notifications. -->
<string name="notification_more_settings">More settings</string>
<!-- Notification: Control panel: Label for a link that launches notification settings in the
app that sent the notification. -->
<string name="notification_app_settings">Customize</string>
- <!-- Notification: Control panel: Label for button that dismisses control panel. [CHAR LIMIT=NONE] -->
- <string name="notification_done">Done</string>
- <!-- Notification: inline controls: undo block button -->
- <string name="inline_undo">Undo</string>
- <!-- Notification: Conversation: control panel, label for button that demotes notification from conversation to normal notification -->
- <string name="demote">Mark this notification as not a conversation</string>
-
- <!-- [CHAR LIMIT=100] This conversation is marked as important -->
- <string name="notification_conversation_favorite">Important conversation</string>
-
- <!-- [CHAR LIMIT=100] This conversation is not marked as important -->
- <string name="notification_conversation_unfavorite">Not an important conversation</string>
-
- <!-- [CHAR LIMIT=100] This conversation is silenced (will not make sound or vibrate)-->
- <string name="notification_conversation_mute">Silenced</string>
-
- <!-- [CHAR LIMIT=100] This conversation is alerting (may make sound and/or vibrate)-->
- <string name="notification_conversation_unmute">Alerting</string>
<!-- [CHAR LIMIT=100] Show notification as bubble -->
<string name="notification_conversation_bubble">Show bubble</string>
@@ -2006,9 +1399,6 @@
<!-- [CHAR LIMIT=100] Turn off bubbles for notification -->
<string name="notification_conversation_unbubble">Remove bubbles</string>
- <!-- [CHAR LIMIT=100] Add this conversation to home screen -->
- <string name="notification_conversation_home_screen">Add to home screen</string>
-
<!-- Notification: Menu row: Content description for menu items. [CHAR LIMIT=NONE] -->
<string name="notification_menu_accessibility"><xliff:g id="app_name" example="YouTube">%1$s</xliff:g> <xliff:g id="menu_description" example="notification controls">%2$s</xliff:g></string>
@@ -2021,9 +1411,6 @@
<!-- Notification: Menu row: Label for the snooze action shown in local context menu. [CHAR LIMIT=NONE] -->
<string name="notification_menu_snooze_action">Remind me</string>
- <!-- Notification: Menu row: Label for the snooze action shown in local context menu. [CHAR LIMIT=NONE] -->
- <string name="notification_menu_settings_action">Settings</string>
-
<!-- Notification: Snooze panel: Snooze undo button label. [CHAR LIMIT=50]-->
<string name="snooze_undo">Undo</string>
@@ -2045,17 +1432,12 @@
<item quantity="other">%d minutes</item>
</plurals>
- <!-- Title of the battery settings detail panel [CHAR LIMIT=20] -->
- <string name="battery_panel_title">Battery usage</string>
-
<!-- Summary of battery saver not available [CHAR LIMIT=NONE] -->
- <string name="battery_detail_charging_summary">Battery Saver not available during charging</string>
<!-- Title of switch for battery saver [CHAR LIMIT=NONE] -->
<string name="battery_detail_switch_title">Battery Saver</string>
<!-- Summary of switch for battery saver [CHAR LIMIT=NONE] -->
- <string name="battery_detail_switch_summary">Reduces performance and background data</string>
<!-- Name used for certain Keyboard keys on gamepads, e.g. "Button L1". -->
<string name="keyboard_key_button_template">Button <xliff:g id="name">%1$s</xliff:g></string>
@@ -2141,13 +1523,9 @@
<!-- User visible title for the keyboard shortcut that takes the user to the music app. -->
<string name="keyboard_shortcut_group_applications_music">Music</string>
<!-- User visible title for the keyboard shortcut that takes the user to the YouTube app. -->
- <string name="keyboard_shortcut_group_applications_youtube">YouTube</string>
<!-- User visible title for the keyboard shortcut that takes the user to the calendar app. -->
<string name="keyboard_shortcut_group_applications_calendar">Calendar</string>
- <!-- SysUI Tuner: Option to show full do not disturb panel in volume [CHAR LIMIT=60] -->
- <string name="tuner_full_zen_title">Show with volume controls</string>
-
<!-- SysUI Tuner: Label for screen about do not disturb settings [CHAR LIMIT=60] -->
<string name="volume_and_do_not_disturb">Do Not Disturb</string>
@@ -2155,15 +1533,9 @@
not disturb [CHAR LIMIT=60] -->
<string name="volume_dnd_silent">Volume buttons shortcut</string>
- <!-- SysUI Tuner: Switch to control volume up behavior [CHAR LIMIT=60] -->
- <string name="volume_up_silent">Exit Do Not Disturb on volume up</string>
-
<!-- Name of the battery icon in status bar [CHAR LIMIT=30] -->
<string name="battery">Battery</string>
- <!-- Name of the clock in status bar [CHAR LIMIT=30] -->
- <string name="clock">Clock</string>
-
<!-- Name of the headset in status bar [CHAR LIMIT=30] -->
<string name="headset">Headset</string>
@@ -2184,7 +1556,6 @@
<string name="accessibility_data_saver_on">Data Saver is on</string>
<!-- Accessibility description for data saver being off [CHAR LIMIT=NONE] -->
- <string name="accessibility_data_saver_off">Data Saver is off</string>
<!-- Label for feature switch [CHAR LIMIT=30] -->
<string name="switch_bar_on">On</string>
@@ -2213,10 +1584,6 @@
<!-- SysUI Tuner: Setting for button type in nav bar [CHAR LIMIT=60] -->
<string name="right_nav_bar_button_type">Extra right button type</string>
-
- <!-- SysUI Tuner: Added to nav bar option to indicate it is the default [CHAR LIMIT=60] -->
- <string name="nav_bar_default"> (default)</string>
-
<!-- SysUI Tuner: Labels for different types of navigation bar buttons [CHAR LIMIT=60] -->
<string-array name="nav_bar_buttons">
<item>Clipboard</item>
@@ -2246,16 +1613,11 @@
<item>space;space;left,back,home,recent,right</item>
</string-array>
- <!-- SysUI Tuner: Name of Combination Menu / Keyboard Switcher button [CHAR LIMIT=30] -->
- <string name="menu_ime">Keyboard switcher</string>
<!-- SysUI Tuner: Save the current settings [CHAR LIMIT=30] -->
<string name="save">Save</string>
<!-- SysUI Tuner: Reset to default settings [CHAR LIMIT=30] -->
<string name="reset">Reset</string>
- <!-- SysUI Tuner: Adjust button width dialog title [CHAR LIMIT=60] -->
- <string name="adjust_button_width">Adjust button width</string>
-
<!-- SysUI Tuner: Nav bar button that holds the clipboard [CHAR LIMIT=30] -->
<string name="clipboard">Clipboard</string>
@@ -2358,7 +1720,6 @@
<string name="accessibility_quick_settings_collapse">Close quick settings.</string>
<!-- accessibility label for alarm icon [CHAR LIMIT=NONE] -->
- <string name="accessibility_quick_settings_alarm_set">Alarm set.</string>
<!-- accessibility label for button to select user [CHAR LIMIT=NONE] -->
<string name="accessibility_quick_settings_user">Signed in as <xliff:g name="user" example="John">%s</xliff:g></string>
@@ -2373,7 +1734,6 @@
<string name="accessibility_quick_settings_open_details">Open details.</string>
<!-- accessibility label for quick settings items that are currently disabled. Must have a reason [CHAR LIMIT=NONE] -->
- <string name="accessibility_quick_settings_not_available">Unvailable due to <xliff:g name="reason" id="reason" example="Wifi not available">%s</xliff:g></string>
<!-- accessibility label for quick settings items that open a details page [CHAR LIMIT=NONE] -->
<string name="accessibility_quick_settings_open_settings">Open <xliff:g name="page" example="Bluetooth">%s</xliff:g> settings.</string>
@@ -2403,11 +1763,8 @@
<string name="tuner_lock_screen">Lock screen</string>
<!-- Tuner string -->
- <string name="change_theme_reboot" translatable="false">Changing the theme requires a restart.</string>
<!-- Tuner string -->
- <string name="theme" translatable="false">Theme</string>
<!-- Tuner string -->
- <string name="default_theme" translatable="false">Default</string>
<!-- Title for notification & dialog that the user's phone last shut down because it got too hot. [CHAR LIMIT=40] -->
<string name="thermal_shutdown_title">Phone turned off due to heat</string>
@@ -2543,15 +1900,6 @@
<!-- Prompt for when Do not disturb is on from automatic rule or app in QS [CHAR LIMIT=NONE] -->
<string name="qs_dnd_prompt_auto_rule_app">Do Not Disturb was turned on by an automatic rule or app.</string>
- <!-- Description of Do Not Disturb option in QS that ends at the specified time[CHAR LIMIT=20] -->
- <string name="qs_dnd_until">Until <xliff:g name="time">%s</xliff:g></string>
-
- <!-- Do Not Disturb button to keep the current settings [CHAR LIMIT=20] -->
- <string name="qs_dnd_keep">Keep</string>
-
- <!-- Do Not Disturb button to change the current settings [CHAR LIMIT=20] -->
- <string name="qs_dnd_replace">Replace</string>
-
<!-- Title of the "running foreground services" dialog. [CHAR LIMIT=NONE] -->
<string name="running_foreground_services_title">Apps running in background</string>
@@ -2593,8 +1941,6 @@
<string name="slice_permission_deny">Deny</string>
<!-- List of packages for which we don't want to show recents onboarding, add into overlay as needed. -->
- <string-array name="recents_onboarding_blacklisted_packages" translatable="false">
- </string-array>
<!-- The title of the notification to suggest enabling automatic battery saver. [CHAR LIMIT=NONE]-->
<string name="auto_saver_title">Tap to schedule Battery Saver</string>
@@ -2606,16 +1952,12 @@
<string name="no_auto_saver_action">No thanks</string>
<!-- The title of the dialog that tells that scheduled (i.e. automatic) battery saver has been turned on. [CHAR LIMIT=NONE]-->
- <string name="auto_saver_enabled_title">Battery Saver schedule turned on</string>
<!-- The content of the dialog that tells that scheduled (i.e. automatic) battery saver has been turned on. [CHAR LIMIT=NONE]-->
- <string name="auto_saver_enabled_text">Battery Saver will turn on automatically once battery goes below <xliff:g id="percentage">%d</xliff:g>%%.</string>
<!-- An action on the dialog that tells that scheduled (i.e. automatic) battery saver: open the battery saver setting. [CHAR LIMIT=NONE]-->
- <string name="open_saver_setting_action">Settings</string>
<!-- An action on the dialog that tells that scheduled (i.e. automatic) battery saver: user acknowledges and closes the dialog. [CHAR LIMIT=NONE]-->
- <string name="auto_saver_okay_action">Got it</string>
<!-- URl of the webpage that explains battery saver. -->
<string name="help_uri_battery_saver_learn_more_link_target" translatable="false"></string>
@@ -2625,7 +1967,6 @@
<string name="heap_dump_tile_name">Dump SysUI Heap</string>
<!-- Content description for ongoing privacy chip. Use with a single app [CHAR LIMIT=NONE]-->
- <string name="ongoing_privacy_chip_content_single_app"><xliff:g id="app" example="Example App">%1$s</xliff:g> is using your <xliff:g id="types_list" example="camera, location">%2$s</xliff:g>.</string>
<!-- Content description for ongoing privacy chip. Use with multiple apps [CHAR LIMIT=NONE]-->
<string name="ongoing_privacy_chip_content_multiple_apps">Applications are using your <xliff:g id="types_list" example="camera, location">%s</xliff:g>.</string>
@@ -2660,24 +2001,9 @@
<!-- Text for microphone app op [CHAR LIMIT=20]-->
<string name="privacy_type_microphone">microphone</string>
- <!-- Text for the quick setting tile for sensor privacy [CHAR LIMIT=30] -->
- <string name="sensor_privacy_mode">Sensors off</string>
-
- <!-- Name for device services grouping system uid apps in Ongoing Privacy Dialog [CHAR_LIMIT=NONE] -->
- <string name="device_services">Device Services</string>
-
<!-- What to show on the ambient display player when song doesn't have a title. [CHAR LIMIT=20] -->
<string name="music_controls_no_title">No title</string>
- <!-- Action in accessibility menu to move the stack of bubbles [CHAR LIMIT=20] -->
- <string name="bubble_accessibility_action_move">Move</string>
-
- <!-- Notification content text when the system navigation mode changes as a result of changing the default launcher [CHAR LIMIT=NONE] -->
- <string name="notification_content_system_nav_changed">System navigation updated. To make changes, go to Settings.</string>
-
- <!-- Notification content text when switching to a default launcher that supports gesture navigation [CHAR LIMIT=NONE] -->
- <string name="notification_content_gesture_nav_available">Go to Settings to update system navigation</string>
-
<!-- Title of the overlay warning the user to interact with the device or it will go to sleep. [CHAR LIMIT=25] -->
<string name="inattentive_sleep_warning_title">Standby</string>
@@ -2710,8 +2036,6 @@
<!-- Accessibility floating menu strings -->
<!-- Message for the accessibility floating button migration tooltip. It shows when the user use gestural navigation then upgrade their system. It will tell the user the accessibility gesture had been replaced by accessibility floating button. [CHAR LIMIT=100] -->
<string name="accessibility_floating_button_migration_tooltip">Accessibility button replaced the accessibility gesture\n\n<annotation id="link">View settings</annotation></string>
- <!-- Message for the accessibility floating button settings tooltip. It shows when the user use gestural navigation then upgrade their system. It will tell the user to have another option to switch from the accessibility gesture to a button. [CHAR LIMIT=100] -->
- <string name="accessibility_floating_button_switch_migration_tooltip">You can switch from the accessibility gesture to a button\n\n<annotation id="link">Settings</annotation></string>
<!-- Message for the accessibility floating button docking tooltip. It shows when the user first time drag the button. It will tell the user about docking behavior. [CHAR LIMIT=70] -->
<string name="accessibility_floating_button_docking_tooltip">Move button to the edge to hide it temporarily</string>
<!-- Action in accessibility menu to move the accessibility floating button to the top left of the screen. [CHAR LIMIT=30] -->
@@ -2786,9 +2110,6 @@
<string name="controls_dialog_ok">Add</string>
<!-- Controls dialog message. Indicates app that suggested this control [CHAR LIMIT=NONE] -->
<string name="controls_dialog_message">Suggested by <xliff:g id="app" example="System UI">%s</xliff:g></string>
- <!-- Controls dialog confirmation [CHAR LIMIT=30] -->
- <string name="controls_dialog_confirmation">Controls updated</string>
-
<!-- Controls tile secondary label when device is locked and user does not want access to controls from lockscreen [CHAR LIMIT=20] -->
<string name="controls_tile_locked">Device locked</string>
@@ -2798,14 +2119,10 @@
<string name="controls_pin_verify">Verify <xliff:g id="device" example="Backdoor lock">%s</xliff:g></string>
<!-- Controls PIN entry dialog, title when 1st attempt failed [CHAR LIMIT=30] -->
<string name="controls_pin_wrong">Wrong PIN</string>
- <!-- Controls PIN entry dialog, waiting to verify [CHAR LIMIT=30] -->
- <string name="controls_pin_verifying">Verifying\u2026</string>
<!-- Controls PIN entry dialog, text hint [CHAR LIMIT=30] -->
<string name="controls_pin_instructions">Enter PIN</string>
<!-- Controls PIN entry dialog, text hint, retry [CHAR LIMIT=30] -->
<string name="controls_pin_instructions_retry">Try another PIN</string>
- <!-- Controls confirmation dialog, waiting to confirm [CHAR LIMIT=30] -->
- <string name="controls_confirmation_confirming">Confirming\u2026</string>
<!-- Controls confirmation dialog, user prompt [CHAR LIMIT=NONE] -->
<string name="controls_confirmation_message">Confirm change for <xliff:g id="device" example="Backdoor lock">%s</xliff:g></string>
@@ -2844,9 +2161,6 @@
<!-- Error message indicating that a control timed out while waiting for an update [CHAR_LIMIT=30] -->
<string name="controls_error_timeout">Inactive, check app</string>
- <!-- Error message indicating that an unspecified error occurred while getting the status, and
- a retry will be attempted [CHAR LIMIT=30] -->
- <string name="controls_error_retryable">Error, retrying\u2026</string>
<!-- Error message indicating that the control is no longer available in the application [CHAR LIMIT=30] -->
<string name="controls_error_removed">Not found</string>
<!-- Title for dialog indicating that the control is no longer available in the application [CHAR LIMIT=30] -->
@@ -2859,11 +2173,6 @@
<string name="controls_error_generic">Can\u2019t load status</string>
<!-- Error message indicating that a control action failed [CHAR_LIMIT=30] -->
<string name="controls_error_failed">Error, try again</string>
- <!-- Stateless control message informing the user that a routine has started [CHAR_LIMIT=30] -->
- <string name="controls_in_progress">In progress</string>
- <!-- Tooltip informing user where the recently added controls are [CHAR_LIMIT=100] -->
- <string name="controls_added_tooltip">Open Quick Settings to see new controls</string>
-
<!-- Controls menu, add [CHAR_LIMIT=30] -->
<string name="controls_menu_add">Add controls</string>
<!-- Controls menu, edit [CHAR_LIMIT=30] -->
@@ -2878,7 +2187,7 @@
<!-- Summary for media output group with the active device count [CHAR LIMIT=NONE] -->
<string name="media_output_dialog_multiple_devices"><xliff:g id="count" example="2">%1$d</xliff:g> devices selected</string>
<!-- Summary for disconnected status [CHAR LIMIT=50] -->
- <string name="media_output_dialog_disconnected"><xliff:g id="device_name" example="My device">%1$s</xliff:g> (disconnected)</string>
+ <string name="media_output_dialog_disconnected">(disconnected)</string>
<!-- Summary for connecting error message [CHAR LIMIT=NONE] -->
<string name="media_output_dialog_connect_failed">Couldn\'t connect. Try again.</string>
<!-- Title for pairing item [CHAR LIMIT=60] -->
@@ -2901,8 +2210,6 @@
<string name="priority_conversations">Priority conversations</string>
<!--Text header for recent conversation tiles available to be added to the home screen [CHAR LIMIT=100] -->
<string name="recent_conversations">Recent conversations</string>
- <!-- Text for button dismissing configuration activity with no conversations [CHAR LIMIT=20] -->
- <string name="okay">Okay</string>
<!-- Timestamp for notification with exact time in days plural [CHAR LIMIT=25] -->
<string name="days_timestamp"><xliff:g id="duration" example="5">%1$s</xliff:g> days ago</string>
<!-- Timestamp for notification from one week ago[CHAR LIMIT=25] -->
@@ -2976,8 +2283,6 @@
<!-- Accessibility label for fingerprint sensor [CHAR LIMIT=NONE] -->
<string name="accessibility_fingerprint_label">Fingerprint sensor</string>
- <!-- Accessibility label for disabled udfps sensor [CHAR LIMIT=NONE] -->
- <string name="accessibility_udfps_disabled_button">Fingerprint sensor disabled</string>
<!-- Accessibility action for tapping on an affordance that will bring up the user's
pin/pattern/password bouncer (ie: "Double tap to authenticate") [CHAR LIMIT=NONE] -->
<string name="accessibility_authenticate_hint">authenticate</string>
@@ -3012,8 +2317,6 @@
<string name="all_network_unavailable">No networks available</string>
<!-- Provider Model: Panel title text for turning on the Wi-Fi networks. [CHAR LIMIT=40] -->
<string name="turn_on_wifi">Wi\u2011Fi</string>
- <!-- Provider Model: Title for detail page of wifi network [CHAR LIMIT=30] -->
- <string name="pref_title_network_details" msgid="7329759534269363308">"Network details"</string>
<!-- Provider Model: Panel subtitle for tapping a network to connect to internet. [CHAR LIMIT=60] -->
<string name="tap_a_network_to_connect">Tap a network to connect</string>
<!-- Provider Model: Panel subtitle for unlocking screen to view networks. [CHAR LIMIT=60] -->
diff --git a/packages/SystemUI/res/values/strings_tv.xml b/packages/SystemUI/res/values/strings_tv.xml
index 649e80e..1b96ad6 100644
--- a/packages/SystemUI/res/values/strings_tv.xml
+++ b/packages/SystemUI/res/values/strings_tv.xml
@@ -18,8 +18,6 @@
-->
<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<!-- Title and subtitle for AudioRecordingIndicator -->
- <string name="mic_active">Microphone Active</string>
- <string name="app_accessed_mic">%1$s accessed your microphone</string>
<string name="notification_vpn_connected">VPN is connected</string>
<string name="notification_vpn_disconnected">VPN is disconnected</string>
diff --git a/packages/SystemUI/res/values/styles.xml b/packages/SystemUI/res/values/styles.xml
index b6ef258..b83ac3d 100644
--- a/packages/SystemUI/res/values/styles.xml
+++ b/packages/SystemUI/res/values/styles.xml
@@ -16,30 +16,6 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android">
<!-- NOTE: Adding the androidprv: namespace to this file will break the studio build. -->
- <style name="ClearAllButtonDefaultMargins">
- <item name="android:layout_marginStart">0dp</item>
- <item name="android:layout_marginTop">0dp</item>
- <item name="android:layout_marginEnd">0dp</item>
- <item name="android:layout_marginBottom">0dp</item>
- </style>
-
- <style name="PipPhoneOverlayControlTheme" parent="@android:style/Theme.Material">
- <item name="android:windowIsTranslucent">true</item>
- <item name="android:windowNoTitle">true</item>
- <item name="android:windowContentOverlay">@null</item>
- <item name="android:windowBackground">@android:color/transparent</item>
- <item name="android:colorBackgroundCacheHint">@null</item>
- <item name="android:statusBarColor">@*android:color/transparent</item>
- <item name="android:windowAnimationStyle">@style/Animation.PipPhoneOverlayControl</item>
- </style>
-
- <style name="Animation.PipPhoneOverlayControl" parent="@android:style/Animation">
- <item name="android:activityOpenEnterAnimation">@anim/forced_resizable_enter</item>
-
- <!-- If the target stack doesn't have focus, we do a task to front animation. -->
- <item name="android:taskToFrontEnterAnimation">@anim/forced_resizable_enter</item>
- <item name="android:activityCloseExitAnimation">@anim/forced_resizable_exit</item>
- </style>
<!-- HybridNotification themes and styles -->
@@ -65,17 +41,6 @@
</style>
- <style name="TextAppearance.StatusBar.HeadsUp"
- parent="@*android:style/TextAppearance.StatusBar">
- </style>
-
- <style name="TextAppearance.StatusBar.SystemPanel"
- parent="@*android:style/TextAppearance.StatusBar">
- <item name="android:textAppearance">?android:attr/textAppearance</item>
- <item name="android:textStyle">normal</item>
- <item name="android:textColor">#FF808080</item>
- </style>
-
<style name="TextAppearance.StatusBar.Clock" parent="@*android:style/TextAppearance.StatusBar.Icon">
<item name="android:textSize">@dimen/status_bar_clock_size</item>
<item name="android:fontFamily">@*android:string/config_headlineFontFamilyMedium</item>
@@ -172,11 +137,6 @@
<item name="android:textColor">?android:attr/textColorPrimary</item>
</style>
- <style name="TextAppearance.QS.Subhead">
- <item name="android:textSize">14sp</item>
- <item name="android:textColor">@color/qs_subhead</item>
- </style>
-
<style name="TextAppearance.QS.SegmentedButton">
<item name="android:textSize">16sp</item>
<item name="android:fontFamily">@*android:string/config_bodyFontFamilyMedium</item>
@@ -211,16 +171,7 @@
<item name="android:textColor">?android:attr/textColorSecondary</item>
</style>
- <style name="TextAppearance.QS.UserSwitcher.Activated">
- <item name="android:fontWeight">700</item>
- <item name="android:textStyle">bold</item>
- </style>
-
<!-- This is hard coded to be sans-serif-condensed to match the icons -->
- <style name="TextAppearance.RATBadge" parent="@style/TextAppearance.QS.TileLabel.Secondary">
- <item name="android:fontFamily">sans-serif-condensed</item>
- <item name="android:textSize">@dimen/celltile_rat_type_size</item>
- </style>
<style name="TextAppearance.QS.Status">
<item name="android:fontFamily">@*android:string/config_bodyFontFamilyMedium</item>
@@ -247,10 +198,6 @@
<item name="android:textColor">?android:attr/textColorSecondary</item>
</style>
- <style name="TextAppearance.DeviceManagementDialog">
- <item name="android:textColor">?android:attr/textColorPrimary</item>
- </style>
-
<style name="TextAppearance.DeviceManagementDialog.Title" parent="@android:style/TextAppearance.DeviceDefault.DialogWindowTitle"/>
<style name="TextAppearance.AuthCredential">
@@ -318,11 +265,6 @@
<style name="Animation" />
- <style name="Animation.ShirtPocketPanel">
- <item name="android:windowEnterAnimation">@*android:anim/grow_fade_in_from_bottom</item>
- <item name="android:windowExitAnimation">@*android:anim/shrink_fade_out_from_bottom</item>
- </style>
-
<style name="Animation.NavigationBarFadeIn">
<item name="android:windowEnterAnimation">@anim/navbar_fade_in</item>
<item name="android:windowExitAnimation">@null</item>
@@ -332,8 +274,6 @@
</style>
<!-- Standard animations for hiding and showing the status bar. -->
- <style name="Animation.StatusBar">
- </style>
<style name="Theme.SystemUI" parent="@*android:style/Theme.DeviceDefault.SystemUI">
<item name="lightIconTheme">@style/DualToneLightTheme</item>
@@ -441,11 +381,6 @@
<item name="android:gravity">center</item>
</style>
- <style name="SearchPanelCircle">
- <item name="android:layout_width">match_parent</item>
- <item name="android:layout_height">match_parent</item>
- </style>
-
<style name="UserDetailView">
<item name="numColumns">3</item>
</style>
@@ -506,11 +441,6 @@
<item name="android:textColor">?android:attr/textColorSecondary</item>
</style>
- <style name="TextAppearance.Volume.Header.Secondary">
- <item name="android:textSize">12sp</item>
- <item name="android:textColor">?android:attr/textColorTertiary</item>
- </style>
-
<style name="VolumeButtons" parent="@android:style/Widget.Material.Button.Borderless">
<item name="android:background">@drawable/btn_borderless_rect</item>
</style>
@@ -536,15 +466,6 @@
<item name="android:fontFamily">@*android:string/config_headlineFontFamily</item>
</style>
- <style name="TextAppearance.NotificationInfo.Secondary">
- <item name="android:textSize">14sp</item>
- <item name="android:alpha">0.62</item>
- </style>
-
- <style name="TextAppearance.NotificationInfo.Title">
- <item name="android:textStyle">bold</item>
- </style>
-
<style name="TextAppearance.NotificationInfo.Button">
<item name="android:fontFamily">@*android:string/config_headlineFontFamilyMedium</item>
<item name="android:textSize">14sp</item>
@@ -966,10 +887,6 @@
<item name="android:textColor">?android:attr/textColorPrimary</item>
</style>
- <style name="Theme.SystemUI.Dialog.Internet">
- <item name="android:windowBackground">@drawable/internet_dialog_background</item>
- </style>
-
<style name="MainSwitch.Settingslib" parent="@android:style/Theme.DeviceDefault">
<item name="android:switchMinWidth">@dimen/settingslib_min_switch_width</item>
</style>
diff --git a/packages/SystemUI/shared/Android.bp b/packages/SystemUI/shared/Android.bp
index 4880b12..62e9d8b 100644
--- a/packages/SystemUI/shared/Android.bp
+++ b/packages/SystemUI/shared/Android.bp
@@ -45,7 +45,9 @@
":wm_shell-aidls",
":wm_shell_util-sources",
],
-
+ resource_dirs: [
+ "res",
+ ],
static_libs: [
"PluginCoreLib",
"androidx.dynamicanimation_dynamicanimation",
diff --git a/packages/SystemUI/res/layout/rotate_suggestion.xml b/packages/SystemUI/shared/res/layout/rotate_suggestion.xml
similarity index 90%
rename from packages/SystemUI/res/layout/rotate_suggestion.xml
rename to packages/SystemUI/shared/res/layout/rotate_suggestion.xml
index 1c3eedb..2fb775c 100644
--- a/packages/SystemUI/res/layout/rotate_suggestion.xml
+++ b/packages/SystemUI/shared/res/layout/rotate_suggestion.xml
@@ -18,15 +18,13 @@
android:layout_width="match_parent"
android:layout_height="match_parent"
>
-
- <com.android.systemui.navigationbar.buttons.KeyButtonView
+ <com.android.systemui.shared.rotation.FloatingRotationButtonView
android:id="@+id/rotate_suggestion"
android:layout_width="@dimen/floating_rotation_button_diameter"
android:layout_height="@dimen/floating_rotation_button_diameter"
- android:contentDescription="@string/accessibility_rotate_button"
android:paddingStart="@dimen/navigation_key_padding"
android:paddingEnd="@dimen/navigation_key_padding"
android:layout_gravity="bottom|left"
android:scaleType="center"
android:visibility="invisible" />
-</FrameLayout>
\ No newline at end of file
+</FrameLayout>
diff --git a/packages/SystemUI/res/values/arrays_tv.xml b/packages/SystemUI/shared/res/values-sw600dp/dimens.xml
similarity index 72%
copy from packages/SystemUI/res/values/arrays_tv.xml
copy to packages/SystemUI/shared/res/values-sw600dp/dimens.xml
index 9c77077..5d9e059 100644
--- a/packages/SystemUI/res/values/arrays_tv.xml
+++ b/packages/SystemUI/shared/res/values-sw600dp/dimens.xml
@@ -1,7 +1,5 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
-/**
- * Copyright (c) 2017, The Android Open Source Project
+<?xml version="1.0" encoding="utf-8"?><!--
+ * Copyright (c) 2021, 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,9 +12,8 @@
* 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>
- <string-array name="audio_recording_disclosure_exempt_apps" translatable="false">
- </string-array>
+ <dimen name="navigation_key_padding">25dp</dimen>
</resources>
diff --git a/packages/SystemUI/res/values/arrays_tv.xml b/packages/SystemUI/shared/res/values-sw900dp/dimens.xml
similarity index 63%
copy from packages/SystemUI/res/values/arrays_tv.xml
copy to packages/SystemUI/shared/res/values-sw900dp/dimens.xml
index 9c77077..3efa5e3 100644
--- a/packages/SystemUI/res/values/arrays_tv.xml
+++ b/packages/SystemUI/shared/res/values-sw900dp/dimens.xml
@@ -1,7 +1,5 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
-/**
- * Copyright (c) 2017, The Android Open Source Project
+<?xml version="1.0" encoding="utf-8"?><!--
+ * Copyright (c) 2021, 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,9 +12,12 @@
* 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>
- <string-array name="audio_recording_disclosure_exempt_apps" translatable="false">
- </string-array>
-</resources>
+ <!-- The maximum width of the navigation bar ripples. -->
+ <dimen name="key_button_ripple_max_width">76dp</dimen>
+
+ <!-- The padding around the navigation buttons -->
+ <dimen name="navigation_key_padding">0dp</dimen>
+</resources>
\ No newline at end of file
diff --git a/packages/SystemUI/shared/res/values/dimens.xml b/packages/SystemUI/shared/res/values/dimens.xml
new file mode 100644
index 0000000..b7f3328
--- /dev/null
+++ b/packages/SystemUI/shared/res/values/dimens.xml
@@ -0,0 +1,30 @@
+<?xml version="1.0" encoding="utf-8"?><!--
+ * Copyright (c) 2021, 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 maximum width of the navigation bar ripples. -->
+ <dimen name="key_button_ripple_max_width">95dp</dimen>
+
+ <dimen name="rounded_corner_content_padding">0dp</dimen>
+
+ <dimen name="navigation_key_padding">0dp</dimen>
+
+ <!-- Floating rotation button -->
+ <dimen name="floating_rotation_button_diameter">40dp</dimen>
+ <dimen name="floating_rotation_button_min_margin">20dp</dimen>
+ <dimen name="floating_rotation_button_taskbar_left_margin">20dp</dimen>
+ <dimen name="floating_rotation_button_taskbar_bottom_margin">10dp</dimen>
+</resources>
diff --git a/packages/SystemUI/src/com/android/systemui/navigationbar/buttons/KeyButtonRipple.java b/packages/SystemUI/shared/src/com/android/systemui/navigationbar/buttons/KeyButtonRipple.java
similarity index 95%
rename from packages/SystemUI/src/com/android/systemui/navigationbar/buttons/KeyButtonRipple.java
rename to packages/SystemUI/shared/src/com/android/systemui/navigationbar/buttons/KeyButtonRipple.java
index e3e2367..53df0f3 100644
--- a/packages/SystemUI/src/com/android/systemui/navigationbar/buttons/KeyButtonRipple.java
+++ b/packages/SystemUI/shared/src/com/android/systemui/navigationbar/buttons/KeyButtonRipple.java
@@ -33,9 +33,11 @@
import android.view.View;
import android.view.ViewConfiguration;
import android.view.animation.Interpolator;
+import android.view.animation.PathInterpolator;
-import com.android.systemui.R;
-import com.android.systemui.animation.Interpolators;
+import androidx.annotation.Keep;
+
+import com.android.systemui.shared.R;
import java.util.ArrayList;
import java.util.HashSet;
@@ -47,6 +49,8 @@
private static final float GLOW_MAX_ALPHA_DARK = 0.1f;
private static final int ANIMATION_DURATION_SCALE = 350;
private static final int ANIMATION_DURATION_FADE = 450;
+ private static final Interpolator ALPHA_OUT_INTERPOLATOR =
+ new PathInterpolator(0f, 0f, 0.8f, 1f);
private Paint mRipplePaint;
private CanvasProperty<Float> mLeftProp;
@@ -184,19 +188,27 @@
}
}
+ /** Gets the glow alpha, used by {@link android.animation.ObjectAnimator} via reflection. */
+ @Keep
public float getGlowAlpha() {
return mGlowAlpha;
}
+ /** Sets the glow alpha, used by {@link android.animation.ObjectAnimator} via reflection. */
+ @Keep
public void setGlowAlpha(float x) {
mGlowAlpha = x;
invalidateSelf();
}
+ /** Gets the glow scale, used by {@link android.animation.ObjectAnimator} via reflection. */
+ @Keep
public float getGlowScale() {
return mGlowScale;
}
+ /** Sets the glow scale, used by {@link android.animation.ObjectAnimator} via reflection. */
+ @Keep
public void setGlowScale(float x) {
mGlowScale = x;
invalidateSelf();
@@ -326,7 +338,7 @@
private void exitSoftware() {
ObjectAnimator alphaAnimator = ObjectAnimator.ofFloat(this, "glowAlpha", mGlowAlpha, 0f);
- alphaAnimator.setInterpolator(Interpolators.ALPHA_OUT);
+ alphaAnimator.setInterpolator(ALPHA_OUT_INTERPOLATOR);
alphaAnimator.setDuration(ANIMATION_DURATION_FADE);
alphaAnimator.addListener(mAnimatorListener);
alphaAnimator.start();
@@ -449,7 +461,7 @@
final RenderNodeAnimator opacityAnim = new RenderNodeAnimator(mPaintProp,
RenderNodeAnimator.PAINT_ALPHA, 0);
opacityAnim.setDuration(ANIMATION_DURATION_FADE);
- opacityAnim.setInterpolator(Interpolators.ALPHA_OUT);
+ opacityAnim.setInterpolator(ALPHA_OUT_INTERPOLATOR);
opacityAnim.addListener(mAnimatorListener);
opacityAnim.addListener(mExitHwTraceAnimator);
opacityAnim.setTarget(mTargetView);
diff --git a/packages/SystemUI/src/com/android/systemui/navigationbar/gestural/FloatingRotationButton.java b/packages/SystemUI/shared/src/com/android/systemui/shared/rotation/FloatingRotationButton.java
similarity index 81%
rename from packages/SystemUI/src/com/android/systemui/navigationbar/gestural/FloatingRotationButton.java
rename to packages/SystemUI/shared/src/com/android/systemui/shared/rotation/FloatingRotationButton.java
index 4605795..be3d780 100644
--- a/packages/SystemUI/src/com/android/systemui/navigationbar/gestural/FloatingRotationButton.java
+++ b/packages/SystemUI/shared/src/com/android/systemui/shared/rotation/FloatingRotationButton.java
@@ -14,12 +14,14 @@
* limitations under the License.
*/
-package com.android.systemui.navigationbar.gestural;
+package com.android.systemui.shared.rotation;
+import android.annotation.StringRes;
import android.content.Context;
import android.content.res.Resources;
-import android.graphics.Color;
import android.graphics.PixelFormat;
+import android.graphics.drawable.AnimatedVectorDrawable;
+import android.graphics.drawable.Drawable;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
@@ -27,28 +29,25 @@
import android.view.animation.AccelerateDecelerateInterpolator;
import android.widget.FrameLayout;
-import com.android.systemui.R;
-import com.android.systemui.navigationbar.RotationButton;
-import com.android.systemui.navigationbar.RotationButtonController;
-import com.android.systemui.navigationbar.buttons.KeyButtonDrawable;
-import com.android.systemui.navigationbar.buttons.KeyButtonView;
-import com.android.systemui.navigationbar.gestural.FloatingRotationButtonPositionCalculator.Position;
+import androidx.core.view.OneShotPreDrawListener;
+
+import com.android.systemui.shared.R;
+import com.android.systemui.shared.rotation.FloatingRotationButtonPositionCalculator.Position;
/**
* Containing logic for the rotation button on the physical left bottom corner of the screen.
*/
public class FloatingRotationButton implements RotationButton {
- private static final float BACKGROUND_ALPHA = 0.92f;
private static final int MARGIN_ANIMATION_DURATION_MILLIS = 300;
private final WindowManager mWindowManager;
private final ViewGroup mKeyButtonContainer;
- private final KeyButtonView mKeyButtonView;
+ private final FloatingRotationButtonView mKeyButtonView;
private final int mContainerSize;
- private KeyButtonDrawable mKeyButtonDrawable;
+ private AnimatedVectorDrawable mAnimatedDrawable;
private boolean mIsShowing;
private boolean mCanShow = true;
private int mDisplayRotation;
@@ -62,12 +61,13 @@
private RotationButtonUpdatesCallback mUpdatesCallback;
private Position mPosition;
- public FloatingRotationButton(Context context) {
+ public FloatingRotationButton(Context context, @StringRes int contentDescription) {
mWindowManager = context.getSystemService(WindowManager.class);
mKeyButtonContainer = (ViewGroup) LayoutInflater.from(context).inflate(
R.layout.rotate_suggestion, null);
mKeyButtonView = mKeyButtonContainer.findViewById(R.id.rotate_suggestion);
mKeyButtonView.setVisibility(View.VISIBLE);
+ mKeyButtonView.setContentDescription(context.getString(contentDescription));
Resources res = context.getResources();
@@ -113,6 +113,10 @@
mIsShowing = true;
int flags = WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE;
+
+ // TODO(b/200103245): add new window type that has z-index above
+ // TYPE_NAVIGATION_BAR_PANEL as currently it could be below the taskbar which has
+ // the same window type
final WindowManager.LayoutParams lp = new WindowManager.LayoutParams(
mContainerSize,
mContainerSize,
@@ -134,14 +138,18 @@
updateTranslation(mPosition, /* animate */ false);
mWindowManager.addView(mKeyButtonContainer, lp);
- if (mKeyButtonDrawable != null && mKeyButtonDrawable.canAnimate()) {
- mKeyButtonDrawable.resetAnimation();
- mKeyButtonDrawable.startAnimation();
+ if (mAnimatedDrawable != null) {
+ mAnimatedDrawable.reset();
+ mAnimatedDrawable.start();
}
- if (mUpdatesCallback != null) {
- mUpdatesCallback.onVisibilityChanged(true);
- }
+ // Notify about visibility only after first traversal so we can properly calculate
+ // the touch region for the button
+ OneShotPreDrawListener.add(mKeyButtonView, () -> {
+ if (mIsShowing && mUpdatesCallback != null) {
+ mUpdatesCallback.onVisibilityChanged(true);
+ }
+ });
return true;
}
@@ -166,12 +174,10 @@
@Override
public void updateIcon(int lightIconColor, int darkIconColor) {
- Color ovalBackgroundColor = Color.valueOf(Color.red(darkIconColor),
- Color.green(darkIconColor), Color.blue(darkIconColor), BACKGROUND_ALPHA);
- mKeyButtonDrawable = KeyButtonDrawable.create(mRotationButtonController.getContext(),
- lightIconColor, darkIconColor, mRotationButtonController.getIconResId(),
- false /* shadow */, ovalBackgroundColor);
- mKeyButtonView.setImageDrawable(mKeyButtonDrawable);
+ mAnimatedDrawable = (AnimatedVectorDrawable) mKeyButtonView.getContext()
+ .getDrawable(mRotationButtonController.getIconResId());
+ mKeyButtonView.setImageDrawable(mAnimatedDrawable);
+ mKeyButtonView.setColors(lightIconColor, darkIconColor);
}
@Override
@@ -185,8 +191,8 @@
}
@Override
- public KeyButtonDrawable getImageDrawable() {
- return mKeyButtonDrawable;
+ public Drawable getImageDrawable() {
+ return mAnimatedDrawable;
}
@Override
@@ -202,6 +208,7 @@
}
}
+ @Override
public void onTaskbarStateChanged(boolean taskbarVisible, boolean taskbarStashed) {
mIsTaskbarVisible = taskbarVisible;
mIsTaskbarStashed = taskbarStashed;
diff --git a/packages/SystemUI/src/com/android/systemui/navigationbar/gestural/FloatingRotationButtonPositionCalculator.kt b/packages/SystemUI/shared/src/com/android/systemui/shared/rotation/FloatingRotationButtonPositionCalculator.kt
similarity index 94%
rename from packages/SystemUI/src/com/android/systemui/navigationbar/gestural/FloatingRotationButtonPositionCalculator.kt
rename to packages/SystemUI/shared/src/com/android/systemui/shared/rotation/FloatingRotationButtonPositionCalculator.kt
index 3ce51ad..ec3c073 100644
--- a/packages/SystemUI/src/com/android/systemui/navigationbar/gestural/FloatingRotationButtonPositionCalculator.kt
+++ b/packages/SystemUI/shared/src/com/android/systemui/shared/rotation/FloatingRotationButtonPositionCalculator.kt
@@ -1,4 +1,4 @@
-package com.android.systemui.navigationbar.gestural
+package com.android.systemui.shared.rotation
import android.view.Gravity
import android.view.Surface
@@ -7,7 +7,7 @@
* Calculates gravity and translation that is necessary to display
* the button in the correct position based on the current state
*/
-internal class FloatingRotationButtonPositionCalculator(
+class FloatingRotationButtonPositionCalculator(
private val defaultMargin: Int,
private val taskbarMarginLeft: Int,
private val taskbarMarginBottom: Int
diff --git a/packages/SystemUI/shared/src/com/android/systemui/shared/rotation/FloatingRotationButtonView.java b/packages/SystemUI/shared/src/com/android/systemui/shared/rotation/FloatingRotationButtonView.java
new file mode 100644
index 0000000..e0187f4
--- /dev/null
+++ b/packages/SystemUI/shared/src/com/android/systemui/shared/rotation/FloatingRotationButtonView.java
@@ -0,0 +1,81 @@
+/*
+ * Copyright (C) 2021 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.shared.rotation;
+
+import android.content.Context;
+import android.graphics.Canvas;
+import android.graphics.Color;
+import android.graphics.Paint;
+import android.graphics.PorterDuff;
+import android.graphics.PorterDuffColorFilter;
+import android.util.AttributeSet;
+import android.view.View;
+import android.widget.ImageView;
+
+import com.android.systemui.navigationbar.buttons.KeyButtonRipple;
+
+public class FloatingRotationButtonView extends ImageView {
+
+ private static final float BACKGROUND_ALPHA = 0.92f;
+
+ private final KeyButtonRipple mRipple;
+ private final Paint mOvalBgPaint = new Paint(Paint.ANTI_ALIAS_FLAG | Paint.FILTER_BITMAP_FLAG);
+
+ public FloatingRotationButtonView(Context context, AttributeSet attrs) {
+ this(context, attrs, 0);
+ }
+
+ public FloatingRotationButtonView(Context context, AttributeSet attrs, int defStyle) {
+ super(context, attrs, defStyle);
+
+ setClickable(true);
+
+ mRipple = new KeyButtonRipple(context, this);
+ setBackground(mRipple);
+ setWillNotDraw(false);
+ forceHasOverlappingRendering(false);
+ }
+
+ @Override
+ protected void onWindowVisibilityChanged(int visibility) {
+ super.onWindowVisibilityChanged(visibility);
+ if (visibility != View.VISIBLE) {
+ jumpDrawablesToCurrentState();
+ }
+ }
+
+ public void setColors(int lightColor, int darkColor) {
+ getDrawable().setColorFilter(new PorterDuffColorFilter(lightColor, PorterDuff.Mode.SRC_IN));
+
+ final int ovalBackgroundColor = Color.valueOf(Color.red(darkColor),
+ Color.green(darkColor), Color.blue(darkColor), BACKGROUND_ALPHA).toArgb();
+
+ mOvalBgPaint.setColor(ovalBackgroundColor);
+ mRipple.setType(KeyButtonRipple.Type.OVAL);
+ }
+
+ public void setDarkIntensity(float darkIntensity) {
+ mRipple.setDarkIntensity(darkIntensity);
+ }
+
+ @Override
+ public void draw(Canvas canvas) {
+ int d = Math.min(getWidth(), getHeight());
+ canvas.drawOval(0, 0, d, d, mOvalBgPaint);
+ super.draw(canvas);
+ }
+}
diff --git a/packages/SystemUI/shared/src/com/android/systemui/shared/rotation/RotationButton.java b/packages/SystemUI/shared/src/com/android/systemui/shared/rotation/RotationButton.java
new file mode 100644
index 0000000..89f71eb
--- /dev/null
+++ b/packages/SystemUI/shared/src/com/android/systemui/shared/rotation/RotationButton.java
@@ -0,0 +1,59 @@
+/*
+ * Copyright (C) 2021 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.shared.rotation;
+
+import android.graphics.drawable.Drawable;
+import android.view.View;
+
+/**
+ * Interface of a rotation button that interacts {@link RotationButtonController}.
+ * This interface exists because of the two different styles of rotation button in Sysui,
+ * one in contextual for 3 button nav and a floating rotation button for gestural.
+ */
+public interface RotationButton {
+ default void setRotationButtonController(RotationButtonController rotationButtonController) { }
+ default void setUpdatesCallback(RotationButtonUpdatesCallback updatesCallback) { }
+
+ default View getCurrentView() {
+ return null;
+ }
+ default boolean show() { return false; }
+ default boolean hide() { return false; }
+ default boolean isVisible() {
+ return false;
+ }
+ default void setCanShowRotationButton(boolean canShow) {}
+ default void onTaskbarStateChanged(boolean taskbarVisible, boolean taskbarStashed) {}
+ default void updateIcon(int lightIconColor, int darkIconColor) { }
+ default void setOnClickListener(View.OnClickListener onClickListener) { }
+ default void setOnHoverListener(View.OnHoverListener onHoverListener) { }
+ default Drawable getImageDrawable() {
+ return null;
+ }
+ default void setDarkIntensity(float darkIntensity) { }
+ default boolean acceptRotationProposal() {
+ return getCurrentView() != null;
+ }
+
+ /**
+ * Callback for updates provided by a rotation button
+ */
+ interface RotationButtonUpdatesCallback {
+ default void onVisibilityChanged(boolean isVisible) {};
+ default void onPositionChanged() {};
+ }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/navigationbar/RotationButtonController.java b/packages/SystemUI/shared/src/com/android/systemui/shared/rotation/RotationButtonController.java
similarity index 73%
rename from packages/SystemUI/src/com/android/systemui/navigationbar/RotationButtonController.java
rename to packages/SystemUI/shared/src/com/android/systemui/shared/rotation/RotationButtonController.java
index 0f5c03a..2dbd5de 100644
--- a/packages/SystemUI/src/com/android/systemui/navigationbar/RotationButtonController.java
+++ b/packages/SystemUI/shared/src/com/android/systemui/shared/rotation/RotationButtonController.java
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2020 The Android Open Source Project
+ * Copyright 2021 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,7 +14,9 @@
* limitations under the License.
*/
-package com.android.systemui.navigationbar;
+package com.android.systemui.shared.rotation;
+
+import static android.view.Display.DEFAULT_DISPLAY;
import static com.android.internal.view.RotationPolicy.NATURAL_ROTATION;
@@ -23,48 +25,51 @@
import android.animation.ObjectAnimator;
import android.annotation.ColorInt;
import android.annotation.DrawableRes;
+import android.annotation.SuppressLint;
import android.app.StatusBarManager;
import android.content.ContentResolver;
import android.content.Context;
+import android.graphics.drawable.AnimatedVectorDrawable;
+import android.graphics.drawable.Drawable;
import android.os.Handler;
import android.os.Looper;
import android.os.RemoteException;
import android.provider.Settings;
import android.util.Log;
-import android.view.IRotationWatcher.Stub;
+import android.view.IRotationWatcher;
import android.view.MotionEvent;
import android.view.Surface;
import android.view.View;
import android.view.WindowInsetsController;
-import android.view.WindowInsetsController.Behavior;
import android.view.WindowManagerGlobal;
import android.view.accessibility.AccessibilityManager;
+import android.view.animation.Interpolator;
+import android.view.animation.LinearInterpolator;
import com.android.internal.logging.UiEvent;
import com.android.internal.logging.UiEventLogger;
import com.android.internal.logging.UiEventLoggerImpl;
-import com.android.systemui.Dependency;
-import com.android.systemui.R;
-import com.android.systemui.animation.Interpolators;
-import com.android.systemui.navigationbar.RotationButton.RotationButtonUpdatesCallback;
-import com.android.systemui.navigationbar.buttons.KeyButtonDrawable;
+import com.android.internal.view.RotationPolicy;
+import com.android.systemui.shared.rotation.RotationButton.RotationButtonUpdatesCallback;
import com.android.systemui.shared.recents.utilities.Utilities;
import com.android.systemui.shared.recents.utilities.ViewRippler;
import com.android.systemui.shared.system.ActivityManagerWrapper;
import com.android.systemui.shared.system.TaskStackChangeListener;
import com.android.systemui.shared.system.TaskStackChangeListeners;
-import com.android.systemui.statusbar.policy.AccessibilityManagerWrapper;
-import com.android.systemui.statusbar.policy.RotationLockController;
import java.util.Optional;
import java.util.function.Consumer;
+import java.util.function.Supplier;
-/** Contains logic that deals with showing a rotate suggestion button with animation. */
+/**
+ * Contains logic that deals with showing a rotate suggestion button with animation.
+ */
public class RotationButtonController {
private static final String TAG = "StatusBar/RotationButtonController";
private static final int BUTTON_FADE_IN_OUT_DURATION_MS = 100;
private static final int NAVBAR_HIDDEN_PENDING_ICON_TIMEOUT_MS = 20000;
+ private static final Interpolator LINEAR_INTERPOLATOR = new LinearInterpolator();
private static final int NUM_ACCEPTED_ROTATION_SUGGESTIONS_FOR_INTRODUCTION = 3;
@@ -72,6 +77,7 @@
private final Handler mMainThreadHandler = new Handler(Looper.getMainLooper());
private final UiEventLogger mUiEventLogger = new UiEventLoggerImpl();
private final ViewRippler mViewRippler = new ViewRippler();
+ private final Supplier<Integer> mWindowRotationProvider;
private RotationButton mRotationButton;
private boolean mIsRecentsAnimationRunning;
@@ -79,17 +85,30 @@
private int mLastRotationSuggestion;
private boolean mPendingRotationSuggestion;
private boolean mHoveringRotationSuggestion;
- private RotationLockController mRotationLockController;
- private AccessibilityManagerWrapper mAccessibilityManagerWrapper;
- private TaskStackListenerImpl mTaskStackListener;
+ private final AccessibilityManager mAccessibilityManager;
+ private final TaskStackListenerImpl mTaskStackListener;
private Consumer<Integer> mRotWatcherListener;
+
private boolean mListenersRegistered = false;
private boolean mIsNavigationBarShowing;
- private @Behavior int mBehavior = WindowInsetsController.BEHAVIOR_DEFAULT;
+ @SuppressLint("InlinedApi")
+ private @WindowInsetsController.Behavior
+ int mBehavior = WindowInsetsController.BEHAVIOR_DEFAULT;
private boolean mSkipOverrideUserLockPrefsOnce;
- private int mLightIconColor;
- private int mDarkIconColor;
- private int mIconResId = R.drawable.ic_sysbar_rotate_button_ccw_start_90;
+ private final int mLightIconColor;
+ private final int mDarkIconColor;
+
+ @DrawableRes
+ private final int mIconCcwStart0ResId;
+ @DrawableRes
+ private final int mIconCcwStart90ResId;
+ @DrawableRes
+ private final int mIconCwStart0ResId;
+ @DrawableRes
+ private final int mIconCwStart90ResId;
+
+ @DrawableRes
+ private int mIconResId;
private final Runnable mRemoveRotationProposal =
() -> setRotateSuggestionButtonState(false /* visible */);
@@ -97,19 +116,20 @@
() -> mPendingRotationSuggestion = false;
private Animator mRotateHideAnimator;
- private final Stub mRotationWatcher = new Stub() {
+
+ private final IRotationWatcher.Stub mRotationWatcher = new IRotationWatcher.Stub() {
@Override
- public void onRotationChanged(final int rotation) throws RemoteException {
+ public void onRotationChanged(final int rotation) {
// We need this to be scheduled as early as possible to beat the redrawing of
// window in response to the orientation change.
mMainThreadHandler.postAtFrontOfQueue(() -> {
// If the screen rotation changes while locked, potentially update lock to flow with
// new screen rotation and hide any showing suggestions.
- if (mRotationLockController.isRotationLocked()) {
+ if (isRotationLocked()) {
if (shouldOverrideUserLockPrefs(rotation)) {
setRotationLockedAtAngle(rotation);
}
- setRotateSuggestionButtonState(false /* visible */, true /* hideImmediately */);
+ setRotateSuggestionButtonState(false /* visible */, true /* forced */);
}
if (mRotWatcherListener != null) {
@@ -121,27 +141,39 @@
/**
* Determines if rotation suggestions disabled2 flag exists in flag
+ *
* @param disable2Flags see if rotation suggestion flag exists in this flag
* @return whether flag exists
*/
- static boolean hasDisable2RotateSuggestionFlag(int disable2Flags) {
+ public static boolean hasDisable2RotateSuggestionFlag(int disable2Flags) {
return (disable2Flags & StatusBarManager.DISABLE2_ROTATE_SUGGESTIONS) != 0;
}
- RotationButtonController(Context context, @ColorInt int lightIconColor,
- @ColorInt int darkIconColor) {
+ public RotationButtonController(Context context,
+ @ColorInt int lightIconColor, @ColorInt int darkIconColor,
+ @DrawableRes int iconCcwStart0ResId,
+ @DrawableRes int iconCcwStart90ResId,
+ @DrawableRes int iconCwStart0ResId,
+ @DrawableRes int iconCwStart90ResId,
+ Supplier<Integer> windowRotationProvider) {
+
mContext = context;
mLightIconColor = lightIconColor;
mDarkIconColor = darkIconColor;
- mIsNavigationBarShowing = true;
- mRotationLockController = Dependency.get(RotationLockController.class);
- mAccessibilityManagerWrapper = Dependency.get(AccessibilityManagerWrapper.class);
+ mIconCcwStart0ResId = iconCcwStart0ResId;
+ mIconCcwStart90ResId = iconCcwStart90ResId;
+ mIconCwStart0ResId = iconCwStart0ResId;
+ mIconCwStart90ResId = iconCwStart90ResId;
+ mIconResId = mIconCcwStart90ResId;
+
+ mAccessibilityManager = AccessibilityManager.getInstance(context);
mTaskStackListener = new TaskStackListenerImpl();
+ mWindowRotationProvider = windowRotationProvider;
}
- void setRotationButton(RotationButton rotationButton,
- RotationButtonUpdatesCallback updatesCallback) {
+ public void setRotationButton(RotationButton rotationButton,
+ RotationButtonUpdatesCallback updatesCallback) {
mRotationButton = rotationButton;
mRotationButton.setRotationButtonController(this);
mRotationButton.setOnClickListener(this::onRotateSuggestionClick);
@@ -149,7 +181,24 @@
mRotationButton.setUpdatesCallback(updatesCallback);
}
- void registerListeners() {
+ public Context getContext() {
+ return mContext;
+ }
+
+ public void init() {
+ registerListeners();
+ if (mContext.getDisplay().getDisplayId() != DEFAULT_DISPLAY) {
+ // Currently there is no accelerometer sensor on non-default display, disable fixed
+ // rotation for non-default display
+ onDisable2FlagChanged(StatusBarManager.DISABLE2_ROTATE_SUGGESTIONS);
+ }
+ }
+
+ public void onDestroy() {
+ unregisterListeners();
+ }
+
+ public void registerListeners() {
if (mListenersRegistered) {
return;
}
@@ -157,18 +206,19 @@
mListenersRegistered = true;
try {
WindowManagerGlobal.getWindowManagerService()
- .watchRotation(mRotationWatcher, mContext.getDisplay().getDisplayId());
+ .watchRotation(mRotationWatcher, DEFAULT_DISPLAY);
} catch (IllegalArgumentException e) {
mListenersRegistered = false;
Log.w(TAG, "RegisterListeners for the display failed");
} catch (RemoteException e) {
- throw e.rethrowFromSystemServer();
+ Log.e(TAG, "RegisterListeners caught a RemoteException", e);
+ return;
}
TaskStackChangeListeners.getInstance().registerTaskStackListener(mTaskStackListener);
}
- void unregisterListeners() {
+ public void unregisterListeners() {
if (!mListenersRegistered) {
return;
}
@@ -177,34 +227,31 @@
try {
WindowManagerGlobal.getWindowManagerService().removeRotationWatcher(mRotationWatcher);
} catch (RemoteException e) {
- throw e.rethrowFromSystemServer();
+ Log.e(TAG, "UnregisterListeners caught a RemoteException", e);
+ return;
}
TaskStackChangeListeners.getInstance().unregisterTaskStackListener(mTaskStackListener);
}
- void setRotationCallback(Consumer<Integer> watcher) {
+ public void setRotationCallback(Consumer<Integer> watcher) {
mRotWatcherListener = watcher;
}
- void setRotationLockedAtAngle(int rotationSuggestion) {
- mRotationLockController.setRotationLockedAtAngle(true /* locked */, rotationSuggestion);
+ public void setRotationLockedAtAngle(int rotationSuggestion) {
+ RotationPolicy.setRotationLockAtAngle(mContext, true, rotationSuggestion);
}
public boolean isRotationLocked() {
- return mRotationLockController.isRotationLocked();
+ return RotationPolicy.isRotationLocked(mContext);
}
- void setRotateSuggestionButtonState(boolean visible) {
- setRotateSuggestionButtonState(visible, false /* hideImmediately */);
+ public void setRotateSuggestionButtonState(boolean visible) {
+ setRotateSuggestionButtonState(visible, false /* force */);
}
- /**
- * Change the visibility of rotate suggestion button. If {@code hideImmediately} is true,
- * it doesn't wait until the completion of the running animation.
- */
- void setRotateSuggestionButtonState(final boolean visible, final boolean hideImmediately) {
- // At any point the the button can become invisible because an a11y service became active.
+ void setRotateSuggestionButtonState(final boolean visible, final boolean force) {
+ // At any point the button can become invisible because an a11y service became active.
// Similarly, a call to make the button visible may be rejected because an a11y service is
// active. Must account for this.
// Rerun a show animation to indicate change but don't rerun a hide animation
@@ -213,7 +260,7 @@
final View view = mRotationButton.getCurrentView();
if (view == null) return;
- final KeyButtonDrawable currentDrawable = mRotationButton.getImageDrawable();
+ final Drawable currentDrawable = mRotationButton.getImageDrawable();
if (currentDrawable == null) return;
// Clear any pending suggestion flag as it has either been nullified or is being shown
@@ -232,11 +279,13 @@
view.setAlpha(1f);
// Run the rotate icon's animation if it has one
- if (currentDrawable.canAnimate()) {
- currentDrawable.resetAnimation();
- currentDrawable.startAnimation();
+ if (currentDrawable instanceof AnimatedVectorDrawable) {
+ ((AnimatedVectorDrawable) currentDrawable).reset();
+ ((AnimatedVectorDrawable) currentDrawable).start();
}
+ // TODO(b/187754252): No idea why this doesn't work. If we remove the "false"
+ // we see the animation show the pressed state... but it only shows the first time.
if (!isRotateSuggestionIntroduced()) mViewRippler.start(view);
// Set visibility unless a11y service is active.
@@ -244,7 +293,7 @@
} else { // Hide
mViewRippler.stop(); // Prevent any pending ripples, force hide or not
- if (hideImmediately) {
+ if (force) {
// If a hide animator is running stop it and make invisible
if (mRotateHideAnimator != null && mRotateHideAnimator.isRunning()) {
mRotateHideAnimator.pause();
@@ -258,7 +307,7 @@
ObjectAnimator fadeOut = ObjectAnimator.ofFloat(view, "alpha", 0f);
fadeOut.setDuration(BUTTON_FADE_IN_OUT_DURATION_MS);
- fadeOut.setInterpolator(Interpolators.LINEAR);
+ fadeOut.setInterpolator(LINEAR_INTERPOLATOR);
fadeOut.addListener(new AnimatorListenerAdapter() {
@Override
public void onAnimationEnd(Animator animation) {
@@ -271,29 +320,34 @@
}
}
- void setRecentsAnimationRunning(boolean running) {
+ public void setDarkIntensity(float darkIntensity) {
+ mRotationButton.setDarkIntensity(darkIntensity);
+ }
+
+ public void setRecentsAnimationRunning(boolean running) {
mIsRecentsAnimationRunning = running;
updateRotationButtonStateInOverview();
}
- void setHomeRotationEnabled(boolean enabled) {
+ public void setHomeRotationEnabled(boolean enabled) {
mHomeRotationEnabled = enabled;
updateRotationButtonStateInOverview();
}
private void updateRotationButtonStateInOverview() {
if (mIsRecentsAnimationRunning && !mHomeRotationEnabled) {
- setRotateSuggestionButtonState(false, true /* hideImmediately */ );
+ setRotateSuggestionButtonState(false, true /* hideImmediately */);
}
}
- void setDarkIntensity(float darkIntensity) {
- mRotationButton.setDarkIntensity(darkIntensity);
- }
+ public void onRotationProposal(int rotation, boolean isValid) {
+ int windowRotation = mWindowRotationProvider.get();
- void onRotationProposal(int rotation, int windowRotation, boolean isValid) {
- if (!mRotationButton.acceptRotationProposal() || (!mHomeRotationEnabled
- && mIsRecentsAnimationRunning)) {
+ if (!mRotationButton.acceptRotationProposal()) {
+ return;
+ }
+
+ if (!mHomeRotationEnabled && mIsRecentsAnimationRunning) {
return;
}
@@ -316,13 +370,9 @@
mLastRotationSuggestion = rotation; // Remember rotation for click
final boolean rotationCCW = Utilities.isRotationAnimationCCW(windowRotation, rotation);
if (windowRotation == Surface.ROTATION_0 || windowRotation == Surface.ROTATION_180) {
- mIconResId = rotationCCW
- ? R.drawable.ic_sysbar_rotate_button_ccw_start_90
- : R.drawable.ic_sysbar_rotate_button_cw_start_90;
+ mIconResId = rotationCCW ? mIconCcwStart0ResId : mIconCwStart0ResId;
} else { // 90 or 270
- mIconResId = rotationCCW
- ? R.drawable.ic_sysbar_rotate_button_ccw_start_0
- : R.drawable.ic_sysbar_rotate_button_ccw_start_0;
+ mIconResId = rotationCCW ? mIconCcwStart90ResId : mIconCwStart90ResId;
}
mRotationButton.updateIcon(mLightIconColor, mDarkIconColor);
@@ -339,23 +389,31 @@
}
}
- void onDisable2FlagChanged(int state2) {
+ public void onDisable2FlagChanged(int state2) {
final boolean rotateSuggestionsDisabled = hasDisable2RotateSuggestionFlag(state2);
if (rotateSuggestionsDisabled) onRotationSuggestionsDisabled();
}
- void onNavigationBarWindowVisibilityChange(boolean showing) {
+ public void onBehaviorChanged(int displayId, @WindowInsetsController.Behavior int behavior) {
+ if (DEFAULT_DISPLAY != displayId) {
+ return;
+ }
+
+ if (mBehavior != behavior) {
+ mBehavior = behavior;
+ showPendingRotationButtonIfNeeded();
+ }
+ }
+
+ public void onNavigationBarWindowVisibilityChange(boolean showing) {
if (mIsNavigationBarShowing != showing) {
mIsNavigationBarShowing = showing;
showPendingRotationButtonIfNeeded();
}
}
- void onBehaviorChanged(@Behavior int behavior) {
- if (mBehavior != behavior) {
- mBehavior = behavior;
- showPendingRotationButtonIfNeeded();
- }
+ public void onTaskbarStateChange(boolean visible, boolean stashed) {
+ getRotationButton().onTaskbarStateChanged(visible, stashed);
}
private void showPendingRotationButtonIfNeeded() {
@@ -364,31 +422,33 @@
}
}
- /** Return true when either the nav bar is visible or it's in visual immersive mode. */
+ /**
+ * Return true when either the task bar is visible or it's in visual immersive mode.
+ */
+ @SuppressLint("InlinedApi")
private boolean canShowRotationButton() {
return mIsNavigationBarShowing || mBehavior == WindowInsetsController.BEHAVIOR_DEFAULT;
}
- public Context getContext() {
- return mContext;
- }
-
- RotationButton getRotationButton() {
- return mRotationButton;
- }
-
- public @DrawableRes int getIconResId() {
+ @DrawableRes
+ public int getIconResId() {
return mIconResId;
}
- public @ColorInt int getLightIconColor() {
+ @ColorInt
+ public int getLightIconColor() {
return mLightIconColor;
}
- public @ColorInt int getDarkIconColor() {
+ @ColorInt
+ public int getDarkIconColor() {
return mDarkIconColor;
}
+ public RotationButton getRotationButton() {
+ return mRotationButton;
+ }
+
private void onRotateSuggestionClick(View v) {
mUiEventLogger.log(RotationButtonEvent.ROTATION_SUGGESTION_ACCEPTED);
incrementNumAcceptedRotationSuggestionsIfNeeded();
@@ -420,7 +480,7 @@
* avoid losing original user rotation when display rotation is changed by entering the fixed
* orientation overview.
*/
- void setSkipOverrideUserLockPrefsOnce() {
+ public void setSkipOverrideUserLockPrefsOnce() {
mSkipOverrideUserLockPrefsOnce = true;
}
@@ -451,7 +511,7 @@
}
private int computeRotationProposalTimeout() {
- return mAccessibilityManagerWrapper.getRecommendedTimeoutMillis(
+ return mAccessibilityManager.getRecommendedTimeoutMillis(
mHoveringRotationSuggestion ? 16000 : 5000,
AccessibilityManager.FLAG_CONTENT_CONTROLS);
}
@@ -513,11 +573,15 @@
ROTATION_SUGGESTION_ACCEPTED(207);
private final int mId;
+
RotationButtonEvent(int id) {
mId = id;
}
- @Override public int getId() {
+
+ @Override
+ public int getId() {
return mId;
}
}
}
+
diff --git a/packages/SystemUI/src-debug/com/android/systemui/flags/FeatureFlagManager.java b/packages/SystemUI/src-debug/com/android/systemui/flags/FeatureFlagManager.java
index 5b6845f..1eeb516 100644
--- a/packages/SystemUI/src-debug/com/android/systemui/flags/FeatureFlagManager.java
+++ b/packages/SystemUI/src-debug/com/android/systemui/flags/FeatureFlagManager.java
@@ -23,11 +23,18 @@
import android.os.Bundle;
import android.util.Log;
+import androidx.annotation.NonNull;
+
+import com.android.systemui.Dumpable;
import com.android.systemui.dagger.SysUISingleton;
+import com.android.systemui.dump.DumpManager;
import org.json.JSONException;
import org.json.JSONObject;
+import java.io.FileDescriptor;
+import java.io.PrintWriter;
+import java.util.ArrayList;
import java.util.HashMap;
import java.util.Map;
@@ -43,7 +50,7 @@
* To restore a flag back to its default, leave the `--ez value <0|1>` off of the command.
*/
@SysUISingleton
-public class FeatureFlagManager implements FlagReader, FlagWriter {
+public class FeatureFlagManager implements FlagReader, FlagWriter, Dumpable {
private static final String TAG = "SysUIFlags";
private static final String SYSPROP_PREFIX = "persist.systemui.flag_";
@@ -58,14 +65,17 @@
private final Map<Integer, Boolean> mBooleanFlagCache = new HashMap<>();
@Inject
- public FeatureFlagManager(SystemPropertiesHelper systemPropertiesHelper, Context context) {
+ public FeatureFlagManager(SystemPropertiesHelper systemPropertiesHelper, Context context,
+ DumpManager dumpManager) {
mSystemPropertiesHelper = systemPropertiesHelper;
IntentFilter filter = new IntentFilter(ACTION_SET_FLAG);
context.registerReceiver(mReceiver, filter, FLAGS_PERMISSION, null);
+ dumpManager.registerDumpable(TAG, this);
}
/** Return a {@link BooleanFlag}'s value. */
+ @Override
public boolean isEnabled(int id, boolean defaultValue) {
if (!mBooleanFlagCache.containsKey(id)) {
Boolean result = isEnabledInternal(id);
@@ -96,6 +106,7 @@
}
/** Set whether a given {@link BooleanFlag} is enabled or not. */
+ @Override
public void setEnabled(int id, boolean value) {
Boolean currentValue = isEnabledInternal(id);
if (currentValue != null && currentValue == value) {
@@ -127,8 +138,10 @@
Log.i(TAG, "Erase id " + id);
}
+ @Override
public void addListener(Listener run) {}
+ @Override
public void removeListener(Listener run) {}
private void restartSystemUI() {
@@ -186,4 +199,17 @@
}
}
};
+
+ @Override
+ public void dump(@NonNull FileDescriptor fd, @NonNull PrintWriter pw, @NonNull String[] args) {
+ pw.println("can override: true");
+ ArrayList<String> flagStrings = new ArrayList<>(mBooleanFlagCache.size());
+ for (Map.Entry<Integer, Boolean> entry : mBooleanFlagCache.entrySet()) {
+ flagStrings.add(" sysui_flag_" + entry.getKey() + ": " + entry.getValue());
+ }
+ flagStrings.sort(String.CASE_INSENSITIVE_ORDER);
+ for (String flagString : flagStrings) {
+ pw.println(flagString);
+ }
+ }
}
diff --git a/packages/SystemUI/src-release/com/android/systemui/flags/FeatureFlagManager.java b/packages/SystemUI/src-release/com/android/systemui/flags/FeatureFlagManager.java
new file mode 100644
index 0000000..e501a07
--- /dev/null
+++ b/packages/SystemUI/src-release/com/android/systemui/flags/FeatureFlagManager.java
@@ -0,0 +1,64 @@
+/*
+ * Copyright (C) 2021 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.flags;
+
+import android.content.Context;
+import android.util.SparseBooleanArray;
+
+import androidx.annotation.NonNull;
+
+import com.android.systemui.Dumpable;
+import com.android.systemui.dagger.SysUISingleton;
+import com.android.systemui.dump.DumpManager;
+
+import java.io.FileDescriptor;
+import java.io.PrintWriter;
+
+import javax.inject.Inject;
+
+/**
+ * Default implementation of the a Flag manager that returns default values for release builds
+ *
+ * There's a version of this file in src-debug which allows overriding, and has documentation about
+ * how to set flags.
+ */
+@SysUISingleton
+public class FeatureFlagManager implements FlagReader, FlagWriter, Dumpable {
+ SparseBooleanArray mAccessedFlags = new SparseBooleanArray();
+ @Inject
+ public FeatureFlagManager(SystemPropertiesHelper systemPropertiesHelper, Context context,
+ DumpManager dumpManager) {
+ dumpManager.registerDumpable("SysUIFlags", this);
+ }
+ @Override
+ public boolean isEnabled(int key, boolean defaultValue) {
+ mAccessedFlags.append(key, defaultValue);
+ return defaultValue;
+ }
+ @Override
+ public void setEnabled(int key, boolean value) {}
+
+ @Override
+ public void dump(@NonNull FileDescriptor fd, @NonNull PrintWriter pw, @NonNull String[] args) {
+ pw.println("can override: false");
+ int size = mAccessedFlags.size();
+ for (int i = 0; i < size; i++) {
+ pw.println(" sysui_flag_" + mAccessedFlags.keyAt(i)
+ + ": " + mAccessedFlags.valueAt(i));
+ }
+ }
+}
diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardDisplayManager.java b/packages/SystemUI/src/com/android/keyguard/KeyguardDisplayManager.java
index cac90ea..8c7ede2 100644
--- a/packages/SystemUI/src/com/android/keyguard/KeyguardDisplayManager.java
+++ b/packages/SystemUI/src/com/android/keyguard/KeyguardDisplayManager.java
@@ -49,7 +49,7 @@
public class KeyguardDisplayManager {
protected static final String TAG = "KeyguardDisplayManager";
- private static boolean DEBUG = KeyguardConstants.DEBUG;
+ private static final boolean DEBUG = KeyguardConstants.DEBUG;
private MediaRouter mMediaRouter = null;
private final DisplayManager mDisplayService;
diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardMessageArea.java b/packages/SystemUI/src/com/android/keyguard/KeyguardMessageArea.java
index 11eeac2..099dd5d 100644
--- a/packages/SystemUI/src/com/android/keyguard/KeyguardMessageArea.java
+++ b/packages/SystemUI/src/com/android/keyguard/KeyguardMessageArea.java
@@ -27,8 +27,10 @@
import android.util.AttributeSet;
import android.util.TypedValue;
import android.view.View;
+import android.view.ViewGroup;
import android.widget.TextView;
+import com.android.internal.policy.SystemBarUtils;
import com.android.settingslib.Utils;
import com.android.systemui.R;
@@ -55,6 +57,8 @@
private ColorStateList mNextMessageColorState = ColorStateList.valueOf(DEFAULT_COLOR);
private boolean mBouncerVisible;
private boolean mAltBouncerShowing;
+ private ViewGroup mContainer;
+ private int mTopMargin;
public KeyguardMessageArea(Context context, AttributeSet attrs) {
super(context, attrs);
@@ -65,6 +69,24 @@
}
@Override
+ protected void onAttachedToWindow() {
+ super.onAttachedToWindow();
+ mContainer = getRootView().findViewById(R.id.keyguard_message_area_container);
+ }
+
+ void onConfigChanged() {
+ final int newTopMargin = SystemBarUtils.getStatusBarHeight(getContext());
+ if (mTopMargin == newTopMargin) {
+ return;
+ }
+ mTopMargin = newTopMargin;
+ ViewGroup.MarginLayoutParams lp =
+ (ViewGroup.MarginLayoutParams) mContainer.getLayoutParams();
+ lp.topMargin = mTopMargin;
+ mContainer.setLayoutParams(lp);
+ }
+
+ @Override
public void setNextMessageColor(ColorStateList colorState) {
mNextMessageColorState = colorState;
}
diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardMessageAreaController.java b/packages/SystemUI/src/com/android/keyguard/KeyguardMessageAreaController.java
index 51ded3f..05318bb 100644
--- a/packages/SystemUI/src/com/android/keyguard/KeyguardMessageAreaController.java
+++ b/packages/SystemUI/src/com/android/keyguard/KeyguardMessageAreaController.java
@@ -17,6 +17,7 @@
package com.android.keyguard;
import android.content.res.ColorStateList;
+import android.content.res.Configuration;
import com.android.systemui.statusbar.policy.ConfigurationController;
import com.android.systemui.statusbar.policy.ConfigurationController.ConfigurationListener;
@@ -48,6 +49,11 @@
private ConfigurationListener mConfigurationListener = new ConfigurationListener() {
@Override
+ public void onConfigChanged(Configuration newConfig) {
+ mView.onConfigChanged();
+ }
+
+ @Override
public void onThemeChanged() {
mView.onThemeChanged();
}
diff --git a/packages/SystemUI/src/com/android/keyguard/clock/AnalogClockController.java b/packages/SystemUI/src/com/android/keyguard/clock/AnalogClockController.java
index 99e122e..7517dee 100644
--- a/packages/SystemUI/src/com/android/keyguard/clock/AnalogClockController.java
+++ b/packages/SystemUI/src/com/android/keyguard/clock/AnalogClockController.java
@@ -91,7 +91,7 @@
mResources = res;
mLayoutInflater = inflater;
mColorExtractor = colorExtractor;
- mClockPosition = new SmallClockPosition(res);
+ mClockPosition = new SmallClockPosition(inflater.getContext());
}
private void createViews() {
diff --git a/packages/SystemUI/src/com/android/keyguard/clock/BubbleClockController.java b/packages/SystemUI/src/com/android/keyguard/clock/BubbleClockController.java
index fac923c01..1add1a3 100644
--- a/packages/SystemUI/src/com/android/keyguard/clock/BubbleClockController.java
+++ b/packages/SystemUI/src/com/android/keyguard/clock/BubbleClockController.java
@@ -91,7 +91,7 @@
mResources = res;
mLayoutInflater = inflater;
mColorExtractor = colorExtractor;
- mClockPosition = new SmallClockPosition(res);
+ mClockPosition = new SmallClockPosition(inflater.getContext());
}
private void createViews() {
diff --git a/packages/SystemUI/src/com/android/keyguard/clock/SmallClockPosition.java b/packages/SystemUI/src/com/android/keyguard/clock/SmallClockPosition.java
index b304074..4e51b98 100644
--- a/packages/SystemUI/src/com/android/keyguard/clock/SmallClockPosition.java
+++ b/packages/SystemUI/src/com/android/keyguard/clock/SmallClockPosition.java
@@ -16,10 +16,11 @@
package com.android.keyguard.clock;
-import android.content.res.Resources;
+import android.content.Context;
import android.util.MathUtils;
import com.android.internal.annotations.VisibleForTesting;
+import com.android.internal.policy.SystemBarUtils;
import com.android.systemui.R;
/**
@@ -40,11 +41,11 @@
*/
private float mDarkAmount;
- SmallClockPosition(Resources res) {
- this(res.getDimensionPixelSize(R.dimen.status_bar_height),
- res.getDimensionPixelSize(R.dimen.keyguard_lock_padding),
- res.getDimensionPixelSize(R.dimen.keyguard_lock_height),
- res.getDimensionPixelSize(R.dimen.burn_in_prevention_offset_y)
+ SmallClockPosition(Context context) {
+ this(SystemBarUtils.getStatusBarHeight(context),
+ context.getResources().getDimensionPixelSize(R.dimen.keyguard_lock_padding),
+ context.getResources().getDimensionPixelSize(R.dimen.keyguard_lock_height),
+ context.getResources().getDimensionPixelSize(R.dimen.burn_in_prevention_offset_y)
);
}
diff --git a/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsEnrollProgressBarDrawable.java b/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsEnrollProgressBarDrawable.java
index b2a5409..11addf0 100644
--- a/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsEnrollProgressBarDrawable.java
+++ b/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsEnrollProgressBarDrawable.java
@@ -40,7 +40,7 @@
@Nullable private UdfpsEnrollHelper mEnrollHelper;
@NonNull private List<UdfpsEnrollProgressBarSegment> mSegments = new ArrayList<>();
- private int mTotalSteps = 1;
+ private int mTotalSteps = 0;
private int mProgressSteps = 0;
private boolean mIsShowingHelp = false;
@@ -67,22 +67,19 @@
void onEnrollmentProgress(int remaining, int totalSteps) {
mTotalSteps = totalSteps;
- updateState(getProgressSteps(remaining, totalSteps), false /* isShowingHelp */);
+
+ // Show some progress for the initial touch.
+ updateState(Math.max(1, totalSteps - remaining), false /* isShowingHelp */);
}
void onEnrollmentHelp(int remaining, int totalSteps) {
- updateState(getProgressSteps(remaining, totalSteps), true /* isShowingHelp */);
+ updateState(Math.max(0, totalSteps - remaining), true /* isShowingHelp */);
}
void onLastStepAcquired() {
updateState(mTotalSteps, false /* isShowingHelp */);
}
- private static int getProgressSteps(int remaining, int totalSteps) {
- // Show some progress for the initial touch.
- return Math.max(1, totalSteps - remaining);
- }
-
private void updateState(int progressSteps, boolean isShowingHelp) {
updateProgress(progressSteps);
updateFillColor(isShowingHelp);
diff --git a/packages/SystemUI/src/com/android/systemui/doze/DozeSensors.java b/packages/SystemUI/src/com/android/systemui/doze/DozeSensors.java
index 9d0591e..5c3e07f 100644
--- a/packages/SystemUI/src/com/android/systemui/doze/DozeSensors.java
+++ b/packages/SystemUI/src/com/android/systemui/doze/DozeSensors.java
@@ -659,7 +659,7 @@
@Override
@AnyThread
public void onTrigger(TriggerEvent event) {
- final Sensor sensor = mSensors[mDevicePosture];
+ final Sensor sensor = mSensors[mPosture];
mDozeLog.traceSensor(mPulseReason);
mHandler.post(mWakeLock.wrap(() -> {
if (DEBUG) Log.d(TAG, "onTrigger: " + triggerEventToString(event));
diff --git a/packages/SystemUI/src/com/android/systemui/egg/MLand.java b/packages/SystemUI/src/com/android/systemui/egg/MLand.java
deleted file mode 100644
index 0fb4432..0000000
--- a/packages/SystemUI/src/com/android/systemui/egg/MLand.java
+++ /dev/null
@@ -1,1440 +0,0 @@
-/*
- * Copyright (C) 2015 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.egg;
-
-import android.animation.LayoutTransition;
-import android.animation.TimeAnimator;
-import android.content.Context;
-import android.content.res.Resources;
-import android.graphics.Canvas;
-import android.graphics.Color;
-import android.graphics.Matrix;
-import android.graphics.Outline;
-import android.graphics.Paint;
-import android.graphics.Path;
-import android.graphics.PorterDuff;
-import android.graphics.PorterDuffColorFilter;
-import android.graphics.Rect;
-import android.graphics.drawable.Drawable;
-import android.graphics.drawable.GradientDrawable;
-import android.media.AudioAttributes;
-import android.media.AudioManager;
-import android.os.Vibrator;
-import android.util.AttributeSet;
-import android.util.Log;
-import android.view.Gravity;
-import android.view.InputDevice;
-import android.view.KeyEvent;
-import android.view.LayoutInflater;
-import android.view.MotionEvent;
-import android.view.View;
-import android.view.ViewGroup;
-import android.view.ViewOutlineProvider;
-import android.widget.FrameLayout;
-import android.widget.ImageView;
-import android.widget.TextView;
-
-import com.android.internal.logging.MetricsLogger;
-import com.android.systemui.R;
-
-import java.util.ArrayList;
-
-// It's like LLand, but "M"ultiplayer.
-public class MLand extends FrameLayout {
- public static final String TAG = "MLand";
-
- public static final boolean DEBUG = Log.isLoggable(TAG, Log.DEBUG);
- public static final boolean DEBUG_DRAW = false; // DEBUG
-
- public static final boolean SHOW_TOUCHES = true;
-
- public static void L(String s, Object ... objects) {
- if (DEBUG) {
- Log.d(TAG, objects.length == 0 ? s : String.format(s, objects));
- }
- }
-
- public static final float PI_2 = (float) (Math.PI/2);
-
- public static final boolean AUTOSTART = true;
- public static final boolean HAVE_STARS = true;
-
- public static final float DEBUG_SPEED_MULTIPLIER = 0.5f; // only if DEBUG
- public static final boolean DEBUG_IDDQD = Log.isLoggable(TAG + ".iddqd", Log.DEBUG);
-
- public static final int DEFAULT_PLAYERS = 1;
- public static final int MIN_PLAYERS = 1;
- public static final int MAX_PLAYERS = 6;
-
- static final float CONTROLLER_VIBRATION_MULTIPLIER = 2f;
-
- private static class Params {
- public float TRANSLATION_PER_SEC;
- public int OBSTACLE_SPACING, OBSTACLE_PERIOD;
- public int BOOST_DV;
- public int PLAYER_HIT_SIZE;
- public int PLAYER_SIZE;
- public int OBSTACLE_WIDTH, OBSTACLE_STEM_WIDTH;
- public int OBSTACLE_GAP;
- public int OBSTACLE_MIN;
- public int BUILDING_WIDTH_MIN, BUILDING_WIDTH_MAX;
- public int BUILDING_HEIGHT_MIN;
- public int CLOUD_SIZE_MIN, CLOUD_SIZE_MAX;
- public int STAR_SIZE_MIN, STAR_SIZE_MAX;
- public int G;
- public int MAX_V;
- public float SCENERY_Z, OBSTACLE_Z, PLAYER_Z, PLAYER_Z_BOOST, HUD_Z;
- public Params(Resources res) {
- TRANSLATION_PER_SEC = res.getDimension(R.dimen.translation_per_sec);
- OBSTACLE_SPACING = res.getDimensionPixelSize(R.dimen.obstacle_spacing);
- OBSTACLE_PERIOD = (int) (OBSTACLE_SPACING / TRANSLATION_PER_SEC);
- BOOST_DV = res.getDimensionPixelSize(R.dimen.boost_dv);
- PLAYER_HIT_SIZE = res.getDimensionPixelSize(R.dimen.player_hit_size);
- PLAYER_SIZE = res.getDimensionPixelSize(R.dimen.player_size);
- OBSTACLE_WIDTH = res.getDimensionPixelSize(R.dimen.obstacle_width);
- OBSTACLE_STEM_WIDTH = res.getDimensionPixelSize(R.dimen.obstacle_stem_width);
- OBSTACLE_GAP = res.getDimensionPixelSize(R.dimen.obstacle_gap);
- OBSTACLE_MIN = res.getDimensionPixelSize(R.dimen.obstacle_height_min);
- BUILDING_HEIGHT_MIN = res.getDimensionPixelSize(R.dimen.building_height_min);
- BUILDING_WIDTH_MIN = res.getDimensionPixelSize(R.dimen.building_width_min);
- BUILDING_WIDTH_MAX = res.getDimensionPixelSize(R.dimen.building_width_max);
- CLOUD_SIZE_MIN = res.getDimensionPixelSize(R.dimen.cloud_size_min);
- CLOUD_SIZE_MAX = res.getDimensionPixelSize(R.dimen.cloud_size_max);
- STAR_SIZE_MIN = res.getDimensionPixelSize(R.dimen.star_size_min);
- STAR_SIZE_MAX = res.getDimensionPixelSize(R.dimen.star_size_max);
-
- G = res.getDimensionPixelSize(R.dimen.G);
- MAX_V = res.getDimensionPixelSize(R.dimen.max_v);
-
- SCENERY_Z = res.getDimensionPixelSize(R.dimen.scenery_z);
- OBSTACLE_Z = res.getDimensionPixelSize(R.dimen.obstacle_z);
- PLAYER_Z = res.getDimensionPixelSize(R.dimen.player_z);
- PLAYER_Z_BOOST = res.getDimensionPixelSize(R.dimen.player_z_boost);
- HUD_Z = res.getDimensionPixelSize(R.dimen.hud_z);
-
- // Sanity checking
- if (OBSTACLE_MIN <= OBSTACLE_WIDTH / 2) {
- L("error: obstacles might be too short, adjusting");
- OBSTACLE_MIN = OBSTACLE_WIDTH / 2 + 1;
- }
- }
- }
-
- private TimeAnimator mAnim;
- private Vibrator mVibrator;
- private AudioManager mAudioManager;
- private final AudioAttributes mAudioAttrs = new AudioAttributes.Builder()
- .setUsage(AudioAttributes.USAGE_GAME).build();
-
- private View mSplash;
- private ViewGroup mScoreFields;
-
- private ArrayList<Player> mPlayers = new ArrayList<Player>();
- private ArrayList<Obstacle> mObstaclesInPlay = new ArrayList<Obstacle>();
-
- private float t, dt;
-
- private float mLastPipeTime; // in sec
- private int mCurrentPipeId; // basically, equivalent to the current score
- private int mWidth, mHeight;
- private boolean mAnimating, mPlaying;
- private boolean mFrozen; // after death, a short backoff
- private int mCountdown = 0;
- private boolean mFlipped;
-
- private int mTaps;
-
- private int mTimeOfDay;
- private static final int DAY = 0, NIGHT = 1, TWILIGHT = 2, SUNSET = 3;
- private static final int[][] SKIES = {
- { 0xFFc0c0FF, 0xFFa0a0FF }, // DAY
- { 0xFF000010, 0xFF000000 }, // NIGHT
- { 0xFF000040, 0xFF000010 }, // TWILIGHT
- { 0xFFa08020, 0xFF204080 }, // SUNSET
- };
-
- private int mScene;
- private static final int SCENE_CITY = 0, SCENE_TX = 1, SCENE_ZRH = 2;
- private static final int SCENE_COUNT = 3;
-
- private static Params PARAMS;
-
- private static float dp = 1f;
-
- private Paint mTouchPaint, mPlayerTracePaint;
-
- private ArrayList<Integer> mGameControllers = new ArrayList<>();
-
- public MLand(Context context) {
- this(context, null);
- }
-
- public MLand(Context context, AttributeSet attrs) {
- this(context, attrs, 0);
- }
-
- public MLand(Context context, AttributeSet attrs, int defStyle) {
- super(context, attrs, defStyle);
-
- mVibrator = (Vibrator) context.getSystemService(Context.VIBRATOR_SERVICE);
- mAudioManager = (AudioManager) context.getSystemService(Context.AUDIO_SERVICE);
- setFocusable(true);
- PARAMS = new Params(getResources());
- mTimeOfDay = irand(0, SKIES.length - 1);
- mScene = irand(0, SCENE_COUNT);
-
- mTouchPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
- mTouchPaint.setColor(0x80FFFFFF);
- mTouchPaint.setStyle(Paint.Style.FILL);
-
- mPlayerTracePaint = new Paint(Paint.ANTI_ALIAS_FLAG);
- mPlayerTracePaint.setColor(0x80FFFFFF);
- mPlayerTracePaint.setStyle(Paint.Style.STROKE);
- mPlayerTracePaint.setStrokeWidth(2 * dp);
-
- // we assume everything will be laid out left|top
- setLayoutDirection(LAYOUT_DIRECTION_LTR);
-
- setupPlayers(DEFAULT_PLAYERS);
-
- MetricsLogger.count(getContext(), "egg_mland_create", 1);
- }
-
- @Override
- public void onAttachedToWindow() {
- super.onAttachedToWindow();
- dp = getResources().getDisplayMetrics().density;
-
- reset();
- if (AUTOSTART) {
- start(false);
- }
- }
-
- @Override
- public boolean willNotDraw() {
- return !DEBUG;
- }
-
- public int getGameWidth() { return mWidth; }
- public int getGameHeight() { return mHeight; }
- public float getGameTime() { return t; }
- public float getLastTimeStep() { return dt; }
-
- public void setScoreFieldHolder(ViewGroup vg) {
- mScoreFields = vg;
- if (vg != null) {
- final LayoutTransition lt = new LayoutTransition();
- lt.setDuration(250);
- mScoreFields.setLayoutTransition(lt);
- }
- for (Player p : mPlayers) {
- mScoreFields.addView(p.mScoreField,
- new MarginLayoutParams(
- MarginLayoutParams.WRAP_CONTENT,
- MarginLayoutParams.MATCH_PARENT));
- }
- }
-
- public void setSplash(View v) {
- mSplash = v;
- }
-
- public static boolean isGamePad(InputDevice dev) {
- int sources = dev.getSources();
-
- // Verify that the device has gamepad buttons, control sticks, or both.
- return (((sources & InputDevice.SOURCE_GAMEPAD) == InputDevice.SOURCE_GAMEPAD)
- || ((sources & InputDevice.SOURCE_JOYSTICK) == InputDevice.SOURCE_JOYSTICK));
- }
-
- public ArrayList getGameControllers() {
- mGameControllers.clear();
- int[] deviceIds = InputDevice.getDeviceIds();
- for (int deviceId : deviceIds) {
- InputDevice dev = InputDevice.getDevice(deviceId);
- if (isGamePad(dev)) {
- if (!mGameControllers.contains(deviceId)) {
- mGameControllers.add(deviceId);
- }
- }
- }
- return mGameControllers;
- }
-
- public int getControllerPlayer(int id) {
- final int player = mGameControllers.indexOf(id);
- if (player < 0 || player >= mPlayers.size()) return 0;
- return player;
- }
-
- @Override
- protected void onSizeChanged(int w, int h, int oldw, int oldh) {
- dp = getResources().getDisplayMetrics().density;
-
- stop();
-
- reset();
- if (AUTOSTART) {
- start(false);
- }
- }
-
- final static float hsv[] = {0, 0, 0};
-
- private static float luma(int bgcolor) {
- return 0.2126f * (float) (bgcolor & 0xFF0000) / 0xFF0000
- + 0.7152f * (float) (bgcolor & 0xFF00) / 0xFF00
- + 0.0722f * (float) (bgcolor & 0xFF) / 0xFF;
- }
-
- public Player getPlayer(int i) {
- return i < mPlayers.size() ? mPlayers.get(i) : null;
- }
-
- private int addPlayerInternal(Player p) {
- mPlayers.add(p);
- realignPlayers();
- TextView scoreField = (TextView)
- LayoutInflater.from(getContext()).inflate(R.layout.mland_scorefield, null);
- if (mScoreFields != null) {
- mScoreFields.addView(scoreField,
- new MarginLayoutParams(
- MarginLayoutParams.WRAP_CONTENT,
- MarginLayoutParams.MATCH_PARENT));
- }
- p.setScoreField(scoreField);
- return mPlayers.size()-1;
- }
-
- private void removePlayerInternal(Player p) {
- if (mPlayers.remove(p)) {
- removeView(p);
- mScoreFields.removeView(p.mScoreField);
- realignPlayers();
- }
- }
-
- private void realignPlayers() {
- final int N = mPlayers.size();
- float x = (mWidth - (N-1) * PARAMS.PLAYER_SIZE) / 2;
- for (int i=0; i<N; i++) {
- final Player p = mPlayers.get(i);
- p.setX(x);
- x += PARAMS.PLAYER_SIZE;
- }
- }
-
- private void clearPlayers() {
- while (mPlayers.size() > 0) {
- removePlayerInternal(mPlayers.get(0));
- }
- }
-
- public void setupPlayers(int num) {
- clearPlayers();
- for (int i=0; i<num; i++) {
- addPlayerInternal(Player.create(this));
- }
- }
-
- public void addPlayer() {
- if (getNumPlayers() == MAX_PLAYERS) return;
- addPlayerInternal(Player.create(this));
- }
-
- public int getNumPlayers() {
- return mPlayers.size();
- }
-
- public void removePlayer() {
- if (getNumPlayers() == MIN_PLAYERS) return;
- removePlayerInternal(mPlayers.get(mPlayers.size() - 1));
- }
-
- private void thump(int playerIndex, long ms) {
- if (mAudioManager.getRingerMode() == AudioManager.RINGER_MODE_SILENT) {
- // No interruptions. Not even game haptics.
- return;
- }
- if (playerIndex < mGameControllers.size()) {
- int controllerId = mGameControllers.get(playerIndex);
- InputDevice dev = InputDevice.getDevice(controllerId);
- if (dev != null && dev.getVibrator().hasVibrator()) {
- dev.getVibrator().vibrate(
- (long) (ms * CONTROLLER_VIBRATION_MULTIPLIER),
- mAudioAttrs);
- return;
- }
- }
- mVibrator.vibrate(ms, mAudioAttrs);
- }
-
- public void reset() {
- L("reset");
- final Drawable sky = new GradientDrawable(
- GradientDrawable.Orientation.BOTTOM_TOP,
- SKIES[mTimeOfDay]
- );
- sky.setDither(true);
- setBackground(sky);
-
- mFlipped = frand() > 0.5f;
- setScaleX(mFlipped ? -1 : 1);
-
- int i = getChildCount();
- while (i-->0) {
- final View v = getChildAt(i);
- if (v instanceof GameView) {
- removeViewAt(i);
- }
- }
-
- mObstaclesInPlay.clear();
- mCurrentPipeId = 0;
-
- mWidth = getWidth();
- mHeight = getHeight();
-
- boolean showingSun = (mTimeOfDay == DAY || mTimeOfDay == SUNSET) && frand() > 0.25;
- if (showingSun) {
- final Star sun = new Star(getContext());
- sun.setBackgroundResource(R.drawable.sun);
- final int w = getResources().getDimensionPixelSize(R.dimen.sun_size);
- sun.setTranslationX(frand(w, mWidth-w));
- if (mTimeOfDay == DAY) {
- sun.setTranslationY(frand(w, (mHeight * 0.66f)));
- sun.getBackground().setTint(0);
- } else {
- sun.setTranslationY(frand(mHeight * 0.66f, mHeight - w));
- sun.getBackground().setTintMode(PorterDuff.Mode.SRC_ATOP);
- sun.getBackground().setTint(0xC0FF8000);
-
- }
- addView(sun, new LayoutParams(w, w));
- }
- if (!showingSun) {
- final boolean dark = mTimeOfDay == NIGHT || mTimeOfDay == TWILIGHT;
- final float ff = frand();
- if ((dark && ff < 0.75f) || ff < 0.5f) {
- final Star moon = new Star(getContext());
- moon.setBackgroundResource(R.drawable.moon);
- moon.getBackground().setAlpha(dark ? 255 : 128);
- moon.setScaleX(frand() > 0.5 ? -1 : 1);
- moon.setRotation(moon.getScaleX() * frand(5, 30));
- final int w = getResources().getDimensionPixelSize(R.dimen.sun_size);
- moon.setTranslationX(frand(w, mWidth - w));
- moon.setTranslationY(frand(w, mHeight - w));
- addView(moon, new LayoutParams(w, w));
- }
- }
-
- final int mh = mHeight / 6;
- final boolean cloudless = frand() < 0.25;
- final int N = 20;
- for (i=0; i<N; i++) {
- final float r1 = frand();
- final Scenery s;
- if (HAVE_STARS && r1 < 0.3 && mTimeOfDay != DAY) {
- s = new Star(getContext());
- } else if (r1 < 0.6 && !cloudless) {
- s = new Cloud(getContext());
- } else {
- switch (mScene) {
- case SCENE_ZRH:
- s = new Mountain(getContext());
- break;
- case SCENE_TX:
- s = new Cactus(getContext());
- break;
- case SCENE_CITY:
- default:
- s = new Building(getContext());
- break;
- }
- s.z = (float) i / N;
- // no more shadows for these things
- //s.setTranslationZ(PARAMS.SCENERY_Z * (1+s.z));
- s.v = 0.85f * s.z; // buildings move proportional to their distance
- if (mScene == SCENE_CITY) {
- s.setBackgroundColor(Color.GRAY);
- s.h = irand(PARAMS.BUILDING_HEIGHT_MIN, mh);
- }
- final int c = (int)(255f*s.z);
- final Drawable bg = s.getBackground();
- if (bg != null) bg.setColorFilter(Color.rgb(c,c,c), PorterDuff.Mode.MULTIPLY);
- }
- final LayoutParams lp = new LayoutParams(s.w, s.h);
- if (s instanceof Building) {
- lp.gravity = Gravity.BOTTOM;
- } else {
- lp.gravity = Gravity.TOP;
- final float r = frand();
- if (s instanceof Star) {
- lp.topMargin = (int) (r * r * mHeight);
- } else {
- lp.topMargin = (int) (1 - r*r * mHeight/2) + mHeight/2;
- }
- }
-
-
- addView(s, lp);
- s.setTranslationX(frand(-lp.width, mWidth + lp.width));
- }
-
- for (Player p : mPlayers) {
- addView(p); // put it back!
- p.reset();
- }
-
- realignPlayers();
-
- if (mAnim != null) {
- mAnim.cancel();
- }
- mAnim = new TimeAnimator();
- mAnim.setTimeListener(new TimeAnimator.TimeListener() {
- @Override
- public void onTimeUpdate(TimeAnimator timeAnimator, long t, long dt) {
- step(t, dt);
- }
- });
- }
-
- public void start(boolean startPlaying) {
- L("start(startPlaying=%s)", startPlaying ? "true" : "false");
- if (startPlaying && mCountdown <= 0) {
- showSplash();
-
- mSplash.findViewById(R.id.play_button).setEnabled(false);
-
- final View playImage = mSplash.findViewById(R.id.play_button_image);
- final TextView playText = (TextView) mSplash.findViewById(R.id.play_button_text);
-
- playImage.animate().alpha(0f);
- playText.animate().alpha(1f);
-
- mCountdown = 3;
- post(new Runnable() {
- @Override
- public void run() {
- if (mCountdown == 0) {
- startPlaying();
- } else {
- postDelayed(this, 500);
- }
- playText.setText(String.valueOf(mCountdown));
- mCountdown--;
- }
- });
- }
-
- for (Player p : mPlayers) {
- p.setVisibility(View.INVISIBLE);
- }
-
- if (!mAnimating) {
- mAnim.start();
- mAnimating = true;
- }
- }
-
- public void hideSplash() {
- if (mSplash != null && mSplash.getVisibility() == View.VISIBLE) {
- mSplash.setClickable(false);
- mSplash.animate().alpha(0).translationZ(0).setDuration(300).withEndAction(
- new Runnable() {
- @Override
- public void run() {
- mSplash.setVisibility(View.GONE);
- }
- }
- );
- }
- }
-
- public void showSplash() {
- if (mSplash != null && mSplash.getVisibility() != View.VISIBLE) {
- mSplash.setClickable(true);
- mSplash.setAlpha(0f);
- mSplash.setVisibility(View.VISIBLE);
- mSplash.animate().alpha(1f).setDuration(1000);
- mSplash.findViewById(R.id.play_button_image).setAlpha(1f);
- mSplash.findViewById(R.id.play_button_text).setAlpha(0f);
- mSplash.findViewById(R.id.play_button).setEnabled(true);
- mSplash.findViewById(R.id.play_button).requestFocus();
- }
- }
-
- public void startPlaying() {
- mPlaying = true;
-
- t = 0;
- // there's a sucker born every OBSTACLE_PERIOD
- mLastPipeTime = getGameTime() - PARAMS.OBSTACLE_PERIOD;
-
- hideSplash();
-
- realignPlayers();
- mTaps = 0;
-
- final int N = mPlayers.size();
- MetricsLogger.histogram(getContext(), "egg_mland_players", N);
- for (int i=0; i<N; i++) {
- final Player p = mPlayers.get(i);
- p.setVisibility(View.VISIBLE);
- p.reset();
- p.start();
- p.boost(-1, -1); // start you off flying!
- p.unboost(); // not forever, though
- }
- }
-
- public void stop() {
- if (mAnimating) {
- mAnim.cancel();
- mAnim = null;
- mAnimating = false;
- mPlaying = false;
- mTimeOfDay = irand(0, SKIES.length - 1); // for next reset
- mScene = irand(0, SCENE_COUNT);
- mFrozen = true;
- for (Player p : mPlayers) {
- p.die();
- }
- postDelayed(new Runnable() {
- @Override
- public void run() {
- mFrozen = false;
- }
- }, 250);
- }
- }
-
- public static final float lerp(float x, float a, float b) {
- return (b - a) * x + a;
- }
-
- public static final float rlerp(float v, float a, float b) {
- return (v - a) / (b - a);
- }
-
- public static final float clamp(float f) {
- return f < 0f ? 0f : f > 1f ? 1f : f;
- }
-
- public static final float frand() {
- return (float) Math.random();
- }
-
- public static final float frand(float a, float b) {
- return lerp(frand(), a, b);
- }
-
- public static final int irand(int a, int b) {
- return Math.round(frand((float) a, (float) b));
- }
-
- public static int pick(int[] l) {
- return l[irand(0, l.length-1)];
- }
-
- private void step(long t_ms, long dt_ms) {
- t = t_ms / 1000f; // seconds
- dt = dt_ms / 1000f;
-
- if (DEBUG) {
- t *= DEBUG_SPEED_MULTIPLIER;
- dt *= DEBUG_SPEED_MULTIPLIER;
- }
-
- // 1. Move all objects and update bounds
- final int N = getChildCount();
- int i = 0;
- for (; i<N; i++) {
- final View v = getChildAt(i);
- if (v instanceof GameView) {
- ((GameView) v).step(t_ms, dt_ms, t, dt);
- }
- }
-
- if (mPlaying) {
- int livingPlayers = 0;
- for (i = 0; i < mPlayers.size(); i++) {
- final Player p = getPlayer(i);
-
- if (p.mAlive) {
- // 2. Check for altitude
- if (p.below(mHeight)) {
- if (DEBUG_IDDQD) {
- poke(i);
- unpoke(i);
- } else {
- L("player %d hit the floor", i);
- thump(i, 80);
- p.die();
- }
- }
-
- // 3. Check for obstacles
- int maxPassedStem = 0;
- for (int j = mObstaclesInPlay.size(); j-- > 0; ) {
- final Obstacle ob = mObstaclesInPlay.get(j);
- if (ob.intersects(p) && !DEBUG_IDDQD) {
- L("player hit an obstacle");
- thump(i, 80);
- p.die();
- } else if (ob.cleared(p)) {
- if (ob instanceof Stem) {
- maxPassedStem = Math.max(maxPassedStem, ((Stem)ob).id);
- }
- }
- }
-
- if (maxPassedStem > p.mScore) {
- p.addScore(1);
- }
- }
-
- if (p.mAlive) livingPlayers++;
- }
-
- if (livingPlayers == 0) {
- stop();
-
- MetricsLogger.count(getContext(), "egg_mland_taps", mTaps);
- mTaps = 0;
- final int playerCount = mPlayers.size();
- for (int pi=0; pi<playerCount; pi++) {
- final Player p = mPlayers.get(pi);
- MetricsLogger.histogram(getContext(), "egg_mland_score", p.getScore());
- }
- }
- }
-
- // 4. Handle edge of screen
- // Walk backwards to make sure removal is safe
- while (i-->0) {
- final View v = getChildAt(i);
- if (v instanceof Obstacle) {
- if (v.getTranslationX() + v.getWidth() < 0) {
- removeViewAt(i);
- mObstaclesInPlay.remove(v);
- }
- } else if (v instanceof Scenery) {
- final Scenery s = (Scenery) v;
- if (v.getTranslationX() + s.w < 0) {
- v.setTranslationX(getWidth());
- }
- }
- }
-
- // 3. Time for more obstacles!
- if (mPlaying && (t - mLastPipeTime) > PARAMS.OBSTACLE_PERIOD) {
- mLastPipeTime = t;
- mCurrentPipeId ++;
- final int obstacley =
- (int)(frand() * (mHeight - 2*PARAMS.OBSTACLE_MIN - PARAMS.OBSTACLE_GAP)) +
- PARAMS.OBSTACLE_MIN;
-
- final int inset = (PARAMS.OBSTACLE_WIDTH - PARAMS.OBSTACLE_STEM_WIDTH) / 2;
- final int yinset = PARAMS.OBSTACLE_WIDTH/2;
-
- final int d1 = irand(0,250);
- final Obstacle s1 = new Stem(getContext(), obstacley - yinset, false);
- addView(s1, new LayoutParams(
- PARAMS.OBSTACLE_STEM_WIDTH,
- (int) s1.h,
- Gravity.TOP|Gravity.LEFT));
- s1.setTranslationX(mWidth+inset);
- s1.setTranslationY(-s1.h-yinset);
- s1.setTranslationZ(PARAMS.OBSTACLE_Z*0.75f);
- s1.animate()
- .translationY(0)
- .setStartDelay(d1)
- .setDuration(250);
- mObstaclesInPlay.add(s1);
-
- final Obstacle p1 = new Pop(getContext(), PARAMS.OBSTACLE_WIDTH);
- addView(p1, new LayoutParams(
- PARAMS.OBSTACLE_WIDTH,
- PARAMS.OBSTACLE_WIDTH,
- Gravity.TOP|Gravity.LEFT));
- p1.setTranslationX(mWidth);
- p1.setTranslationY(-PARAMS.OBSTACLE_WIDTH);
- p1.setTranslationZ(PARAMS.OBSTACLE_Z);
- p1.setScaleX(0.25f);
- p1.setScaleY(-0.25f);
- p1.animate()
- .translationY(s1.h-inset)
- .scaleX(1f)
- .scaleY(-1f)
- .setStartDelay(d1)
- .setDuration(250);
- mObstaclesInPlay.add(p1);
-
- final int d2 = irand(0,250);
- final Obstacle s2 = new Stem(getContext(),
- mHeight - obstacley - PARAMS.OBSTACLE_GAP - yinset,
- true);
- addView(s2, new LayoutParams(
- PARAMS.OBSTACLE_STEM_WIDTH,
- (int) s2.h,
- Gravity.TOP|Gravity.LEFT));
- s2.setTranslationX(mWidth+inset);
- s2.setTranslationY(mHeight+yinset);
- s2.setTranslationZ(PARAMS.OBSTACLE_Z*0.75f);
- s2.animate()
- .translationY(mHeight-s2.h)
- .setStartDelay(d2)
- .setDuration(400);
- mObstaclesInPlay.add(s2);
-
- final Obstacle p2 = new Pop(getContext(), PARAMS.OBSTACLE_WIDTH);
- addView(p2, new LayoutParams(
- PARAMS.OBSTACLE_WIDTH,
- PARAMS.OBSTACLE_WIDTH,
- Gravity.TOP|Gravity.LEFT));
- p2.setTranslationX(mWidth);
- p2.setTranslationY(mHeight);
- p2.setTranslationZ(PARAMS.OBSTACLE_Z);
- p2.setScaleX(0.25f);
- p2.setScaleY(0.25f);
- p2.animate()
- .translationY(mHeight-s2.h-yinset)
- .scaleX(1f)
- .scaleY(1f)
- .setStartDelay(d2)
- .setDuration(400);
- mObstaclesInPlay.add(p2);
- }
-
- if (SHOW_TOUCHES || DEBUG_DRAW) invalidate();
- }
-
- @Override
- public boolean onTouchEvent(MotionEvent ev) {
- L("touch: %s", ev);
- final int actionIndex = ev.getActionIndex();
- final float x = ev.getX(actionIndex);
- final float y = ev.getY(actionIndex);
- int playerIndex = (int) (getNumPlayers() * (x / getWidth()));
- if (mFlipped) playerIndex = getNumPlayers() - 1 - playerIndex;
- switch (ev.getActionMasked()) {
- case MotionEvent.ACTION_DOWN:
- case MotionEvent.ACTION_POINTER_DOWN:
- poke(playerIndex, x, y);
- return true;
- case MotionEvent.ACTION_UP:
- case MotionEvent.ACTION_POINTER_UP:
- unpoke(playerIndex);
- return true;
- }
- return false;
- }
-
- @Override
- public boolean onTrackballEvent(MotionEvent ev) {
- L("trackball: %s", ev);
- switch (ev.getAction()) {
- case MotionEvent.ACTION_DOWN:
- poke(0);
- return true;
- case MotionEvent.ACTION_UP:
- unpoke(0);
- return true;
- }
- return false;
- }
-
- @Override
- public boolean onKeyDown(int keyCode, KeyEvent ev) {
- L("keyDown: %d", keyCode);
- switch (keyCode) {
- case KeyEvent.KEYCODE_DPAD_CENTER:
- case KeyEvent.KEYCODE_DPAD_UP:
- case KeyEvent.KEYCODE_SPACE:
- case KeyEvent.KEYCODE_ENTER:
- case KeyEvent.KEYCODE_BUTTON_A:
- int player = getControllerPlayer(ev.getDeviceId());
- poke(player);
- return true;
- }
- return false;
- }
-
- @Override
- public boolean onKeyUp(int keyCode, KeyEvent ev) {
- L("keyDown: %d", keyCode);
- switch (keyCode) {
- case KeyEvent.KEYCODE_DPAD_CENTER:
- case KeyEvent.KEYCODE_DPAD_UP:
- case KeyEvent.KEYCODE_SPACE:
- case KeyEvent.KEYCODE_ENTER:
- case KeyEvent.KEYCODE_BUTTON_A:
- int player = getControllerPlayer(ev.getDeviceId());
- unpoke(player);
- return true;
- }
- return false;
- }
-
- @Override
- public boolean onGenericMotionEvent (MotionEvent ev) {
- L("generic: %s", ev);
- return false;
- }
-
- private void poke(int playerIndex) {
- poke(playerIndex, -1, -1);
- }
-
- private void poke(int playerIndex, float x, float y) {
- L("poke(%d)", playerIndex);
- if (mFrozen) return;
- if (!mAnimating) {
- reset();
- }
- if (!mPlaying) {
- start(true);
- } else {
- final Player p = getPlayer(playerIndex);
- if (p == null) return; // no player for this controller
- p.boost(x, y);
- mTaps++;
- if (DEBUG) {
- p.dv *= DEBUG_SPEED_MULTIPLIER;
- p.animate().setDuration((long) (200 / DEBUG_SPEED_MULTIPLIER));
- }
- }
- }
-
- private void unpoke(int playerIndex) {
- L("unboost(%d)", playerIndex);
- if (mFrozen || !mAnimating || !mPlaying) return;
- final Player p = getPlayer(playerIndex);
- if (p == null) return; // no player for this controller
- p.unboost();
- }
-
- @Override
- public void onDraw(Canvas c) {
- super.onDraw(c);
-
- if (SHOW_TOUCHES) {
- for (Player p : mPlayers) {
- if (p.mTouchX > 0) {
- mTouchPaint.setColor(0x80FFFFFF & p.color);
- mPlayerTracePaint.setColor(0x80FFFFFF & p.color);
- float x1 = p.mTouchX;
- float y1 = p.mTouchY;
- c.drawCircle(x1, y1, 100, mTouchPaint);
- float x2 = p.getX() + p.getPivotX();
- float y2 = p.getY() + p.getPivotY();
- float angle = PI_2 - (float) Math.atan2(x2-x1, y2-y1);
- x1 += 100*Math.cos(angle);
- y1 += 100*Math.sin(angle);
- c.drawLine(x1, y1, x2, y2, mPlayerTracePaint);
- }
- }
- }
-
- if (!DEBUG_DRAW) return;
-
- final Paint pt = new Paint();
- pt.setColor(0xFFFFFFFF);
- for (Player p : mPlayers) {
- final int L = p.corners.length;
- final int N = L / 2;
- for (int i = 0; i < N; i++) {
- final int x = (int) p.corners[i * 2];
- final int y = (int) p.corners[i * 2 + 1];
- c.drawCircle(x, y, 4, pt);
- c.drawLine(x, y,
- p.corners[(i * 2 + 2) % L],
- p.corners[(i * 2 + 3) % L],
- pt);
- }
- }
-
- pt.setStyle(Paint.Style.STROKE);
- pt.setStrokeWidth(getResources().getDisplayMetrics().density);
-
- final int M = getChildCount();
- pt.setColor(0x8000FF00);
- for (int i=0; i<M; i++) {
- final View v = getChildAt(i);
- if (v instanceof Player) continue;
- if (!(v instanceof GameView)) continue;
- if (v instanceof Pop) {
- final Pop pop = (Pop) v;
- c.drawCircle(pop.cx, pop.cy, pop.r, pt);
- } else {
- final Rect r = new Rect();
- v.getHitRect(r);
- c.drawRect(r, pt);
- }
- }
-
- pt.setColor(Color.BLACK);
- final StringBuilder sb = new StringBuilder("obstacles: ");
- for (Obstacle ob : mObstaclesInPlay) {
- sb.append(ob.hitRect.toShortString());
- sb.append(" ");
- }
- pt.setTextSize(20f);
- c.drawText(sb.toString(), 20, 100, pt);
- }
-
- static final Rect sTmpRect = new Rect();
-
- private interface GameView {
- public void step(long t_ms, long dt_ms, float t, float dt);
- }
-
- private static class Player extends ImageView implements GameView {
- public float dv;
- public int color;
- private MLand mLand;
- private boolean mBoosting;
- private float mTouchX = -1, mTouchY = -1;
- private boolean mAlive;
- private int mScore;
- private TextView mScoreField;
-
- private final int[] sColors = new int[] {
- //0xFF78C557,
- 0xFFDB4437,
- 0xFF3B78E7,
- 0xFFF4B400,
- 0xFF0F9D58,
- 0xFF7B1880,
- 0xFF9E9E9E,
- };
- static int sNextColor = 0;
-
- private final float[] sHull = new float[] {
- 0.3f, 0f, // left antenna
- 0.7f, 0f, // right antenna
- 0.92f, 0.33f, // off the right shoulder of Orion
- 0.92f, 0.75f, // right hand (our right, not his right)
- 0.6f, 1f, // right foot
- 0.4f, 1f, // left foot BLUE!
- 0.08f, 0.75f, // sinistram
- 0.08f, 0.33f, // cold shoulder
- };
- public final float[] corners = new float[sHull.length];
-
- public static Player create(MLand land) {
- final Player p = new Player(land.getContext());
- p.mLand = land;
- p.reset();
- p.setVisibility(View.INVISIBLE);
- land.addView(p, new LayoutParams(PARAMS.PLAYER_SIZE, PARAMS.PLAYER_SIZE));
- return p;
- }
-
- private void setScore(int score) {
- mScore = score;
- if (mScoreField != null) {
- mScoreField.setText(DEBUG_IDDQD ? "??" : String.valueOf(score));
- }
- }
-
- public int getScore() {
- return mScore;
- }
-
- private void addScore(int incr) {
- setScore(mScore + incr);
- }
-
- public void setScoreField(TextView tv) {
- mScoreField = tv;
- if (tv != null) {
- setScore(mScore); // reapply
- //mScoreField.setBackgroundResource(R.drawable.scorecard);
- mScoreField.getBackground().setColorFilter(color, PorterDuff.Mode.SRC_ATOP);
- mScoreField.setTextColor(luma(color) > 0.7f ? 0xFF000000 : 0xFFFFFFFF);
- }
- }
-
- public void reset() {
- //setX(mLand.mWidth / 2);
- setY(mLand.mHeight / 2
- + (int)(Math.random() * PARAMS.PLAYER_SIZE)
- - PARAMS.PLAYER_SIZE / 2);
- setScore(0);
- setScoreField(mScoreField); // refresh color
- mBoosting = false;
- dv = 0;
- }
-
- public Player(Context context) {
- super(context);
-
- setBackgroundResource(R.drawable.android);
- getBackground().setTintMode(PorterDuff.Mode.SRC_ATOP);
- color = sColors[(sNextColor++%sColors.length)];
- getBackground().setTint(color);
- setOutlineProvider(new ViewOutlineProvider() {
- @Override
- public void getOutline(View view, Outline outline) {
- final int w = view.getWidth();
- final int h = view.getHeight();
- final int ix = (int) (w * 0.3f);
- final int iy = (int) (h * 0.2f);
- outline.setRect(ix, iy, w - ix, h - iy);
- }
- });
- }
-
- public void prepareCheckIntersections() {
- final int inset = (PARAMS.PLAYER_SIZE - PARAMS.PLAYER_HIT_SIZE)/2;
- final int scale = PARAMS.PLAYER_HIT_SIZE;
- final int N = sHull.length/2;
- for (int i=0; i<N; i++) {
- corners[i*2] = scale * sHull[i*2] + inset;
- corners[i*2+1] = scale * sHull[i*2+1] + inset;
- }
- final Matrix m = getMatrix();
- m.mapPoints(corners);
- }
-
- public boolean below(int h) {
- final int N = corners.length/2;
- for (int i=0; i<N; i++) {
- final int y = (int) corners[i*2+1];
- if (y >= h) return true;
- }
- return false;
- }
-
- public void step(long t_ms, long dt_ms, float t, float dt) {
- if (!mAlive) {
- // float away with the garbage
- setTranslationX(getTranslationX()-PARAMS.TRANSLATION_PER_SEC*dt);
- return;
- }
-
- if (mBoosting) {
- dv = -PARAMS.BOOST_DV;
- } else {
- dv += PARAMS.G;
- }
- if (dv < -PARAMS.MAX_V) dv = -PARAMS.MAX_V;
- else if (dv > PARAMS.MAX_V) dv = PARAMS.MAX_V;
-
- final float y = getTranslationY() + dv * dt;
- setTranslationY(y < 0 ? 0 : y);
- setRotation(
- 90 + lerp(clamp(rlerp(dv, PARAMS.MAX_V, -1 * PARAMS.MAX_V)), 90, -90));
-
- prepareCheckIntersections();
- }
-
- public void boost(float x, float y) {
- mTouchX = x;
- mTouchY = y;
- boost();
- }
-
- public void boost() {
- mBoosting = true;
- dv = -PARAMS.BOOST_DV;
-
- animate().cancel();
- animate()
- .scaleX(1.25f)
- .scaleY(1.25f)
- .translationZ(PARAMS.PLAYER_Z_BOOST)
- .setDuration(100);
- setScaleX(1.25f);
- setScaleY(1.25f);
- }
-
- public void unboost() {
- mBoosting = false;
- mTouchX = mTouchY = -1;
-
- animate().cancel();
- animate()
- .scaleX(1f)
- .scaleY(1f)
- .translationZ(PARAMS.PLAYER_Z)
- .setDuration(200);
- }
-
- public void die() {
- mAlive = false;
- if (mScoreField != null) {
- //mScoreField.setTextColor(0xFFFFFFFF);
- //mScoreField.getBackground().setColorFilter(0xFF666666, PorterDuff.Mode.SRC_ATOP);
- //mScoreField.setBackgroundResource(R.drawable.scorecard_gameover);
- }
- }
-
- public void start() {
- mAlive = true;
- }
- }
-
- private class Obstacle extends View implements GameView {
- public float h;
-
- public final Rect hitRect = new Rect();
-
- public Obstacle(Context context, float h) {
- super(context);
- setBackgroundColor(0xFFFF0000);
- this.h = h;
- }
-
- public boolean intersects(Player p) {
- final int N = p.corners.length/2;
- for (int i=0; i<N; i++) {
- final int x = (int) p.corners[i*2];
- final int y = (int) p.corners[i*2+1];
- if (hitRect.contains(x, y)) return true;
- }
- return false;
- }
-
- public boolean cleared(Player p) {
- final int N = p.corners.length/2;
- for (int i=0; i<N; i++) {
- final int x = (int) p.corners[i*2];
- if (hitRect.right >= x) return false;
- }
- return true;
- }
-
- @Override
- public void step(long t_ms, long dt_ms, float t, float dt) {
- setTranslationX(getTranslationX()-PARAMS.TRANSLATION_PER_SEC*dt);
- getHitRect(hitRect);
- }
- }
-
- static final int[] ANTENNAE = new int[] {R.drawable.mm_antennae, R.drawable.mm_antennae2};
- static final int[] EYES = new int[] {R.drawable.mm_eyes, R.drawable.mm_eyes2};
- static final int[] MOUTHS = new int[] {R.drawable.mm_mouth1, R.drawable.mm_mouth2,
- R.drawable.mm_mouth3, R.drawable.mm_mouth4};
- private class Pop extends Obstacle {
- int mRotate;
- int cx, cy, r;
- // The marshmallow illustration and hitbox is 2/3 the size of its container.
- Drawable antenna, eyes, mouth;
-
-
- public Pop(Context context, float h) {
- super(context, h);
- setBackgroundResource(R.drawable.mm_head);
- antenna = context.getDrawable(pick(ANTENNAE));
- if (frand() > 0.5f) {
- eyes = context.getDrawable(pick(EYES));
- if (frand() > 0.8f) {
- mouth = context.getDrawable(pick(MOUTHS));
- }
- }
- setOutlineProvider(new ViewOutlineProvider() {
- @Override
- public void getOutline(View view, Outline outline) {
- final int pad = (int) (getWidth() * 1f/6);
- outline.setOval(pad, pad, getWidth()-pad, getHeight()-pad);
- }
- });
- }
-
- public boolean intersects(Player p) {
- final int N = p.corners.length/2;
- for (int i=0; i<N; i++) {
- final int x = (int) p.corners[i*2];
- final int y = (int) p.corners[i*2+1];
- if (Math.hypot(x-cx, y-cy) <= r) return true;
- }
- return false;
- }
-
- @Override
- public void step(long t_ms, long dt_ms, float t, float dt) {
- super.step(t_ms, dt_ms, t, dt);
- if (mRotate != 0) {
- setRotation(getRotation() + dt * 45 * mRotate);
- }
-
- cx = (hitRect.left + hitRect.right)/2;
- cy = (hitRect.top + hitRect.bottom)/2;
- r = getWidth() / 3; // see above re 2/3 container size
- }
-
- @Override
- public void onDraw(Canvas c) {
- super.onDraw(c);
- if (antenna != null) {
- antenna.setBounds(0, 0, c.getWidth(), c.getHeight());
- antenna.draw(c);
- }
- if (eyes != null) {
- eyes.setBounds(0, 0, c.getWidth(), c.getHeight());
- eyes.draw(c);
- }
- if (mouth != null) {
- mouth.setBounds(0, 0, c.getWidth(), c.getHeight());
- mouth.draw(c);
- }
- }
- }
-
- private class Stem extends Obstacle {
- Paint mPaint = new Paint();
- Path mShadow = new Path();
- GradientDrawable mGradient = new GradientDrawable();
- boolean mDrawShadow;
- Path mJandystripe;
- Paint mPaint2;
- int id; // use this to track which pipes have been cleared
-
- public Stem(Context context, float h, boolean drawShadow) {
- super(context, h);
- id = mCurrentPipeId;
-
- mDrawShadow = drawShadow;
- setBackground(null);
- mGradient.setOrientation(GradientDrawable.Orientation.LEFT_RIGHT);
- mPaint.setColor(0xFF000000);
- mPaint.setColorFilter(new PorterDuffColorFilter(0x22000000, PorterDuff.Mode.MULTIPLY));
-
- if (frand() < 0.01f) {
- mGradient.setColors(new int[]{0xFFFFFFFF, 0xFFDDDDDD});
- mJandystripe = new Path();
- mPaint2 = new Paint();
- mPaint2.setColor(0xFFFF0000);
- mPaint2.setColorFilter(new PorterDuffColorFilter(0xFFFF0000, PorterDuff.Mode.MULTIPLY));
- } else {
- //mPaint.setColor(0xFFA1887F);
- mGradient.setColors(new int[]{0xFFBCAAA4, 0xFFA1887F});
- }
- }
-
- @Override
- public void onAttachedToWindow() {
- super.onAttachedToWindow();
- setWillNotDraw(false);
- setOutlineProvider(new ViewOutlineProvider() {
- @Override
- public void getOutline(View view, Outline outline) {
- outline.setRect(0, 0, getWidth(), getHeight());
- }
- });
- }
- @Override
- public void onDraw(Canvas c) {
- final int w = c.getWidth();
- final int h = c.getHeight();
- mGradient.setGradientCenter(w * 0.75f, 0);
- mGradient.setBounds(0, 0, w, h);
- mGradient.draw(c);
-
- if (mJandystripe != null) {
- mJandystripe.reset();
- mJandystripe.moveTo(0, w);
- mJandystripe.lineTo(w, 0);
- mJandystripe.lineTo(w, 2 * w);
- mJandystripe.lineTo(0, 3 * w);
- mJandystripe.close();
- for (int y=0; y<h; y+=4*w) {
- c.drawPath(mJandystripe, mPaint2);
- mJandystripe.offset(0, 4 * w);
- }
- }
-
- if (!mDrawShadow) return;
- mShadow.reset();
- mShadow.moveTo(0, 0);
- mShadow.lineTo(w, 0);
- mShadow.lineTo(w, PARAMS.OBSTACLE_WIDTH * 0.4f + w*1.5f);
- mShadow.lineTo(0, PARAMS.OBSTACLE_WIDTH * 0.4f);
- mShadow.close();
- c.drawPath(mShadow, mPaint);
- }
- }
-
- private class Scenery extends FrameLayout implements GameView {
- public float z;
- public float v;
- public int h, w;
- public Scenery(Context context) {
- super(context);
- }
-
- @Override
- public void step(long t_ms, long dt_ms, float t, float dt) {
- setTranslationX(getTranslationX() - PARAMS.TRANSLATION_PER_SEC * dt * v);
- }
- }
-
- private class Building extends Scenery {
- public Building(Context context) {
- super(context);
-
- w = irand(PARAMS.BUILDING_WIDTH_MIN, PARAMS.BUILDING_WIDTH_MAX);
- h = 0; // will be setup later, along with z
- }
- }
-
- static final int[] CACTI = { R.drawable.cactus1, R.drawable.cactus2, R.drawable.cactus3 };
- private class Cactus extends Building {
- public Cactus(Context context) {
- super(context);
-
- setBackgroundResource(pick(CACTI));
- w = h = irand(PARAMS.BUILDING_WIDTH_MAX / 4, PARAMS.BUILDING_WIDTH_MAX / 2);
- }
- }
-
- static final int[] MOUNTAINS = {
- R.drawable.mountain1, R.drawable.mountain2, R.drawable.mountain3 };
- private class Mountain extends Building {
- public Mountain(Context context) {
- super(context);
-
- setBackgroundResource(pick(MOUNTAINS));
- w = h = irand(PARAMS.BUILDING_WIDTH_MAX / 2, PARAMS.BUILDING_WIDTH_MAX);
- z = 0;
- }
- }
- private class Cloud extends Scenery {
- public Cloud(Context context) {
- super(context);
- setBackgroundResource(frand() < 0.01f ? R.drawable.cloud_off : R.drawable.cloud);
- getBackground().setAlpha(0x40);
- w = h = irand(PARAMS.CLOUD_SIZE_MIN, PARAMS.CLOUD_SIZE_MAX);
- z = 0;
- v = frand(0.15f,0.5f);
- }
- }
-
- private class Star extends Scenery {
- public Star(Context context) {
- super(context);
- setBackgroundResource(R.drawable.star);
- w = h = irand(PARAMS.STAR_SIZE_MIN, PARAMS.STAR_SIZE_MAX);
- v = z = 0;
- }
- }
-}
diff --git a/packages/SystemUI/src/com/android/systemui/egg/MLandActivity.java b/packages/SystemUI/src/com/android/systemui/egg/MLandActivity.java
deleted file mode 100644
index 84b91bc..0000000
--- a/packages/SystemUI/src/com/android/systemui/egg/MLandActivity.java
+++ /dev/null
@@ -1,90 +0,0 @@
-/*
- * Copyright (C) 2015 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.egg;
-
-import android.app.Activity;
-import android.os.Bundle;
-import android.view.View;
-
-import com.android.systemui.R;
-
-public class MLandActivity extends Activity {
- MLand mLand;
-
- @Override
- public void onCreate(Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
- setContentView(R.layout.mland);
- mLand = findViewById(R.id.world);
- mLand.setScoreFieldHolder(findViewById(R.id.scores));
- final View welcome = findViewById(R.id.welcome);
- mLand.setSplash(welcome);
- final int numControllers = mLand.getGameControllers().size();
- if (numControllers > 0) {
- mLand.setupPlayers(numControllers);
- }
- }
-
- public void updateSplashPlayers() {
- final int N = mLand.getNumPlayers();
- final View minus = findViewById(R.id.player_minus_button);
- final View plus = findViewById(R.id.player_plus_button);
- if (N == 1) {
- minus.setVisibility(View.INVISIBLE);
- plus.setVisibility(View.VISIBLE);
- plus.requestFocus();
- } else if (N == mLand.MAX_PLAYERS) {
- minus.setVisibility(View.VISIBLE);
- plus.setVisibility(View.INVISIBLE);
- minus.requestFocus();
- } else {
- minus.setVisibility(View.VISIBLE);
- plus.setVisibility(View.VISIBLE);
- }
- }
-
- @Override
- public void onPause() {
- mLand.stop();
- super.onPause();
- }
-
- @Override
- public void onResume() {
- super.onResume();
-
- mLand.onAttachedToWindow(); // resets and starts animation
- updateSplashPlayers();
- mLand.showSplash();
- }
-
- public void playerMinus(View v) {
- mLand.removePlayer();
- updateSplashPlayers();
- }
-
- public void playerPlus(View v) {
- mLand.addPlayer();
- updateSplashPlayers();
- }
-
- public void startButtonPressed(View v) {
- findViewById(R.id.player_minus_button).setVisibility(View.INVISIBLE);
- findViewById(R.id.player_plus_button).setVisibility(View.INVISIBLE);
- mLand.start(true);
- }
-}
diff --git a/packages/SystemUI/src/com/android/systemui/flags/FeatureFlagManager.java b/packages/SystemUI/src/com/android/systemui/flags/FeatureFlagManager.java
deleted file mode 100644
index 85baed4..0000000
--- a/packages/SystemUI/src/com/android/systemui/flags/FeatureFlagManager.java
+++ /dev/null
@@ -1,38 +0,0 @@
-/*
- * Copyright (C) 2021 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.flags;
-
-import com.android.systemui.dagger.SysUISingleton;
-
-import javax.inject.Inject;
-
-/**
- * Default implementation of the a Flag manager that returns default values for release builds
- */
-@SysUISingleton
-public class FeatureFlagManager implements FlagReader, FlagWriter {
- @Inject
- public FeatureFlagManager() {}
- public boolean isEnabled(String key, boolean defaultValue) {
- return defaultValue;
- }
- public boolean isEnabled(int key, boolean defaultValue) {
- return defaultValue;
- }
- public void setEnabled(String key, boolean value) {}
- public void setEnabled(int key, boolean value) {}
-}
diff --git a/packages/SystemUI/src/com/android/systemui/flags/FeatureFlags.java b/packages/SystemUI/src/com/android/systemui/flags/FeatureFlags.java
index 5eff0e6..3d44304 100644
--- a/packages/SystemUI/src/com/android/systemui/flags/FeatureFlags.java
+++ b/packages/SystemUI/src/com/android/systemui/flags/FeatureFlags.java
@@ -18,6 +18,8 @@
import android.content.Context;
import android.util.FeatureFlagUtils;
+import android.util.Log;
+import android.widget.Toast;
import com.android.internal.annotations.VisibleForTesting;
import com.android.systemui.R;
@@ -86,6 +88,22 @@
}
}
+ public void assertLegacyPipelineEnabled() {
+ if (isNewNotifPipelineRenderingEnabled()) {
+ throw new IllegalStateException("Old pipeline code running w/ new pipeline enabled");
+ }
+ }
+
+ public boolean checkLegacyPipelineEnabled() {
+ if (!isNewNotifPipelineRenderingEnabled()) {
+ return true;
+ }
+ Log.d("NotifPipeline", "Old pipeline code running w/ new pipeline enabled",
+ new Exception());
+ Toast.makeText(mContext, "Old pipeline code running!", Toast.LENGTH_SHORT).show();
+ return false;
+ }
+
public boolean isNewNotifPipelineEnabled() {
return isEnabled(Flags.NEW_NOTIFICATION_PIPELINE);
}
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/FaceAuthScreenBrightnessController.kt b/packages/SystemUI/src/com/android/systemui/keyguard/FaceAuthScreenBrightnessController.kt
deleted file mode 100644
index b4137fa..0000000
--- a/packages/SystemUI/src/com/android/systemui/keyguard/FaceAuthScreenBrightnessController.kt
+++ /dev/null
@@ -1,195 +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.systemui.keyguard
-
-import android.animation.Animator
-import android.animation.AnimatorListenerAdapter
-import android.animation.ValueAnimator
-import android.content.res.Resources
-import android.database.ContentObserver
-import android.graphics.Bitmap
-import android.graphics.BitmapFactory
-import android.graphics.Color
-import android.graphics.drawable.ColorDrawable
-import android.hardware.biometrics.BiometricSourceType
-import android.os.Handler
-import android.provider.Settings.System.SCREEN_BRIGHTNESS_FLOAT
-import android.util.MathUtils
-import android.view.View
-import android.view.WindowManager.LayoutParams.BRIGHTNESS_OVERRIDE_NONE
-import android.view.WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE
-import com.android.internal.annotations.VisibleForTesting
-import com.android.keyguard.KeyguardUpdateMonitor
-import com.android.keyguard.KeyguardUpdateMonitorCallback
-import com.android.systemui.Dumpable
-import com.android.systemui.R
-import com.android.systemui.dagger.SysUISingleton
-import com.android.systemui.dump.DumpManager
-import com.android.systemui.statusbar.NotificationShadeWindowController
-import com.android.systemui.util.settings.GlobalSettings
-import com.android.systemui.util.settings.SystemSettings
-import java.io.FileDescriptor
-import java.io.PrintWriter
-import java.lang.Float.max
-import java.util.concurrent.TimeUnit
-
-val DEFAULT_ANIMATION_DURATION = TimeUnit.SECONDS.toMillis(4)
-val MAX_SCREEN_BRIGHTNESS = 100 // 0..100
-val MAX_SCRIM_OPACTY = 50 // 0..100
-val DEFAULT_USE_FACE_WALLPAPER = false
-
-/**
- * This class is responsible for ramping up the display brightness (and white overlay) in order
- * to mitigate low light conditions when running face auth without an IR camera.
- */
-@SysUISingleton
-open class FaceAuthScreenBrightnessController(
- private val notificationShadeWindowController: NotificationShadeWindowController,
- private val keyguardUpdateMonitor: KeyguardUpdateMonitor,
- private val resources: Resources,
- private val globalSettings: GlobalSettings,
- private val systemSettings: SystemSettings,
- private val mainHandler: Handler,
- private val dumpManager: DumpManager,
- private val enabled: Boolean
-) : Dumpable {
-
- private var userDefinedBrightness: Float = 1f
- @VisibleForTesting
- var useFaceAuthWallpaper = globalSettings
- .getInt("sysui.use_face_auth_wallpaper", if (DEFAULT_USE_FACE_WALLPAPER) 1 else 0) == 1
- private val brightnessAnimationDuration = globalSettings
- .getLong("sysui.face_brightness_anim_duration", DEFAULT_ANIMATION_DURATION)
- private val maxScreenBrightness = globalSettings
- .getInt("sysui.face_max_brightness", MAX_SCREEN_BRIGHTNESS) / 100f
- private val maxScrimOpacity = globalSettings
- .getInt("sysui.face_max_scrim_opacity", MAX_SCRIM_OPACTY) / 100f
- private val keyguardUpdateCallback = object : KeyguardUpdateMonitorCallback() {
- override fun onBiometricRunningStateChanged(
- running: Boolean,
- biometricSourceType: BiometricSourceType?
- ) {
- if (biometricSourceType != BiometricSourceType.FACE) {
- return
- }
- // TODO enable only when receiving a low-light error
- overridingBrightness = if (enabled) running else false
- }
- }
- private lateinit var whiteOverlay: View
- private var brightnessAnimator: ValueAnimator? = null
- private var overridingBrightness = false
- set(value) {
- if (field == value) {
- return
- }
- field = value
- brightnessAnimator?.cancel()
-
- if (!value) {
- notificationShadeWindowController.setFaceAuthDisplayBrightness(BRIGHTNESS_OVERRIDE_NONE)
- if (whiteOverlay.alpha > 0) {
- brightnessAnimator = createAnimator(whiteOverlay.alpha, 0f).apply {
- duration = 200
- addUpdateListener {
- whiteOverlay.alpha = it.animatedValue as Float
- }
- addListener(object : AnimatorListenerAdapter() {
- override fun onAnimationEnd(animation: Animator?) {
- whiteOverlay.visibility = View.INVISIBLE
- brightnessAnimator = null
- }
- })
- start()
- }
- }
- return
- }
-
- val targetBrightness = max(maxScreenBrightness, userDefinedBrightness)
- whiteOverlay.visibility = View.VISIBLE
- brightnessAnimator = createAnimator(0f, 1f).apply {
- duration = brightnessAnimationDuration
- addUpdateListener {
- val progress = it.animatedValue as Float
- val brightnessProgress = MathUtils.constrainedMap(
- userDefinedBrightness, targetBrightness, 0f, 0.5f, progress)
- val scrimProgress = MathUtils.constrainedMap(
- 0f, maxScrimOpacity, 0.5f, 1f, progress)
- notificationShadeWindowController.setFaceAuthDisplayBrightness(brightnessProgress)
- whiteOverlay.alpha = scrimProgress
- }
- addListener(object : AnimatorListenerAdapter() {
- override fun onAnimationEnd(animation: Animator?) {
- brightnessAnimator = null
- }
- })
- start()
- }
- }
-
- @VisibleForTesting
- open fun createAnimator(start: Float, end: Float) = ValueAnimator.ofFloat(start, end)
-
- /**
- * Returns a bitmap that should be used by the lock screen as a wallpaper, if face auth requires
- * a secure wallpaper.
- */
- var faceAuthWallpaper: Bitmap? = null
- get() {
- val user = KeyguardUpdateMonitor.getCurrentUser()
- if (useFaceAuthWallpaper && keyguardUpdateMonitor.isFaceAuthEnabledForUser(user)) {
- val options = BitmapFactory.Options().apply {
- inScaled = false
- }
- return BitmapFactory.decodeResource(resources, R.drawable.face_auth_wallpaper, options)
- }
- return null
- }
- private set
-
- fun attach(overlayView: View) {
- whiteOverlay = overlayView
- whiteOverlay.focusable = FLAG_NOT_FOCUSABLE
- whiteOverlay.background = ColorDrawable(Color.WHITE)
- whiteOverlay.isEnabled = false
- whiteOverlay.alpha = 0f
- whiteOverlay.visibility = View.INVISIBLE
-
- dumpManager.registerDumpable(this.javaClass.name, this)
- keyguardUpdateMonitor.registerCallback(keyguardUpdateCallback)
- systemSettings.registerContentObserver(SCREEN_BRIGHTNESS_FLOAT,
- object : ContentObserver(mainHandler) {
- override fun onChange(selfChange: Boolean) {
- userDefinedBrightness = systemSettings.getFloat(SCREEN_BRIGHTNESS_FLOAT)
- }
- })
- userDefinedBrightness = systemSettings.getFloat(SCREEN_BRIGHTNESS_FLOAT, 1f)
- }
-
- override fun dump(fd: FileDescriptor, pw: PrintWriter, args: Array<out String>) {
- pw.apply {
- println("overridingBrightness: $overridingBrightness")
- println("useFaceAuthWallpaper: $useFaceAuthWallpaper")
- println("brightnessAnimator: $brightnessAnimator")
- println("brightnessAnimationDuration: $brightnessAnimationDuration")
- println("maxScreenBrightness: $maxScreenBrightness")
- println("userDefinedBrightness: $userDefinedBrightness")
- println("enabled: $enabled")
- }
- }
-}
\ No newline at end of file
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/dagger/KeyguardModule.java b/packages/SystemUI/src/com/android/systemui/keyguard/dagger/KeyguardModule.java
index 11d4aac..9b0d69b 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/dagger/KeyguardModule.java
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/dagger/KeyguardModule.java
@@ -20,9 +20,6 @@
import android.app.trust.TrustManager;
import android.content.Context;
import android.content.pm.PackageManager;
-import android.content.res.Resources;
-import android.hardware.face.FaceManager;
-import android.os.Handler;
import android.os.PowerManager;
import com.android.internal.widget.LockPatternUtils;
@@ -37,17 +34,14 @@
import com.android.systemui.classifier.FalsingCollector;
import com.android.systemui.classifier.FalsingModule;
import com.android.systemui.dagger.SysUISingleton;
-import com.android.systemui.dagger.qualifiers.Main;
import com.android.systemui.dagger.qualifiers.UiBackground;
import com.android.systemui.dump.DumpManager;
import com.android.systemui.keyguard.DismissCallbackRegistry;
-import com.android.systemui.keyguard.FaceAuthScreenBrightnessController;
import com.android.systemui.keyguard.KeyguardUnlockAnimationController;
import com.android.systemui.keyguard.KeyguardViewMediator;
import com.android.systemui.navigationbar.NavigationModeController;
import com.android.systemui.plugins.statusbar.StatusBarStateController;
import com.android.systemui.statusbar.NotificationShadeDepthController;
-import com.android.systemui.statusbar.NotificationShadeWindowController;
import com.android.systemui.statusbar.SysuiStatusBarStateController;
import com.android.systemui.statusbar.phone.DozeParameters;
import com.android.systemui.statusbar.phone.KeyguardLiftController;
@@ -59,10 +53,7 @@
import com.android.systemui.unfold.config.UnfoldTransitionConfig;
import com.android.systemui.util.DeviceConfigProxy;
import com.android.systemui.util.sensors.AsyncSensorManager;
-import com.android.systemui.util.settings.GlobalSettings;
-import com.android.systemui.util.settings.SystemSettings;
-import java.util.Optional;
import java.util.concurrent.Executor;
import dagger.Lazy;
@@ -150,35 +141,4 @@
return new KeyguardLiftController(statusBarStateController, asyncSensorManager,
keyguardUpdateMonitor, dumpManager);
}
-
- @SysUISingleton
- @Provides
- static Optional<FaceAuthScreenBrightnessController> provideFaceAuthScreenBrightnessController(
- Context context,
- NotificationShadeWindowController notificationShadeWindowController,
- @Main Resources resources,
- Handler handler,
- @Nullable FaceManager faceManager,
- PackageManager packageManager,
- KeyguardUpdateMonitor keyguardUpdateMonitor,
- GlobalSettings globalSetting,
- SystemSettings systemSettings,
- DumpManager dumpManager) {
- if (faceManager == null || !packageManager.hasSystemFeature(PackageManager.FEATURE_FACE)) {
- return Optional.empty();
- }
-
- // Cameras that support "self illumination," via IR for example, don't need low light
- // environment mitigation.
- boolean needsLowLightMitigation = faceManager.getSensorPropertiesInternal().stream()
- .anyMatch((properties) -> !properties.supportsSelfIllumination);
- if (!needsLowLightMitigation) {
- return Optional.empty();
- }
-
- // currently disabled (doesn't ramp up brightness or use scrim) see b/175918367
- return Optional.of(new FaceAuthScreenBrightnessController(
- notificationShadeWindowController, keyguardUpdateMonitor, resources,
- globalSetting, systemSettings, handler, dumpManager, false));
- }
}
diff --git a/packages/SystemUI/src/com/android/systemui/media/PlayerViewHolder.kt b/packages/SystemUI/src/com/android/systemui/media/PlayerViewHolder.kt
index f32dad6..042a337 100644
--- a/packages/SystemUI/src/com/android/systemui/media/PlayerViewHolder.kt
+++ b/packages/SystemUI/src/com/android/systemui/media/PlayerViewHolder.kt
@@ -106,6 +106,7 @@
*/
@JvmStatic fun create(inflater: LayoutInflater, parent: ViewGroup): PlayerViewHolder {
val mediaView = inflater.inflate(R.layout.media_view, parent, false)
+ mediaView.setLayerType(View.LAYER_TYPE_HARDWARE, null)
// Because this media view (a TransitionLayout) is used to measure and layout the views
// in various states before being attached to its parent, we can't depend on the default
// LAYOUT_DIRECTION_INHERIT to correctly resolve the ltr direction.
diff --git a/packages/SystemUI/src/com/android/systemui/media/dialog/MediaOutputAdapter.java b/packages/SystemUI/src/com/android/systemui/media/dialog/MediaOutputAdapter.java
index 125b87b..113ba59 100644
--- a/packages/SystemUI/src/com/android/systemui/media/dialog/MediaOutputAdapter.java
+++ b/packages/SystemUI/src/com/android/systemui/media/dialog/MediaOutputAdapter.java
@@ -16,14 +16,10 @@
package com.android.systemui.media.dialog;
-import static android.text.Spanned.SPAN_EXCLUSIVE_EXCLUSIVE;
-
import android.graphics.PorterDuff;
import android.graphics.PorterDuffColorFilter;
import android.graphics.drawable.Drawable;
-import android.text.SpannableString;
import android.text.TextUtils;
-import android.text.style.ForegroundColorSpan;
import android.util.Log;
import android.view.View;
import android.view.ViewGroup;
@@ -99,23 +95,6 @@
return mController.getMediaDevices().size();
}
- @Override
- CharSequence getItemTitle(MediaDevice device) {
- if (device.getDeviceType() == MediaDevice.MediaDeviceType.TYPE_BLUETOOTH_DEVICE
- && !device.isConnected()) {
- final CharSequence deviceName = device.getName();
- // Append status to title only for the disconnected Bluetooth device.
- final SpannableString spannableTitle = new SpannableString(
- mContext.getString(R.string.media_output_dialog_disconnected, deviceName));
- spannableTitle.setSpan(new ForegroundColorSpan(
- Utils.getColorAttrDefaultColor(mContext, android.R.attr.textColorSecondary)),
- deviceName.length(),
- spannableTitle.length(), SPAN_EXCLUSIVE_EXCLUSIVE);
- return spannableTitle;
- }
- return super.getItemTitle(device);
- }
-
class MediaDeviceViewHolder extends MediaDeviceBaseViewHolder {
MediaDeviceViewHolder(View view) {
@@ -166,6 +145,14 @@
false /* showProgressBar */, false /* showSubtitle */);
initSeekbar(device);
mCurrentActivePosition = position;
+ } else if (
+ device.getDeviceType() == MediaDevice.MediaDeviceType.TYPE_BLUETOOTH_DEVICE
+ && !device.isConnected()) {
+ setTwoLineLayout(device, false /* bFocused */,
+ false /* showSeekBar */, false /* showProgressBar */,
+ true /* showSubtitle */);
+ mSubTitleText.setText(R.string.media_output_dialog_disconnected);
+ mContainerLayout.setOnClickListener(v -> onItemClick(v, device));
} else {
setSingleLineLayout(getItemTitle(device), false /* bFocused */);
mContainerLayout.setOnClickListener(v -> onItemClick(v, device));
@@ -175,7 +162,6 @@
@Override
void onBind(int customizedItem, boolean topMargin, boolean bottomMargin) {
- super.onBind(customizedItem, topMargin, bottomMargin);
if (customizedItem == CUSTOMIZED_ITEM_PAIR_NEW) {
mCheckBox.setVisibility(View.GONE);
mAddIcon.setVisibility(View.GONE);
diff --git a/packages/SystemUI/src/com/android/systemui/media/dialog/MediaOutputBaseAdapter.java b/packages/SystemUI/src/com/android/systemui/media/dialog/MediaOutputBaseAdapter.java
index 1ffc2c4..868193b 100644
--- a/packages/SystemUI/src/com/android/systemui/media/dialog/MediaOutputBaseAdapter.java
+++ b/packages/SystemUI/src/com/android/systemui/media/dialog/MediaOutputBaseAdapter.java
@@ -153,9 +153,7 @@
});
}
- void onBind(int customizedItem, boolean topMargin, boolean bottomMargin) {
- // TODO (b/201718621): clean up method after adjustment
- }
+ abstract void onBind(int customizedItem, boolean topMargin, boolean bottomMargin);
void setSingleLineLayout(CharSequence title, boolean bFocused) {
mTwoLineLayout.setVisibility(View.GONE);
diff --git a/packages/SystemUI/src/com/android/systemui/media/dialog/MediaOutputBaseDialog.java b/packages/SystemUI/src/com/android/systemui/media/dialog/MediaOutputBaseDialog.java
index 6895ef1..26ce645 100644
--- a/packages/SystemUI/src/com/android/systemui/media/dialog/MediaOutputBaseDialog.java
+++ b/packages/SystemUI/src/com/android/systemui/media/dialog/MediaOutputBaseDialog.java
@@ -104,8 +104,6 @@
lp.setFitInsetsIgnoringVisibility(true);
window.setAttributes(lp);
window.setContentView(mDialogView);
- window.setLayout(mContext.getResources().getDimensionPixelSize(R.dimen.large_dialog_width),
- ViewGroup.LayoutParams.WRAP_CONTENT);
mHeaderTitle = mDialogView.requireViewById(R.id.header_title);
mHeaderSubtitle = mDialogView.requireViewById(R.id.header_subtitle);
diff --git a/packages/SystemUI/src/com/android/systemui/media/dialog/MediaOutputGroupAdapter.java b/packages/SystemUI/src/com/android/systemui/media/dialog/MediaOutputGroupAdapter.java
index 11d76db..a201c07 100644
--- a/packages/SystemUI/src/com/android/systemui/media/dialog/MediaOutputGroupAdapter.java
+++ b/packages/SystemUI/src/com/android/systemui/media/dialog/MediaOutputGroupAdapter.java
@@ -126,7 +126,6 @@
@Override
void onBind(int customizedItem, boolean topMargin, boolean bottomMargin) {
- super.onBind(customizedItem, topMargin, bottomMargin);
if (customizedItem == CUSTOMIZED_ITEM_GROUP) {
setTwoLineLayout(mContext.getText(R.string.media_output_dialog_group),
true /* bFocused */, true /* showSeekBar */, false /* showProgressBar */,
diff --git a/packages/SystemUI/src/com/android/systemui/navigationbar/NavigationBar.java b/packages/SystemUI/src/com/android/systemui/navigationbar/NavigationBar.java
index 7809b5f..6a1eae7 100644
--- a/packages/SystemUI/src/com/android/systemui/navigationbar/NavigationBar.java
+++ b/packages/SystemUI/src/com/android/systemui/navigationbar/NavigationBar.java
@@ -131,6 +131,8 @@
import com.android.systemui.plugins.statusbar.StatusBarStateController;
import com.android.systemui.recents.OverviewProxyService;
import com.android.systemui.recents.Recents;
+import com.android.systemui.shared.rotation.RotationButton;
+import com.android.systemui.shared.rotation.RotationButtonController;
import com.android.systemui.settings.UserTracker;
import com.android.systemui.shared.recents.utilities.Utilities;
import com.android.systemui.shared.system.ActivityManagerWrapper;
@@ -944,7 +946,6 @@
// not valid. Just ignore the rotation in this case.
if (!mNavigationBarView.isAttachedToWindow()) return;
- final int winRotation = mNavigationBarView.getDisplay().getRotation();
final boolean rotateSuggestionsDisabled = RotationButtonController
.hasDisable2RotateSuggestionFlag(mDisabledFlags2);
final RotationButtonController rotationButtonController =
@@ -953,7 +954,6 @@
if (RotationContextButton.DEBUG_ROTATION) {
Log.v(TAG, "onRotationProposal proposedRotation=" + Surface.rotationToString(rotation)
- + ", winRotation=" + Surface.rotationToString(winRotation)
+ ", isValid=" + isValid + ", mNavBarWindowState="
+ StatusBarManager.windowStateToString(mNavigationBarWindowState)
+ ", rotateSuggestionsDisabled=" + rotateSuggestionsDisabled
@@ -963,7 +963,7 @@
// Respect the disabled flag, no need for action as flag change callback will handle hiding
if (rotateSuggestionsDisabled) return;
- rotationButtonController.onRotationProposal(rotation, winRotation, isValid);
+ rotationButtonController.onRotationProposal(rotation, isValid);
}
@Override
diff --git a/packages/SystemUI/src/com/android/systemui/navigationbar/NavigationBarView.java b/packages/SystemUI/src/com/android/systemui/navigationbar/NavigationBarView.java
index c02cc8d..cba76e0 100644
--- a/packages/SystemUI/src/com/android/systemui/navigationbar/NavigationBarView.java
+++ b/packages/SystemUI/src/com/android/systemui/navigationbar/NavigationBarView.java
@@ -67,7 +67,6 @@
import com.android.systemui.R;
import com.android.systemui.animation.Interpolators;
import com.android.systemui.model.SysUiState;
-import com.android.systemui.navigationbar.RotationButton.RotationButtonUpdatesCallback;
import com.android.systemui.navigationbar.buttons.ButtonDispatcher;
import com.android.systemui.navigationbar.buttons.ContextualButton;
import com.android.systemui.navigationbar.buttons.ContextualButtonGroup;
@@ -76,9 +75,11 @@
import com.android.systemui.navigationbar.buttons.NearestTouchFrame;
import com.android.systemui.navigationbar.buttons.RotationContextButton;
import com.android.systemui.navigationbar.gestural.EdgeBackGestureHandler;
-import com.android.systemui.navigationbar.gestural.FloatingRotationButton;
+import com.android.systemui.shared.rotation.FloatingRotationButton;
import com.android.systemui.recents.OverviewProxyService;
import com.android.systemui.recents.Recents;
+import com.android.systemui.shared.rotation.RotationButton.RotationButtonUpdatesCallback;
+import com.android.systemui.shared.rotation.RotationButtonController;
import com.android.systemui.shared.navigationbar.RegionSamplingHelper;
import com.android.systemui.shared.system.ActivityManagerWrapper;
import com.android.systemui.shared.system.QuickStepContract;
@@ -322,9 +323,15 @@
mContextualButtonGroup.addButton(accessibilityButton);
mRotationContextButton = new RotationContextButton(R.id.rotate_suggestion,
mLightContext, R.drawable.ic_sysbar_rotate_button_ccw_start_0);
- mFloatingRotationButton = new FloatingRotationButton(context);
- mRotationButtonController = new RotationButtonController(mLightContext,
- mLightIconColor, mDarkIconColor);
+ mFloatingRotationButton = new FloatingRotationButton(context,
+ R.string.accessibility_rotate_button);
+ mRotationButtonController = new RotationButtonController(mLightContext, mLightIconColor,
+ mDarkIconColor, R.drawable.ic_sysbar_rotate_button_ccw_start_0,
+ R.drawable.ic_sysbar_rotate_button_ccw_start_90,
+ R.drawable.ic_sysbar_rotate_button_cw_start_0,
+ R.drawable.ic_sysbar_rotate_button_cw_start_90,
+ () -> getDisplay().getRotation());
+
updateRotationButton();
mOverviewProxyService = Dependency.get(OverviewProxyService.class);
@@ -661,7 +668,7 @@
}
public void setBehavior(@Behavior int behavior) {
- mRotationButtonController.onBehaviorChanged(behavior);
+ mRotationButtonController.onBehaviorChanged(Display.DEFAULT_DISPLAY, behavior);
}
@Override
@@ -1277,6 +1284,7 @@
mButtonDispatchers.valueAt(i).onDestroy();
}
if (mRotationButtonController != null) {
+ mFloatingRotationButton.hide();
mRotationButtonController.unregisterListeners();
}
diff --git a/packages/SystemUI/src/com/android/systemui/navigationbar/RotationButton.java b/packages/SystemUI/src/com/android/systemui/navigationbar/RotationButton.java
deleted file mode 100644
index 3486c6e..0000000
--- a/packages/SystemUI/src/com/android/systemui/navigationbar/RotationButton.java
+++ /dev/null
@@ -1,48 +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.systemui.navigationbar;
-
-import android.view.View;
-
-import com.android.systemui.navigationbar.buttons.KeyButtonDrawable;
-
-/** Interface of a rotation button that interacts {@link RotationButtonController}. */
-public interface RotationButton {
- void setRotationButtonController(RotationButtonController rotationButtonController);
- void setUpdatesCallback(RotationButtonUpdatesCallback updatesCallback);
- View getCurrentView();
- boolean show();
- boolean hide();
- boolean isVisible();
- void updateIcon(int lightIconColor, int darkIconColor);
- void setOnClickListener(View.OnClickListener onClickListener);
- void setOnHoverListener(View.OnHoverListener onHoverListener);
- KeyButtonDrawable getImageDrawable();
- void setDarkIntensity(float darkIntensity);
- default void setCanShowRotationButton(boolean canShow) {}
- default boolean acceptRotationProposal() {
- return getCurrentView() != null;
- }
-
- /**
- * Callback for updates provided by a rotation button
- */
- interface RotationButtonUpdatesCallback {
- void onVisibilityChanged(boolean isVisible);
- void onPositionChanged();
- }
-}
diff --git a/packages/SystemUI/src/com/android/systemui/navigationbar/buttons/RotationContextButton.java b/packages/SystemUI/src/com/android/systemui/navigationbar/buttons/RotationContextButton.java
index ebb67af..ac014b5 100644
--- a/packages/SystemUI/src/com/android/systemui/navigationbar/buttons/RotationContextButton.java
+++ b/packages/SystemUI/src/com/android/systemui/navigationbar/buttons/RotationContextButton.java
@@ -21,8 +21,8 @@
import android.content.Context;
import android.view.View;
-import com.android.systemui.navigationbar.RotationButton;
-import com.android.systemui.navigationbar.RotationButtonController;
+import com.android.systemui.shared.rotation.RotationButton;
+import com.android.systemui.shared.rotation.RotationButtonController;
/** Containing logic for the rotation button in nav bar. */
public class RotationContextButton extends ContextualButton implements RotationButton {
diff --git a/packages/SystemUI/src/com/android/systemui/privacy/PrivacyDialog.kt b/packages/SystemUI/src/com/android/systemui/privacy/PrivacyDialog.kt
index 9e8f6b8..23482677 100644
--- a/packages/SystemUI/src/com/android/systemui/privacy/PrivacyDialog.kt
+++ b/packages/SystemUI/src/com/android/systemui/privacy/PrivacyDialog.kt
@@ -24,7 +24,6 @@
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
-import android.view.ViewGroup.LayoutParams.WRAP_CONTENT
import android.view.WindowInsets
import android.widget.ImageView
import android.widget.TextView
@@ -65,7 +64,6 @@
window?.apply {
attributes.fitInsetsTypes = attributes.fitInsetsTypes or WindowInsets.Type.statusBars()
attributes.receiveInsetsIgnoringZOrder = true
- setLayout(context.resources.getDimensionPixelSize(R.dimen.qs_panel_width), WRAP_CONTENT)
setGravity(Gravity.TOP or Gravity.CENTER_HORIZONTAL)
}
diff --git a/packages/SystemUI/src/com/android/systemui/qs/FooterActionsController.kt b/packages/SystemUI/src/com/android/systemui/qs/FooterActionsController.kt
index 4f87cad..98b9146 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/FooterActionsController.kt
+++ b/packages/SystemUI/src/com/android/systemui/qs/FooterActionsController.kt
@@ -72,12 +72,6 @@
private var listening: Boolean = false
var expanded = false
- set(value) {
- if (field != value) {
- field = value
- updateView()
- }
- }
private val settingsButton: SettingsButton = view.findViewById(R.id.settings_button)
private val settingsButtonContainer: View? = view.findViewById(R.id.settings_button_container)
@@ -176,8 +170,7 @@
}
private fun updateView() {
- mView.updateEverything(buttonsVisible(), isTunerEnabled(),
- multiUserSwitchController.isMultiUserEnabled)
+ mView.updateEverything(isTunerEnabled(), multiUserSwitchController.isMultiUserEnabled)
}
override fun onViewDetached() {
@@ -191,14 +184,14 @@
this.listening = listening
if (this.listening) {
userInfoController.addCallback(onUserInfoChangedListener)
+ updateView()
} else {
userInfoController.removeCallback(onUserInfoChangedListener)
}
}
fun disable(state2: Int) {
- mView.disable(buttonsVisible(), state2, isTunerEnabled(),
- multiUserSwitchController.isMultiUserEnabled)
+ mView.disable(state2, isTunerEnabled(), multiUserSwitchController.isMultiUserEnabled)
}
fun setExpansion(headerExpansionFraction: Float) {
diff --git a/packages/SystemUI/src/com/android/systemui/qs/FooterActionsView.kt b/packages/SystemUI/src/com/android/systemui/qs/FooterActionsView.kt
index 941e54a..f81f7bf 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/FooterActionsView.kt
+++ b/packages/SystemUI/src/com/android/systemui/qs/FooterActionsView.kt
@@ -107,7 +107,6 @@
}
fun disable(
- buttonsVisible: Boolean,
state2: Int,
isTunerEnabled: Boolean,
multiUserEnabled: Boolean
@@ -115,16 +114,15 @@
val disabled = state2 and StatusBarManager.DISABLE2_QUICK_SETTINGS != 0
if (disabled == qsDisabled) return
qsDisabled = disabled
- updateEverything(buttonsVisible, isTunerEnabled, multiUserEnabled)
+ updateEverything(isTunerEnabled, multiUserEnabled)
}
fun updateEverything(
- buttonsVisible: Boolean,
isTunerEnabled: Boolean,
multiUserEnabled: Boolean
) {
post {
- updateVisibilities(buttonsVisible, isTunerEnabled, multiUserEnabled)
+ updateVisibilities(isTunerEnabled, multiUserEnabled)
updateClickabilities()
isClickable = false
}
@@ -137,15 +135,14 @@
}
private fun updateVisibilities(
- buttonsVisible: Boolean,
isTunerEnabled: Boolean,
multiUserEnabled: Boolean
) {
settingsContainer.visibility = if (qsDisabled) GONE else VISIBLE
tunerIcon.visibility = if (isTunerEnabled) VISIBLE else INVISIBLE
- multiUserSwitch.visibility = if (buttonsVisible && multiUserEnabled) VISIBLE else GONE
+ multiUserSwitch.visibility = if (multiUserEnabled) VISIBLE else GONE
val isDemo = UserManager.isDeviceInDemoMode(context)
- settingsButton.visibility = if (isDemo || !buttonsVisible) INVISIBLE else VISIBLE
+ settingsButton.visibility = if (isDemo) INVISIBLE else VISIBLE
}
fun onUserInfoChanged(picture: Drawable?, isGuestUser: Boolean) {
diff --git a/packages/SystemUI/src/com/android/systemui/qs/PagedTileLayout.java b/packages/SystemUI/src/com/android/systemui/qs/PagedTileLayout.java
index 1a7a306..1784f73 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/PagedTileLayout.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/PagedTileLayout.java
@@ -112,6 +112,16 @@
@Override
protected void onConfigurationChanged(Configuration newConfig) {
super.onConfigurationChanged(newConfig);
+ // Pass configuration change to non-attached pages as well. Some config changes will cause
+ // QS to recreate itself (as determined in FragmentHostManager), but in order to minimize
+ // those, make sure that all get passed to all pages.
+ int numPages = mPages.size();
+ for (int i = 0; i < numPages; i++) {
+ View page = mPages.get(i);
+ if (page.getParent() == null) {
+ page.dispatchConfigurationChanged(newConfig);
+ }
+ }
if (mLayoutOrientation != newConfig.orientation) {
mLayoutOrientation = newConfig.orientation;
mDistributeTiles = true;
@@ -166,6 +176,11 @@
updateListening();
}
+ @Override
+ public void setSquishinessFraction(float squishinessFraction) {
+ // No-op, paged layouts are not squishy.
+ }
+
private void updateListening() {
for (TileLayout tilePage : mPages) {
tilePage.setListening(tilePage.getParent() != null && mListening);
diff --git a/packages/SystemUI/src/com/android/systemui/qs/QSAnimator.java b/packages/SystemUI/src/com/android/systemui/qs/QSAnimator.java
index 90d3448..44d5e21 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/QSAnimator.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/QSAnimator.java
@@ -316,8 +316,8 @@
if (mQQSTileHeightAnimator == null) {
mQQSTileHeightAnimator = new HeightExpansionAnimator(this,
- quickTileView.getHeight(), tileView.getHeight());
- qqsTileHeight = quickTileView.getHeight();
+ quickTileView.getMeasuredHeight(), tileView.getMeasuredHeight());
+ qqsTileHeight = quickTileView.getMeasuredHeight();
}
mQQSTileHeightAnimator.addView(quickTileView);
@@ -380,7 +380,7 @@
if (mOtherTilesExpandAnimator == null) {
mOtherTilesExpandAnimator =
new HeightExpansionAnimator(
- this, qqsTileHeight, tileView.getHeight());
+ this, qqsTileHeight, tileView.getMeasuredHeight());
}
mOtherTilesExpandAnimator.addView(tileView);
tileView.setClipChildren(true);
@@ -658,7 +658,7 @@
mTranslateWhileExpanding = shouldTranslate;
}
- static class HeightExpansionAnimator {
+ private static class HeightExpansionAnimator {
private final List<View> mViews = new ArrayList<>();
private final ValueAnimator mAnimator;
private final TouchAnimator.Listener mListener;
@@ -673,9 +673,10 @@
int height = (Integer) valueAnimator.getAnimatedValue();
for (int i = 0; i < viewCount; i++) {
View v = mViews.get(i);
- v.setBottom(v.getTop() + height);
if (v instanceof HeightOverrideable) {
((HeightOverrideable) v).setHeightOverride(height);
+ } else {
+ v.setBottom(v.getTop() + height);
}
}
if (t == 0f) {
@@ -713,9 +714,10 @@
final int viewsCount = mViews.size();
for (int i = 0; i < viewsCount; i++) {
View v = mViews.get(i);
- v.setBottom(v.getTop() + v.getMeasuredHeight());
if (v instanceof HeightOverrideable) {
((HeightOverrideable) v).resetOverride();
+ } else {
+ v.setBottom(v.getTop() + v.getMeasuredHeight());
}
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/qs/QSContainerImpl.java b/packages/SystemUI/src/com/android/systemui/qs/QSContainerImpl.java
index 3fc4f50..8588ddf 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/QSContainerImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/QSContainerImpl.java
@@ -32,6 +32,7 @@
import com.android.systemui.Dumpable;
import com.android.systemui.R;
import com.android.systemui.qs.customize.QSCustomizer;
+import com.android.systemui.util.Utils;
import java.io.FileDescriptor;
import java.io.PrintWriter;
@@ -155,8 +156,7 @@
QuickStatusBarHeaderController quickStatusBarHeaderController) {
mQSPanelContainer.setPaddingRelative(
getPaddingStart(),
- mContext.getResources()
- .getDimensionPixelSize(R.dimen.qs_header_system_icons_area_height),
+ Utils.getQsHeaderSystemIconsAreaHeight(mContext),
getPaddingEnd(),
getPaddingBottom()
);
diff --git a/packages/SystemUI/src/com/android/systemui/qs/QSDetail.java b/packages/SystemUI/src/com/android/systemui/qs/QSDetail.java
index 58a942a..d43404b 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/QSDetail.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/QSDetail.java
@@ -40,6 +40,7 @@
import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.logging.MetricsLogger;
import com.android.internal.logging.UiEventLogger;
+import com.android.internal.policy.SystemBarUtils;
import com.android.systemui.Dependency;
import com.android.systemui.FontSizeUtils;
import com.android.systemui.R;
@@ -164,8 +165,7 @@
public void updateResources() {
updateDetailText();
MarginLayoutParams lp = (MarginLayoutParams) getLayoutParams();
- lp.topMargin = mContext.getResources().getDimensionPixelSize(
- com.android.internal.R.dimen.quick_qs_offset_height);
+ lp.topMargin = SystemBarUtils.getQuickQsOffsetHeight(mContext);
setLayoutParams(lp);
}
diff --git a/packages/SystemUI/src/com/android/systemui/qs/QSFragment.java b/packages/SystemUI/src/com/android/systemui/qs/QSFragment.java
index 89bbcf5..eeca239 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/QSFragment.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/QSFragment.java
@@ -81,6 +81,7 @@
private QSAnimator mQSAnimator;
private HeightListener mPanelView;
+ private QSSquishinessController mQSSquishinessController;
protected QuickStatusBarHeader mHeader;
protected NonInterceptingScrollView mQSPanelScrollView;
private QSDetail mQSDetail;
@@ -90,6 +91,7 @@
private QSFooter mFooter;
private float mLastQSExpansion = -1;
private float mLastPanelFraction;
+ private float mSquishinessFraction = 1;
private boolean mQsDisabled;
private ImageView mQsDragHandler;
@@ -210,6 +212,7 @@
mQSDetail.setQsPanel(mQSPanelController, mHeader, mFooter, mFalsingManager);
mQSAnimator = qsFragmentComponent.getQSAnimator();
+ mQSSquishinessController = qsFragmentComponent.getQSSquishinessController();
mQSCustomizerController = qsFragmentComponent.getQSCustomizerController();
mQSCustomizerController.init();
@@ -231,7 +234,7 @@
boolean sizeChanged = (oldTop - oldBottom) != (top - bottom);
if (sizeChanged) {
setQsExpansion(mLastQSExpansion, mLastPanelFraction,
- mLastHeaderTranslation);
+ mLastHeaderTranslation, mSquishinessFraction);
}
});
mQSPanelController.setUsingHorizontalLayoutChangeListener(
@@ -413,7 +416,8 @@
mQSAnimator.setShowCollapsedOnKeyguard(showCollapsed);
}
if (!showCollapsed && isKeyguardState()) {
- setQsExpansion(mLastQSExpansion, mLastPanelFraction, 0);
+ setQsExpansion(mLastQSExpansion, mLastPanelFraction, 0,
+ mSquishinessFraction);
}
}
}
@@ -494,12 +498,13 @@
updateShowCollapsedOnKeyguard();
}
mFullShadeProgress = progress;
- setQsExpansion(mLastQSExpansion, mLastPanelFraction, mLastHeaderTranslation);
+ setQsExpansion(mLastQSExpansion, mLastPanelFraction, mLastHeaderTranslation,
+ isTransitioningToFullShade ? progress : mSquishinessFraction);
}
@Override
public void setQsExpansion(float expansion, float panelExpansionFraction,
- float proposedTranslation) {
+ float proposedTranslation, float squishinessFraction) {
float headerTranslation = mTransitioningToFullShade ? 0 : proposedTranslation;
float progress = mTransitioningToFullShade ? mFullShadeProgress : panelExpansionFraction;
setAlphaAnimationProgress(mInSplitShade ? progress : 1);
@@ -517,11 +522,13 @@
if (expansion == mLastQSExpansion
&& mLastKeyguardAndExpanded == onKeyguardAndExpanded
&& mLastViewHeight == currentHeight
- && mLastHeaderTranslation == headerTranslation) {
+ && mLastHeaderTranslation == headerTranslation
+ && mSquishinessFraction == squishinessFraction) {
return;
}
mLastHeaderTranslation = headerTranslation;
mLastPanelFraction = panelExpansionFraction;
+ mSquishinessFraction = squishinessFraction;
mLastQSExpansion = expansion;
mLastKeyguardAndExpanded = onKeyguardAndExpanded;
mLastViewHeight = currentHeight;
@@ -557,6 +564,9 @@
}
updateQsBounds();
+ if (mQSSquishinessController != null) {
+ mQSSquishinessController.setSquishiness(mSquishinessFraction);
+ }
if (mQSAnimator != null) {
mQSAnimator.setPosition(expansion);
}
diff --git a/packages/SystemUI/src/com/android/systemui/qs/QSPanel.java b/packages/SystemUI/src/com/android/systemui/qs/QSPanel.java
index 28aa884..71eb4a2 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/QSPanel.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/QSPanel.java
@@ -41,7 +41,7 @@
import com.android.systemui.R;
import com.android.systemui.plugins.qs.DetailAdapter;
import com.android.systemui.plugins.qs.QSTile;
-import com.android.systemui.settings.brightness.BrightnessSlider;
+import com.android.systemui.settings.brightness.BrightnessSliderController;
import com.android.systemui.statusbar.policy.BrightnessMirrorController;
import com.android.systemui.tuner.TunerService;
import com.android.systemui.tuner.TunerService.Tunable;
@@ -69,7 +69,7 @@
@Nullable
protected View mBrightnessView;
@Nullable
- protected BrightnessSlider mToggleSliderController;
+ protected BrightnessSliderController mToggleSliderController;
private final H mHandler = new H();
/** Whether or not the QS media player feature is enabled. */
@@ -736,6 +736,11 @@
void setListening(boolean listening, UiEventLogger uiEventLogger);
/**
+ * Sets a size modifier for the tile. Where 0 means collapsed, and 1 expanded.
+ */
+ void setSquishinessFraction(float squishinessFraction);
+
+ /**
* Sets the minimum number of rows to show
*
* @param minRows the minimum.
diff --git a/packages/SystemUI/src/com/android/systemui/qs/QSPanelController.java b/packages/SystemUI/src/com/android/systemui/qs/QSPanelController.java
index 70892a7..6794d5b 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/QSPanelController.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/QSPanelController.java
@@ -41,7 +41,7 @@
import com.android.systemui.qs.logging.QSLogger;
import com.android.systemui.settings.brightness.BrightnessController;
import com.android.systemui.settings.brightness.BrightnessMirrorHandler;
-import com.android.systemui.settings.brightness.BrightnessSlider;
+import com.android.systemui.settings.brightness.BrightnessSliderController;
import com.android.systemui.statusbar.CommandQueue;
import com.android.systemui.statusbar.policy.BrightnessMirrorController;
import com.android.systemui.tuner.TunerService;
@@ -63,7 +63,7 @@
private final FalsingManager mFalsingManager;
private final CommandQueue mCommandQueue;
private final BrightnessController mBrightnessController;
- private final BrightnessSlider mBrightnessSlider;
+ private final BrightnessSliderController mBrightnessSliderController;
private final BrightnessMirrorHandler mBrightnessMirrorHandler;
private boolean mGridContentVisible = true;
@@ -99,8 +99,8 @@
QSTileRevealController.Factory qsTileRevealControllerFactory,
DumpManager dumpManager, MetricsLogger metricsLogger, UiEventLogger uiEventLogger,
QSLogger qsLogger, BrightnessController.Factory brightnessControllerFactory,
- BrightnessSlider.Factory brightnessSliderFactory, FalsingManager falsingManager,
- CommandQueue commandQueue) {
+ BrightnessSliderController.Factory brightnessSliderFactory,
+ FalsingManager falsingManager, CommandQueue commandQueue) {
super(view, qstileHost, qsCustomizerController, usingMediaPlayer, mediaHost,
metricsLogger, uiEventLogger, qsLogger, dumpManager);
mQsSecurityFooter = qsSecurityFooter;
@@ -111,10 +111,10 @@
mCommandQueue = commandQueue;
mQsSecurityFooter.setHostEnvironment(qstileHost);
- mBrightnessSlider = brightnessSliderFactory.create(getContext(), mView);
- mView.setBrightnessView(mBrightnessSlider.getRootView());
+ mBrightnessSliderController = brightnessSliderFactory.create(getContext(), mView);
+ mView.setBrightnessView(mBrightnessSliderController.getRootView());
- mBrightnessController = brightnessControllerFactory.create(mBrightnessSlider);
+ mBrightnessController = brightnessControllerFactory.create(mBrightnessSliderController);
mBrightnessMirrorHandler = new BrightnessMirrorHandler(mBrightnessController);
}
@@ -125,7 +125,7 @@
mMediaHost.setShowsOnlyActiveMedia(false);
mMediaHost.init(MediaHierarchyManager.LOCATION_QS);
mQsCustomizerController.init();
- mBrightnessSlider.init();
+ mBrightnessSliderController.init();
}
@Override
diff --git a/packages/SystemUI/src/com/android/systemui/qs/QSSquishinessController.kt b/packages/SystemUI/src/com/android/systemui/qs/QSSquishinessController.kt
new file mode 100644
index 0000000..6de8370
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/qs/QSSquishinessController.kt
@@ -0,0 +1,64 @@
+package com.android.systemui.qs
+
+import android.view.ViewGroup
+import com.android.systemui.qs.dagger.QSFragmentModule.QQS_FOOTER
+import com.android.systemui.qs.dagger.QSScope
+import com.android.systemui.qs.tileimpl.HeightOverrideable
+import javax.inject.Inject
+import javax.inject.Named
+
+@QSScope
+class QSSquishinessController @Inject constructor(
+ private val qsTileHost: QSTileHost,
+ @Named(QQS_FOOTER) private val qqsFooterActionsView: FooterActionsView,
+ private val qsAnimator: QSAnimator,
+ private val quickQSPanelController: QuickQSPanelController
+) {
+
+ /**
+ * Fraction from 0 to 1, where 0 is collapsed and 1 expanded.
+ */
+ var squishiness: Float = 1f
+ set(value) {
+ if (field == value) {
+ return
+ }
+ if ((field != 1f && value == 1f) || (field != 0f && value == 0f)) {
+ qsAnimator.requestAnimatorUpdate()
+ }
+ field = value
+ updateSquishiness()
+ }
+
+ /**
+ * Change the height of all tiles and repositions their siblings.
+ */
+ private fun updateSquishiness() {
+ // Start by updating the height of all tiles
+ for (tile in qsTileHost.tiles) {
+ val tileView = quickQSPanelController.getTileView(tile)
+ (tileView as? HeightOverrideable)?.let {
+ it.squishinessFraction = squishiness
+ }
+ }
+
+ // Update tile positions in the layout
+ val tileLayout = quickQSPanelController.tileLayout as TileLayout
+ tileLayout.setSquishinessFraction(squishiness)
+
+ // Calculate how much we should move the footer
+ val tileHeightOffset = tileLayout.height - tileLayout.tilesHeight
+ val footerTopMargin = (qqsFooterActionsView.layoutParams as ViewGroup.MarginLayoutParams)
+ .topMargin
+ val nextTop = tileLayout.bottom - tileHeightOffset + footerTopMargin
+ val amountMoved = nextTop - qqsFooterActionsView.top
+
+ // Move the footer and other siblings (MediaPlayer)
+ (qqsFooterActionsView.parent as ViewGroup?)?.let { parent ->
+ val index = parent.indexOfChild(qqsFooterActionsView)
+ for (i in index until parent.childCount) {
+ parent.getChildAt(i).top += amountMoved
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/packages/SystemUI/src/com/android/systemui/qs/QuickQSBrightnessController.kt b/packages/SystemUI/src/com/android/systemui/qs/QuickQSBrightnessController.kt
index 14374ff..65889d7 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/QuickQSBrightnessController.kt
+++ b/packages/SystemUI/src/com/android/systemui/qs/QuickQSBrightnessController.kt
@@ -18,7 +18,7 @@
import androidx.annotation.VisibleForTesting
import com.android.systemui.settings.brightness.BrightnessController
-import com.android.systemui.settings.brightness.BrightnessSlider
+import com.android.systemui.settings.brightness.BrightnessSliderController
import com.android.systemui.settings.brightness.MirroredBrightnessController
import com.android.systemui.statusbar.policy.BrightnessMirrorController
import javax.inject.Inject
@@ -33,10 +33,11 @@
@Inject constructor(
brightnessControllerFactory: BrightnessController.Factory,
- brightnessSliderFactory: BrightnessSlider.Factory,
+ brightnessSliderControllerFactory: BrightnessSliderController.Factory,
quickQSPanel: QuickQSPanel
) : this(brightnessControllerFactory = {
- val slider = brightnessSliderFactory.create(quickQSPanel.context, quickQSPanel)
+ val slider = brightnessSliderControllerFactory.create(quickQSPanel.context,
+ quickQSPanel)
slider.init()
quickQSPanel.setBrightnessView(slider.rootView)
brightnessControllerFactory.create(slider)
diff --git a/packages/SystemUI/src/com/android/systemui/qs/QuickStatusBarHeader.java b/packages/SystemUI/src/com/android/systemui/qs/QuickStatusBarHeader.java
index a81d3c6..071e053 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/QuickStatusBarHeader.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/QuickStatusBarHeader.java
@@ -34,6 +34,7 @@
import androidx.annotation.NonNull;
+import com.android.internal.policy.SystemBarUtils;
import com.android.settingslib.Utils;
import com.android.systemui.R;
import com.android.systemui.battery.BatteryMeterView;
@@ -240,8 +241,7 @@
mRoundedCornerPadding = resources.getDimensionPixelSize(
R.dimen.rounded_corner_content_padding);
- int qsOffsetHeight = resources.getDimensionPixelSize(
- com.android.internal.R.dimen.quick_qs_offset_height);
+ int qsOffsetHeight = SystemBarUtils.getQuickQsOffsetHeight(mContext);
mDatePrivacyView.getLayoutParams().height =
Math.max(qsOffsetHeight, mDatePrivacyView.getMinimumHeight());
diff --git a/packages/SystemUI/src/com/android/systemui/qs/TileLayout.java b/packages/SystemUI/src/com/android/systemui/qs/TileLayout.java
index 1a890a7..ee5d5ff 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/TileLayout.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/TileLayout.java
@@ -41,6 +41,8 @@
private int mMinRows = 1;
private int mMaxColumns = NO_MAX_COLUMNS;
protected int mResourceColumns;
+ private float mSquishinessFraction = 1f;
+ private int mLastTileBottom;
public TileLayout(Context context) {
this(context, null);
@@ -210,10 +212,11 @@
return mMaxCellHeight;
}
- protected void layoutTileRecords(int numRecords) {
+ private void layoutTileRecords(int numRecords) {
final boolean isRtl = getLayoutDirection() == LAYOUT_DIRECTION_RTL;
int row = 0;
int column = 0;
+ mLastTileBottom = 0;
// Layout each QS tile.
final int tilesToLayout = Math.min(numRecords, mRows * mColumns);
@@ -228,7 +231,9 @@
final int top = getRowTop(row);
final int left = getColumnStart(isRtl ? mColumns - column - 1 : column);
final int right = left + mCellWidth;
- record.tileView.layout(left, top, right, top + record.tileView.getMeasuredHeight());
+ final int bottom = top + record.tileView.getMeasuredHeight();
+ record.tileView.layout(left, top, right, bottom);
+ mLastTileBottom = bottom;
}
}
@@ -238,7 +243,7 @@
}
protected int getRowTop(int row) {
- return row * (mCellHeight + mCellMarginVertical);
+ return (int) (row * (mCellHeight * mSquishinessFraction + mCellMarginVertical));
}
protected int getColumnStart(int column) {
@@ -264,4 +269,17 @@
// up.
return Math.max(mColumns * mRows, 1);
}
+
+ public int getTilesHeight() {
+ return mLastTileBottom + getPaddingBottom();
+ }
+
+ @Override
+ public void setSquishinessFraction(float squishinessFraction) {
+ if (Float.compare(mSquishinessFraction, squishinessFraction) == 0) {
+ return;
+ }
+ mSquishinessFraction = squishinessFraction;
+ layoutTileRecords(mRecords.size());
+ }
}
diff --git a/packages/SystemUI/src/com/android/systemui/qs/customize/QSCustomizer.java b/packages/SystemUI/src/com/android/systemui/qs/customize/QSCustomizer.java
index c692252..9ebdb1c 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/customize/QSCustomizer.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/customize/QSCustomizer.java
@@ -36,6 +36,7 @@
import com.android.systemui.plugins.qs.QSContainerController;
import com.android.systemui.qs.QSDetailClipper;
import com.android.systemui.statusbar.phone.LightBarController;
+import com.android.systemui.util.Utils;
/**
* Allows full-screen customization of QS, through show() and hide().
@@ -84,8 +85,7 @@
void updateResources() {
LayoutParams lp = (LayoutParams) mTransparentView.getLayoutParams();
- lp.height = mContext.getResources()
- .getDimensionPixelSize(R.dimen.qs_header_system_icons_area_height);
+ lp.height = Utils.getQsHeaderSystemIconsAreaHeight(mContext);
mTransparentView.setLayoutParams(lp);
}
diff --git a/packages/SystemUI/src/com/android/systemui/qs/dagger/QSFragmentComponent.java b/packages/SystemUI/src/com/android/systemui/qs/dagger/QSFragmentComponent.java
index 8cc0502..63cbc21 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/dagger/QSFragmentComponent.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/dagger/QSFragmentComponent.java
@@ -21,6 +21,7 @@
import com.android.systemui.qs.QSFooter;
import com.android.systemui.qs.QSFragment;
import com.android.systemui.qs.QSPanelController;
+import com.android.systemui.qs.QSSquishinessController;
import com.android.systemui.qs.QuickQSPanelController;
import com.android.systemui.qs.customize.QSCustomizerController;
@@ -57,4 +58,7 @@
/** Construct a {@link QSCustomizerController}. */
QSCustomizerController getQSCustomizerController();
+
+ /** Construct a {@link QSSquishinessController}. */
+ QSSquishinessController getQSSquishinessController();
}
diff --git a/packages/SystemUI/src/com/android/systemui/qs/external/TileServiceRequestController.kt b/packages/SystemUI/src/com/android/systemui/qs/external/TileServiceRequestController.kt
index 3b85e5d..210ee93 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/external/TileServiceRequestController.kt
+++ b/packages/SystemUI/src/com/android/systemui/qs/external/TileServiceRequestController.kt
@@ -55,6 +55,8 @@
internal const val DISMISSED = StatusBarManager.TILE_ADD_REQUEST_RESULT_DIALOG_DISMISSED
}
+ private var dialogCanceller: ((String) -> Unit)? = null
+
private val commandQueueCallback = object : CommandQueue.Callbacks {
override fun requestAddTile(
componentName: ComponentName,
@@ -67,6 +69,10 @@
callback.onTileRequest(it)
}
}
+
+ override fun cancelRequestAddTile(packageName: String) {
+ dialogCanceller?.invoke(packageName)
+ }
}
fun init() {
@@ -95,16 +101,21 @@
callback.accept(TILE_ALREADY_ADDED)
return
}
- val dialogResponse = object : Consumer<Int> {
- override fun accept(response: Int) {
- if (response == ADD_TILE) {
- addTile(componentName)
- }
- callback.accept(response)
+ val dialogResponse = Consumer<Int> { response ->
+ if (response == ADD_TILE) {
+ addTile(componentName)
}
+ callback.accept(response)
}
val tileData = TileRequestDialog.TileData(appName, label, icon)
- createDialog(tileData, dialogResponse).show()
+ createDialog(tileData, dialogResponse).also { dialog ->
+ dialogCanceller = {
+ if (componentName.packageName == it) {
+ dialog.cancel()
+ }
+ dialogCanceller = null
+ }
+ }.show()
}
private fun createDialog(
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tileimpl/HeightOverrideable.kt b/packages/SystemUI/src/com/android/systemui/qs/tileimpl/HeightOverrideable.kt
index 866fa09..61d68ec 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tileimpl/HeightOverrideable.kt
+++ b/packages/SystemUI/src/com/android/systemui/qs/tileimpl/HeightOverrideable.kt
@@ -21,9 +21,8 @@
const val NO_OVERRIDE = -1
}
- var heightOverride: Int
+ abstract var heightOverride: Int
+ abstract fun resetOverride()
- fun resetOverride() {
- heightOverride = NO_OVERRIDE
- }
+ abstract var squishinessFraction: Float
}
\ No newline at end of file
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 ee5e4df..b496e6b 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tileimpl/QSTileViewImpl.kt
+++ b/packages/SystemUI/src/com/android/systemui/qs/tileimpl/QSTileViewImpl.kt
@@ -42,6 +42,7 @@
import com.android.settingslib.Utils
import com.android.systemui.FontSizeUtils
import com.android.systemui.R
+import com.android.systemui.animation.LaunchableView
import com.android.systemui.plugins.qs.QSIconView
import com.android.systemui.plugins.qs.QSTile
import com.android.systemui.plugins.qs.QSTile.BooleanState
@@ -54,7 +55,7 @@
context: Context,
private val _icon: QSIconView,
private val collapsed: Boolean = false
-) : QSTileView(context), HeightOverrideable {
+) : QSTileView(context), HeightOverrideable, LaunchableView {
companion object {
private const val INVALID = -1
@@ -68,6 +69,18 @@
}
override var heightOverride: Int = HeightOverrideable.NO_OVERRIDE
+ set(value) {
+ if (field == value) return
+ field = value
+ updateHeight()
+ }
+
+ override var squishinessFraction: Float = 1f
+ set(value) {
+ if (field == value) return
+ field = value
+ updateHeight()
+ }
private val colorActive = Utils.getColorAttrDefaultColor(context,
com.android.internal.R.attr.colorAccentPrimary)
@@ -118,6 +131,8 @@
private var lastStateDescription: CharSequence? = null
private var tileState = false
private var lastState = INVALID
+ private var blockVisibilityChanges = false
+ private var lastVisibility = View.VISIBLE
private val locInScreen = IntArray(2)
@@ -148,6 +163,11 @@
updateResources()
}
+ override fun resetOverride() {
+ heightOverride = HeightOverrideable.NO_OVERRIDE
+ updateHeight()
+ }
+
fun updateResources() {
FontSizeUtils.updateFontSize(label, R.dimen.qs_tile_text_size)
FontSizeUtils.updateFontSize(secondaryLabel, R.dimen.qs_tile_text_size)
@@ -218,9 +238,17 @@
override fun onLayout(changed: Boolean, l: Int, t: Int, r: Int, b: Int) {
super.onLayout(changed, l, t, r, b)
- if (heightOverride != HeightOverrideable.NO_OVERRIDE) {
- bottom = top + heightOverride
- }
+ updateHeight()
+ }
+
+ private fun updateHeight() {
+ val actualHeight = (if (heightOverride != HeightOverrideable.NO_OVERRIDE) {
+ heightOverride
+ } else {
+ measuredHeight
+ } * squishinessFraction).toInt()
+ bottom = top + actualHeight
+ scrollY = (actualHeight - height) / 2
}
override fun updateAccessibilityOrder(previousView: View?): View {
@@ -298,6 +326,36 @@
return sideView
}
+ override fun setShouldBlockVisibilityChanges(block: Boolean) {
+ blockVisibilityChanges = block
+
+ if (block) {
+ lastVisibility = visibility
+ } else {
+ visibility = lastVisibility
+ }
+ }
+
+ override fun setVisibility(visibility: Int) {
+ if (blockVisibilityChanges) {
+ lastVisibility = visibility
+ return
+ }
+
+ super.setVisibility(visibility)
+ }
+
+ override 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
+ }
+
+ super.setTransitionVisibility(visibility)
+ }
+
// Accessibility
override fun onInitializeAccessibilityEvent(event: AccessibilityEvent) {
@@ -463,7 +521,7 @@
}
private fun setColor(color: Int) {
- colorBackgroundDrawable.setTint(color)
+ colorBackgroundDrawable.mutate().setTint(color)
paintColor = color
}
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/DeviceControlsTile.kt b/packages/SystemUI/src/com/android/systemui/qs/tiles/DeviceControlsTile.kt
index bc21b2d..80ec0ad 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/DeviceControlsTile.kt
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/DeviceControlsTile.kt
@@ -112,20 +112,9 @@
}
mUiHandler.post {
- if (keyguardStateController.isUnlocked) {
- mActivityStarter.startActivity(
- intent, true /* dismissShade */, animationController)
- } else {
- if (state.state == Tile.STATE_ACTIVE) {
- mHost.collapsePanels()
- // With an active tile, don't use ActivityStarter so that the activity is
- // started without prompting keyguard unlock.
- mContext.startActivity(intent)
- } else {
- mActivityStarter.postStartActivityDismissingKeyguard(
- intent, 0 /* delay */, animationController)
- }
- }
+ val showOverLockscreenWhenLocked = state.state == Tile.STATE_ACTIVE
+ mActivityStarter.startActivity(
+ intent, true /* dismissShade */, animationController, showOverLockscreenWhenLocked)
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/InternetTile.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/InternetTile.java
index 98d0a72..23b2a76 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/InternetTile.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/InternetTile.java
@@ -124,7 +124,7 @@
protected void handleClick(@Nullable View view) {
mHandler.post(() -> mInternetDialogFactory.create(true,
mAccessPointController.canConfigMobileData(),
- mAccessPointController.canConfigWifi()));
+ mAccessPointController.canConfigWifi(), view));
}
@Override
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/dialog/InternetDialog.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/dialog/InternetDialog.java
index 15b78e7..1dab263 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/dialog/InternetDialog.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/dialog/InternetDialog.java
@@ -15,14 +15,10 @@
*/
package com.android.systemui.qs.tiles.dialog;
-import static android.view.WindowManager.LayoutParams.FLAG_LAYOUT_NO_LIMITS;
-
import static com.android.systemui.Prefs.Key.QS_HAS_TURNED_OFF_MOBILE_DATA;
import android.app.AlertDialog;
import android.content.Context;
-import android.graphics.Color;
-import android.graphics.drawable.ColorDrawable;
import android.graphics.drawable.Drawable;
import android.net.Network;
import android.net.NetworkCapabilities;
@@ -41,10 +37,7 @@
import android.view.Gravity;
import android.view.LayoutInflater;
import android.view.View;
-import android.view.ViewGroup;
-import android.view.ViewTreeObserver;
import android.view.Window;
-import android.view.WindowInsets;
import android.view.WindowManager;
import android.widget.FrameLayout;
import android.widget.ImageView;
@@ -87,7 +80,6 @@
private final Handler mHandler;
private final Executor mBackgroundExecutor;
- private final LinearLayoutManager mLayoutManager;
@VisibleForTesting
protected InternetAdapter mAdapter;
@@ -130,7 +122,6 @@
private Switch mWiFiToggle;
private FrameLayout mDoneLayout;
private Drawable mBackgroundOn;
- private int mListMaxHeight;
private int mDefaultDataSubId = SubscriptionManager.INVALID_SUBSCRIPTION_ID;
private boolean mCanConfigMobileData;
@@ -149,20 +140,11 @@
mInternetDialogSubTitle.setText(getSubtitleText());
};
- private final ViewTreeObserver.OnGlobalLayoutListener mInternetListLayoutListener = () -> {
- // Set max height for list
- if (mInternetDialogLayout.getHeight() > mListMaxHeight) {
- ViewGroup.LayoutParams params = mInternetDialogLayout.getLayoutParams();
- params.height = mListMaxHeight;
- mInternetDialogLayout.setLayoutParams(params);
- }
- };
-
public InternetDialog(Context context, InternetDialogFactory internetDialogFactory,
InternetDialogController internetDialogController, boolean canConfigMobileData,
boolean canConfigWifi, boolean aboveStatusBar, UiEventLogger uiEventLogger,
@Main Handler handler, @Background Executor executor) {
- super(context, R.style.Theme_SystemUI_Dialog_Internet);
+ super(context);
if (DEBUG) {
Log.d(TAG, "Init InternetDialog");
}
@@ -178,14 +160,6 @@
mCanConfigMobileData = canConfigMobileData;
mCanConfigWifi = canConfigWifi;
- mLayoutManager = new LinearLayoutManager(mContext) {
- @Override
- public boolean canScrollVertically() {
- return false;
- }
- };
- mListMaxHeight = context.getResources().getDimensionPixelSize(
- R.dimen.internet_dialog_list_max_height);
mUiEventLogger = uiEventLogger;
mAdapter = new InternetAdapter(mInternetDialogController);
if (!aboveStatusBar) {
@@ -203,21 +177,9 @@
mDialogView = LayoutInflater.from(mContext).inflate(R.layout.internet_connectivity_dialog,
null);
final Window window = getWindow();
- final WindowManager.LayoutParams layoutParams = window.getAttributes();
- layoutParams.gravity = Gravity.BOTTOM;
- // Move down the dialog to overlay the navigation bar.
- layoutParams.setFitInsetsTypes(
- layoutParams.getFitInsetsTypes() & ~WindowInsets.Type.navigationBars());
- layoutParams.setFitInsetsSides(WindowInsets.Side.all());
- layoutParams.setFitInsetsIgnoringVisibility(true);
- window.setAttributes(layoutParams);
window.setContentView(mDialogView);
- //Only fix the width for large screen or tablet.
- window.setLayout(mContext.getResources().getDimensionPixelSize(
- R.dimen.large_dialog_width), ViewGroup.LayoutParams.WRAP_CONTENT);
+
window.setWindowAnimations(R.style.Animation_InternetDialog);
- window.setBackgroundDrawable(new ColorDrawable(Color.TRANSPARENT));
- window.addFlags(FLAG_LAYOUT_NO_LIMITS);
mInternetDialogLayout = mDialogView.requireViewById(R.id.internet_connectivity_dialog);
mInternetDialogTitle = mDialogView.requireViewById(R.id.internet_dialog_title);
@@ -244,14 +206,12 @@
mMobileDataToggle = mDialogView.requireViewById(R.id.mobile_toggle);
mWiFiToggle = mDialogView.requireViewById(R.id.wifi_toggle);
mBackgroundOn = mContext.getDrawable(R.drawable.settingslib_switch_bar_bg_on);
- mInternetDialogLayout.getViewTreeObserver().addOnGlobalLayoutListener(
- mInternetListLayoutListener);
mInternetDialogTitle.setText(getDialogTitleText());
mInternetDialogTitle.setGravity(Gravity.START | Gravity.CENTER_VERTICAL);
setOnClickListener();
mTurnWifiOnLayout.setBackground(null);
- mWifiRecyclerView.setLayoutManager(mLayoutManager);
+ mWifiRecyclerView.setLayoutManager(new LinearLayoutManager(mContext));
mWifiRecyclerView.setAdapter(mAdapter);
}
@@ -331,7 +291,7 @@
showProgressBar();
final boolean isDeviceLocked = mInternetDialogController.isDeviceLocked();
final boolean isWifiEnabled = mWifiManager.isWifiEnabled();
- final boolean isWifiScanEnabled = mWifiManager.isScanAlwaysAvailable();
+ final boolean isWifiScanEnabled = mInternetDialogController.isWifiScanEnabled();
updateWifiToggle(isWifiEnabled, isDeviceLocked);
updateConnectedWifi(isWifiEnabled, isDeviceLocked);
updateWifiScanNotify(isWifiEnabled, isWifiScanEnabled, isDeviceLocked);
@@ -502,10 +462,6 @@
}
private void setProgressBarVisible(boolean visible) {
- if (mWifiManager.isWifiEnabled() && mAdapter.mHolderView != null
- && mAdapter.mHolderView.isAttachedToWindow()) {
- mIsProgressBarVisible = true;
- }
mIsProgressBarVisible = visible;
mProgressBar.setVisibility(mIsProgressBarVisible ? View.VISIBLE : View.GONE);
mDivider.setVisibility(mIsProgressBarVisible ? View.GONE : View.VISIBLE);
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/dialog/InternetDialogController.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/dialog/InternetDialogController.java
index 1ade5ce..5673136 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/dialog/InternetDialogController.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/dialog/InternetDialogController.java
@@ -71,6 +71,7 @@
import com.android.settingslib.net.SignalStrengthUtil;
import com.android.settingslib.wifi.WifiUtils;
import com.android.systemui.R;
+import com.android.systemui.animation.DialogLaunchAnimator;
import com.android.systemui.broadcast.BroadcastDispatcher;
import com.android.systemui.dagger.qualifiers.Background;
import com.android.systemui.dagger.qualifiers.Main;
@@ -78,6 +79,7 @@
import com.android.systemui.statusbar.connectivity.NetworkController;
import com.android.systemui.statusbar.connectivity.NetworkController.AccessPointController;
import com.android.systemui.statusbar.policy.KeyguardStateController;
+import com.android.systemui.statusbar.policy.LocationController;
import com.android.systemui.toast.SystemUIToast;
import com.android.systemui.toast.ToastFactory;
import com.android.systemui.util.CarrierConfigTracker;
@@ -150,6 +152,8 @@
private WindowManager mWindowManager;
private ToastFactory mToastFactory;
private SignalDrawable mSignalDrawable;
+ private LocationController mLocationController;
+ private DialogLaunchAnimator mDialogLaunchAnimator;
@VisibleForTesting
static final float TOAST_PARAMS_HORIZONTAL_WEIGHT = 1.0f;
@@ -199,7 +203,9 @@
GlobalSettings globalSettings, KeyguardStateController keyguardStateController,
WindowManager windowManager, ToastFactory toastFactory,
@Background Handler workerHandler,
- CarrierConfigTracker carrierConfigTracker) {
+ CarrierConfigTracker carrierConfigTracker,
+ LocationController locationController,
+ DialogLaunchAnimator dialogLaunchAnimator) {
if (DEBUG) {
Log.d(TAG, "Init InternetDialogController");
}
@@ -227,6 +233,8 @@
mWindowManager = windowManager;
mToastFactory = toastFactory;
mSignalDrawable = new SignalDrawable(mContext);
+ mLocationController = locationController;
+ mDialogLaunchAnimator = dialogLaunchAnimator;
}
void onStart(@NonNull InternetDialogCallback callback, boolean canConfigWifi) {
@@ -592,20 +600,32 @@
}
void launchNetworkSetting() {
+ // Dismissing a dialog into its touch surface and starting an activity at the same time
+ // looks bad, so let's make sure the dialog just fades out quickly.
+ mDialogLaunchAnimator.disableAllCurrentDialogsExitAnimations();
mCallback.dismissDialog();
+
mActivityStarter.postStartActivityDismissingKeyguard(getSettingsIntent(), 0);
}
void launchWifiNetworkDetailsSetting(String key) {
Intent intent = getWifiDetailsSettingsIntent(key);
if (intent != null) {
+ // Dismissing a dialog into its touch surface and starting an activity at the same time
+ // looks bad, so let's make sure the dialog just fades out quickly.
+ mDialogLaunchAnimator.disableAllCurrentDialogsExitAnimations();
mCallback.dismissDialog();
+
mActivityStarter.postStartActivityDismissingKeyguard(intent, 0);
}
}
void launchWifiScanningSetting() {
+ // Dismissing a dialog into its touch surface and starting an activity at the same time
+ // looks bad, so let's make sure the dialog just fades out quickly.
+ mDialogLaunchAnimator.disableAllCurrentDialogsExitAnimations();
mCallback.dismissDialog();
+
final Intent intent = new Intent(ACTION_WIFI_SCANNING_SETTINGS);
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
mActivityStarter.postStartActivityDismissingKeyguard(intent, 0);
@@ -788,6 +808,14 @@
return false;
}
+ @WorkerThread
+ boolean isWifiScanEnabled() {
+ if (!mLocationController.isLocationEnabled()) {
+ return false;
+ }
+ return mWifiManager.isScanAlwaysAvailable();
+ }
+
static class WifiEntryConnectCallback implements WifiEntry.ConnectCallback {
final ActivityStarter mActivityStarter;
final WifiEntry mWifiEntry;
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/dialog/InternetDialogFactory.kt b/packages/SystemUI/src/com/android/systemui/qs/tiles/dialog/InternetDialogFactory.kt
index ea5df17..93828b3 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/dialog/InternetDialogFactory.kt
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/dialog/InternetDialogFactory.kt
@@ -18,9 +18,11 @@
import android.content.Context
import android.os.Handler
import android.util.Log
+import android.view.View
import com.android.internal.logging.UiEventLogger
+import com.android.systemui.animation.DialogLaunchAnimator
import com.android.systemui.dagger.SysUISingleton
-import com.android.systemui.dagger.qualifiers.Background;
+import com.android.systemui.dagger.qualifiers.Background
import com.android.systemui.dagger.qualifiers.Main
import java.util.concurrent.Executor
import javax.inject.Inject
@@ -37,14 +39,20 @@
@Background private val executor: Executor,
private val internetDialogController: InternetDialogController,
private val context: Context,
- private val uiEventLogger: UiEventLogger
+ private val uiEventLogger: UiEventLogger,
+ private val dialogLaunchAnimator: DialogLaunchAnimator
) {
companion object {
var internetDialog: InternetDialog? = null
}
- /** Creates a [InternetDialog]. */
- fun create(aboveStatusBar: Boolean, canConfigMobileData: Boolean, canConfigWifi: Boolean) {
+ /** Creates a [InternetDialog]. The dialog will be animated from [view] if it is not null. */
+ fun create(
+ aboveStatusBar: Boolean,
+ canConfigMobileData: Boolean,
+ canConfigWifi: Boolean,
+ view: View?
+ ) {
if (internetDialog != null) {
if (DEBUG) {
Log.d(TAG, "InternetDialog is showing, do not create it twice.")
@@ -54,7 +62,11 @@
internetDialog = InternetDialog(context, this, internetDialogController,
canConfigMobileData, canConfigWifi, aboveStatusBar, uiEventLogger, handler,
executor)
- internetDialog?.show()
+ if (view != null) {
+ dialogLaunchAnimator.showFromView(internetDialog!!, view)
+ } else {
+ internetDialog?.show()
+ }
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/qs/user/UserDialog.kt b/packages/SystemUI/src/com/android/systemui/qs/user/UserDialog.kt
index 01afa56..26d1bbd 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/user/UserDialog.kt
+++ b/packages/SystemUI/src/com/android/systemui/qs/user/UserDialog.kt
@@ -71,10 +71,6 @@
setType(WindowManager.LayoutParams.TYPE_STATUS_BAR_SUB_PANEL)
attributes.fitInsetsTypes = attributes.fitInsetsTypes or WindowInsets.Type.statusBars()
attributes.receiveInsetsIgnoringZOrder = true
- setLayout(
- context.resources.getDimensionPixelSize(R.dimen.notification_panel_width),
- ViewGroup.LayoutParams.WRAP_CONTENT
- )
setGravity(Gravity.CENTER)
}
setContentView(R.layout.qs_user_dialog_content)
diff --git a/packages/SystemUI/src/com/android/systemui/settings/brightness/BrightnessController.java b/packages/SystemUI/src/com/android/systemui/settings/brightness/BrightnessController.java
index acc6ee1..d7d1de0 100644
--- a/packages/SystemUI/src/com/android/systemui/settings/brightness/BrightnessController.java
+++ b/packages/SystemUI/src/com/android/systemui/settings/brightness/BrightnessController.java
@@ -51,8 +51,6 @@
import com.android.systemui.settings.CurrentUserTracker;
import com.android.systemui.statusbar.policy.BrightnessMirrorController;
-import java.util.ArrayList;
-
import javax.inject.Inject;
public class BrightnessController implements ToggleSlider.Listener, MirroredBrightnessController {
@@ -92,13 +90,9 @@
@Override
public void onDisplayChanged(int displayId) {
mBackgroundHandler.post(mUpdateSliderRunnable);
- notifyCallbacks();
}
};
- private ArrayList<BrightnessStateChangeCallback> mChangeCallbacks =
- new ArrayList<BrightnessStateChangeCallback>();
-
private volatile boolean mAutomatic; // Brightness adjusted automatically using ambient light.
private volatile boolean mIsVrModeEnabled;
private boolean mListening;
@@ -114,11 +108,6 @@
mControl.setMirrorControllerAndMirror(controller);
}
- public interface BrightnessStateChangeCallback {
- /** Indicates that some of the brightness settings have changed */
- void onBrightnessLevelChanged();
- }
-
/** ContentObserver to watch brightness */
private class BrightnessObserver extends ContentObserver {
@@ -139,7 +128,6 @@
mBackgroundHandler.post(mUpdateModeRunnable);
mBackgroundHandler.post(mUpdateSliderRunnable);
}
- notifyCallbacks();
}
public void startObserving() {
@@ -317,14 +305,6 @@
Context.VR_SERVICE));
}
- public void addStateChangedCallback(BrightnessStateChangeCallback cb) {
- mChangeCallbacks.add(cb);
- }
-
- public boolean removeStateChangedCallback(BrightnessStateChangeCallback cb) {
- return mChangeCallbacks.remove(cb);
- }
-
public void registerCallbacks() {
mBackgroundHandler.post(mStartListeningRunnable);
}
@@ -375,10 +355,6 @@
}
});
}
-
- for (BrightnessStateChangeCallback cb : mChangeCallbacks) {
- cb.onBrightnessLevelChanged();
- }
}
public void checkRestrictionAndSetEnabled() {
@@ -435,8 +411,12 @@
}
private void animateSliderTo(int target) {
- if (!mControlValueInitialized) {
+ if (!mControlValueInitialized || !mControl.isVisible()) {
// Don't animate the first value since its default state isn't meaningful to users.
+ // We also don't want to animate slider if it's not visible - especially important when
+ // two sliders are active at the same time in split shade (one in QS and one in QQS),
+ // as this negatively affects transition between them and they share mirror slider -
+ // animating it from two different sources causes janky motion
mControl.setValue(target);
mControlValueInitialized = true;
}
@@ -455,13 +435,6 @@
mSliderAnimator.start();
}
- private void notifyCallbacks() {
- final int size = mChangeCallbacks.size();
- for (int i = 0; i < size; i++) {
- mChangeCallbacks.get(i).onBrightnessLevelChanged();
- }
- }
-
/** Factory for creating a {@link BrightnessController}. */
public static class Factory {
private final Context mContext;
diff --git a/packages/SystemUI/src/com/android/systemui/settings/brightness/BrightnessDialog.java b/packages/SystemUI/src/com/android/systemui/settings/brightness/BrightnessDialog.java
index 8fc831a..c9c1a9b 100644
--- a/packages/SystemUI/src/com/android/systemui/settings/brightness/BrightnessDialog.java
+++ b/packages/SystemUI/src/com/android/systemui/settings/brightness/BrightnessDialog.java
@@ -41,14 +41,14 @@
public class BrightnessDialog extends Activity {
private BrightnessController mBrightnessController;
- private final BrightnessSlider.Factory mToggleSliderFactory;
+ private final BrightnessSliderController.Factory mToggleSliderFactory;
private final BroadcastDispatcher mBroadcastDispatcher;
private final Handler mBackgroundHandler;
@Inject
public BrightnessDialog(
BroadcastDispatcher broadcastDispatcher,
- BrightnessSlider.Factory factory,
+ BrightnessSliderController.Factory factory,
@Background Handler bgHandler) {
mBroadcastDispatcher = broadcastDispatcher;
mToggleSliderFactory = factory;
@@ -77,7 +77,7 @@
// The brightness mirror container is INVISIBLE by default.
frame.setVisibility(View.VISIBLE);
- BrightnessSlider controller = mToggleSliderFactory.create(this, frame);
+ BrightnessSliderController controller = mToggleSliderFactory.create(this, frame);
controller.init();
frame.addView(controller.getRootView(), MATCH_PARENT, WRAP_CONTENT);
diff --git a/packages/SystemUI/src/com/android/systemui/settings/brightness/BrightnessSlider.java b/packages/SystemUI/src/com/android/systemui/settings/brightness/BrightnessSliderController.java
similarity index 89%
rename from packages/SystemUI/src/com/android/systemui/settings/brightness/BrightnessSlider.java
rename to packages/SystemUI/src/com/android/systemui/settings/brightness/BrightnessSliderController.java
index b0e320a..6c8190a 100644
--- a/packages/SystemUI/src/com/android/systemui/settings/brightness/BrightnessSlider.java
+++ b/packages/SystemUI/src/com/android/systemui/settings/brightness/BrightnessSliderController.java
@@ -44,7 +44,8 @@
*
* @see BrightnessMirrorController
*/
-public class BrightnessSlider extends ViewController<BrightnessSliderView> implements ToggleSlider {
+public class BrightnessSliderController extends ViewController<BrightnessSliderView> implements
+ ToggleSlider {
private Listener mListener;
private ToggleSlider mMirror;
@@ -69,7 +70,7 @@
}
};
- BrightnessSlider(
+ BrightnessSliderController(
BrightnessSliderView brightnessSliderView,
FalsingManager falsingManager) {
super(brightnessSliderView);
@@ -184,6 +185,15 @@
mView.setVisibility(View.VISIBLE);
}
+ @Override
+ public boolean isVisible() {
+ // this should be called rarely - once or twice per slider's value change, but not for
+ // every value change when user slides finger - only the final one.
+ // If view is not visible this call is quick (around 50 µs) as it sees parent is not visible
+ // otherwise it's slightly longer (70 µs) because there are more checks to be done
+ return mView.isVisibleToUser();
+ }
+
private final SeekBar.OnSeekBarChangeListener mSeekListener =
new SeekBar.OnSeekBarChangeListener() {
@Override
@@ -222,7 +232,7 @@
};
/**
- * Creates a {@link BrightnessSlider} with its associated view.
+ * Creates a {@link BrightnessSliderController} with its associated view.
*/
public static class Factory {
@@ -240,11 +250,11 @@
* @param viewRoot the {@link ViewGroup} that will contain the hierarchy. The inflated
* hierarchy will not be attached
*/
- public BrightnessSlider create(Context context, @Nullable ViewGroup viewRoot) {
+ public BrightnessSliderController create(Context context, @Nullable ViewGroup viewRoot) {
int layout = getLayout();
BrightnessSliderView root = (BrightnessSliderView) LayoutInflater.from(context)
.inflate(layout, viewRoot, false);
- return new BrightnessSlider(root, mFalsingManager);
+ return new BrightnessSliderController(root, mFalsingManager);
}
/** Get the layout to inflate based on what slider to use */
diff --git a/packages/SystemUI/src/com/android/systemui/settings/brightness/BrightnessSliderView.java b/packages/SystemUI/src/com/android/systemui/settings/brightness/BrightnessSliderView.java
index 15aa2b7..38cb441 100644
--- a/packages/SystemUI/src/com/android/systemui/settings/brightness/BrightnessSliderView.java
+++ b/packages/SystemUI/src/com/android/systemui/settings/brightness/BrightnessSliderView.java
@@ -27,6 +27,7 @@
import android.widget.FrameLayout;
import android.widget.SeekBar.OnSeekBarChangeListener;
+import androidx.annotation.Keep;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
@@ -60,6 +61,7 @@
@Override
protected void onFinishInflate() {
super.onFinishInflate();
+ setLayerType(LAYER_TYPE_HARDWARE, null);
mSlider = requireViewById(R.id.slider);
mSlider.setAccessibilityLabel(getContentDescription().toString());
@@ -183,6 +185,7 @@
*
* Used in {@link com.android.systemui.qs.QSAnimator}.
*/
+ @Keep
public void setSliderScaleY(float scale) {
if (scale != mScale) {
mScale = scale;
@@ -199,6 +202,7 @@
}
}
+ @Keep
public float getSliderScaleY() {
return mScale;
}
diff --git a/packages/SystemUI/src/com/android/systemui/settings/brightness/ToggleSlider.java b/packages/SystemUI/src/com/android/systemui/settings/brightness/ToggleSlider.java
index 5de22d4..648e33b 100644
--- a/packages/SystemUI/src/com/android/systemui/settings/brightness/ToggleSlider.java
+++ b/packages/SystemUI/src/com/android/systemui/settings/brightness/ToggleSlider.java
@@ -38,4 +38,5 @@
void showView();
void hideView();
+ boolean isVisible();
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/CommandQueue.java b/packages/SystemUI/src/com/android/systemui/statusbar/CommandQueue.java
index f95dd34..c25bc84 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/CommandQueue.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/CommandQueue.java
@@ -48,6 +48,7 @@
import android.os.Looper;
import android.os.Message;
import android.os.ParcelFileDescriptor;
+import android.os.RemoteException;
import android.util.Log;
import android.util.Pair;
import android.util.SparseArray;
@@ -152,6 +153,7 @@
private static final int MSG_SET_NAVIGATION_BAR_LUMA_SAMPLING_ENABLED = 59 << MSG_SHIFT;
private static final int MSG_SET_UDFPS_HBM_LISTENER = 60 << MSG_SHIFT;
private static final int MSG_TILE_SERVICE_REQUEST_ADD = 61 << MSG_SHIFT;
+ private static final int MSG_TILE_SERVICE_REQUEST_CANCEL = 62 << MSG_SHIFT;
public static final int FLAG_EXCLUDE_NONE = 0;
public static final int FLAG_EXCLUDE_SEARCH_PANEL = 1 << 0;
@@ -416,6 +418,11 @@
@NonNull CharSequence label,
@NonNull Icon icon,
@NonNull IAddTileResultCallback callback) {}
+
+ /**
+ * @see IStatusBar#cancelRequestAddTile
+ */
+ default void cancelRequestAddTile(@NonNull String packageName) {}
}
public CommandQueue(Context context) {
@@ -1138,6 +1145,11 @@
mHandler.obtainMessage(MSG_TILE_SERVICE_REQUEST_ADD, args).sendToTarget();
}
+ @Override
+ public void cancelRequestAddTile(@NonNull String s) throws RemoteException {
+ mHandler.obtainMessage(MSG_TILE_SERVICE_REQUEST_CANCEL, s).sendToTarget();
+ }
+
private final class H extends Handler {
private H(Looper l) {
super(l);
@@ -1524,6 +1536,11 @@
}
args.recycle();
break;
+ case MSG_TILE_SERVICE_REQUEST_CANCEL:
+ String packageName = (String) msg.obj;
+ for (int i = 0; i < mCallbacks.size(); i++) {
+ mCallbacks.get(i).cancelRequestAddTile(packageName);
+ }
}
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationRemoteInputManager.java b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationRemoteInputManager.java
index 18a3d86..1ce7f03 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationRemoteInputManager.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationRemoteInputManager.java
@@ -15,21 +15,16 @@
*/
package com.android.systemui.statusbar;
-import android.annotation.NonNull;
-import android.annotation.Nullable;
import android.app.ActivityManager;
import android.app.ActivityOptions;
import android.app.KeyguardManager;
import android.app.Notification;
import android.app.PendingIntent;
import android.app.RemoteInput;
-import android.app.RemoteInputHistoryItem;
import android.content.Context;
import android.content.Intent;
import android.content.pm.UserInfo;
-import android.net.Uri;
import android.os.Handler;
-import android.os.Parcelable;
import android.os.RemoteException;
import android.os.ServiceManager;
import android.os.SystemClock;
@@ -48,6 +43,9 @@
import android.widget.RemoteViews.InteractionHandler;
import android.widget.TextView;
+import androidx.annotation.NonNull;
+import androidx.annotation.Nullable;
+
import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.statusbar.IStatusBarService;
import com.android.internal.statusbar.NotificationVisibility;
@@ -55,6 +53,7 @@
import com.android.systemui.R;
import com.android.systemui.dagger.qualifiers.Main;
import com.android.systemui.dump.DumpManager;
+import com.android.systemui.flags.FeatureFlags;
import com.android.systemui.plugins.statusbar.StatusBarStateController;
import com.android.systemui.statusbar.dagger.StatusBarDependenciesModule;
import com.android.systemui.statusbar.notification.NotificationEntryListener;
@@ -70,12 +69,10 @@
import java.io.FileDescriptor;
import java.io.PrintWriter;
import java.util.ArrayList;
-import java.util.Arrays;
import java.util.List;
import java.util.Objects;
import java.util.Optional;
import java.util.Set;
-import java.util.stream.Stream;
import dagger.Lazy;
@@ -93,27 +90,7 @@
private static final boolean DEBUG = false;
private static final String TAG = "NotifRemoteInputManager";
- /**
- * How long to wait before auto-dismissing a notification that was kept for remote input, and
- * has now sent a remote input. We auto-dismiss, because the app may not see a reason to cancel
- * these given that they technically don't exist anymore. We wait a bit in case the app issues
- * an update.
- */
- private static final int REMOTE_INPUT_KEPT_ENTRY_AUTO_CANCEL_DELAY = 200;
-
- /**
- * Notifications that are already removed but are kept around because we want to show the
- * remote input history. See {@link RemoteInputHistoryExtender} and
- * {@link SmartReplyHistoryExtender}.
- */
- protected final ArraySet<String> mKeysKeptForRemoteInputHistory = new ArraySet<>();
-
- /**
- * Notifications that are already removed but are kept around because the remote input is
- * actively being used (i.e. user is typing in it). See {@link RemoteInputActiveExtender}.
- */
- protected final ArraySet<NotificationEntry> mEntriesKeptForRemoteInputActive =
- new ArraySet<>();
+ private RemoteInputListener mRemoteInputListener;
// Dependencies:
private final NotificationLockscreenUserManager mLockscreenUserManager;
@@ -125,18 +102,17 @@
private final Lazy<Optional<StatusBar>> mStatusBarOptionalLazy;
protected final Context mContext;
+ protected final FeatureFlags mFeatureFlags;
private final UserManager mUserManager;
private final KeyguardManager mKeyguardManager;
+ private final RemoteInputNotificationRebuilder mRebuilder;
private final StatusBarStateController mStatusBarStateController;
private final RemoteInputUriController mRemoteInputUriController;
private final NotificationClickNotifier mClickNotifier;
protected RemoteInputController mRemoteInputController;
- protected NotificationLifetimeExtender.NotificationSafeToRemoveCallback
- mNotificationLifetimeFinishedCallback;
protected IStatusBarService mBarService;
protected Callback mCallback;
- protected final ArrayList<NotificationLifetimeExtender> mLifetimeExtenders = new ArrayList<>();
private final List<RemoteInputController.Callback> mControllerCallbacks = new ArrayList<>();
@@ -226,6 +202,7 @@
ViewGroup actionGroup = (ViewGroup) parent;
buttonIndex = actionGroup.indexOfChild(view);
}
+ // TODO(b/204183781): get this from the current pipeline
final int count = mEntryManager.getActiveNotificationsCount();
final int rank = entry.getRanking().getRank();
@@ -283,9 +260,11 @@
*/
public NotificationRemoteInputManager(
Context context,
+ FeatureFlags featureFlags,
NotificationLockscreenUserManager lockscreenUserManager,
SmartReplyController smartReplyController,
NotificationEntryManager notificationEntryManager,
+ RemoteInputNotificationRebuilder rebuilder,
Lazy<Optional<StatusBar>> statusBarOptionalLazy,
StatusBarStateController statusBarStateController,
@Main Handler mainHandler,
@@ -294,6 +273,7 @@
ActionClickLogger logger,
DumpManager dumpManager) {
mContext = context;
+ mFeatureFlags = featureFlags;
mLockscreenUserManager = lockscreenUserManager;
mSmartReplyController = smartReplyController;
mEntryManager = notificationEntryManager;
@@ -303,7 +283,11 @@
mBarService = IStatusBarService.Stub.asInterface(
ServiceManager.getService(Context.STATUS_BAR_SERVICE));
mUserManager = (UserManager) mContext.getSystemService(Context.USER_SERVICE);
- addLifetimeExtenders();
+ mRebuilder = rebuilder;
+ if (!featureFlags.isNewNotifPipelineRenderingEnabled()) {
+ mRemoteInputListener = createLegacyRemoteInputLifetimeExtender(mainHandler,
+ notificationEntryManager, smartReplyController);
+ }
mKeyguardManager = context.getSystemService(KeyguardManager.class);
mStatusBarStateController = statusBarStateController;
mRemoteInputUriController = remoteInputUriController;
@@ -335,10 +319,35 @@
});
}
+ /** Add a listener for various remote input events. Works with NEW pipeline only. */
+ public void setRemoteInputListener(@NonNull RemoteInputListener remoteInputListener) {
+ if (mFeatureFlags.isNewNotifPipelineRenderingEnabled()) {
+ if (mRemoteInputListener != null) {
+ throw new IllegalStateException("mRemoteInputListener is already set");
+ }
+ mRemoteInputListener = remoteInputListener;
+ if (mRemoteInputController != null) {
+ mRemoteInputListener.setRemoteInputController(mRemoteInputController);
+ }
+ }
+ }
+
+ @NonNull
+ @VisibleForTesting
+ protected LegacyRemoteInputLifetimeExtender createLegacyRemoteInputLifetimeExtender(
+ Handler mainHandler,
+ NotificationEntryManager notificationEntryManager,
+ SmartReplyController smartReplyController) {
+ return new LegacyRemoteInputLifetimeExtender();
+ }
+
/** Initializes this component with the provided dependencies. */
public void setUpWithCallback(Callback callback, RemoteInputController.Delegate delegate) {
mCallback = callback;
mRemoteInputController = new RemoteInputController(delegate, mRemoteInputUriController);
+ if (mRemoteInputListener != null) {
+ mRemoteInputListener.setRemoteInputController(mRemoteInputController);
+ }
// Register all stored callbacks from before the Controller was initialized.
for (RemoteInputController.Callback cb : mControllerCallbacks) {
mRemoteInputController.addCallback(cb);
@@ -347,19 +356,8 @@
mRemoteInputController.addCallback(new RemoteInputController.Callback() {
@Override
public void onRemoteInputSent(NotificationEntry entry) {
- if (FORCE_REMOTE_INPUT_HISTORY
- && isNotificationKeptForRemoteInputHistory(entry.getKey())) {
- mNotificationLifetimeFinishedCallback.onSafeToRemove(entry.getKey());
- } else if (mEntriesKeptForRemoteInputActive.contains(entry)) {
- // We're currently holding onto this notification, but from the apps point of
- // view it is already canceled, so we'll need to cancel it on the apps behalf
- // after sending - unless the app posts an update in the mean time, so wait a
- // bit.
- mMainHandler.postDelayed(() -> {
- if (mEntriesKeptForRemoteInputActive.remove(entry)) {
- mNotificationLifetimeFinishedCallback.onSafeToRemove(entry.getKey());
- }
- }, REMOTE_INPUT_KEPT_ENTRY_AUTO_CANCEL_DELAY);
+ if (mRemoteInputListener != null) {
+ mRemoteInputListener.onRemoteInputSent(entry);
}
try {
mBarService.onNotificationDirectReplied(entry.getSbn().getKey());
@@ -381,12 +379,12 @@
}
}
});
- mSmartReplyController.setCallback((entry, reply) -> {
- StatusBarNotification newSbn =
- rebuildNotificationWithRemoteInputInserted(entry, reply, true /* showSpinner */,
- null /* mimeType */, null /* uri */);
- mEntryManager.updateNotification(newSbn, null /* ranking */);
- });
+ if (!mFeatureFlags.isNewNotifPipelineRenderingEnabled()) {
+ mSmartReplyController.setCallback((entry, reply) -> {
+ StatusBarNotification newSbn = mRebuilder.rebuildForSendingSmartReply(entry, reply);
+ mEntryManager.updateNotification(newSbn, null /* ranking */);
+ });
+ }
}
public void addControllerCallback(RemoteInputController.Callback callback) {
@@ -574,51 +572,47 @@
if (v == null) {
return null;
}
- return (RemoteInputView) v.findViewWithTag(RemoteInputView.VIEW_TAG);
- }
-
- /**
- * Adds all the notification lifetime extenders. Each extender represents a reason for the
- * NotificationRemoteInputManager to keep a notification lifetime extended.
- */
- protected void addLifetimeExtenders() {
- mLifetimeExtenders.add(new RemoteInputHistoryExtender());
- mLifetimeExtenders.add(new SmartReplyHistoryExtender());
- mLifetimeExtenders.add(new RemoteInputActiveExtender());
+ return v.findViewWithTag(RemoteInputView.VIEW_TAG);
}
public ArrayList<NotificationLifetimeExtender> getLifetimeExtenders() {
- return mLifetimeExtenders;
+ // OLD pipeline code ONLY; can assume implementation
+ return ((LegacyRemoteInputLifetimeExtender) mRemoteInputListener).mLifetimeExtenders;
}
@VisibleForTesting
void onPerformRemoveNotification(NotificationEntry entry, final String key) {
- if (mKeysKeptForRemoteInputHistory.contains(key)) {
- mKeysKeptForRemoteInputHistory.remove(key);
- }
+ // OLD pipeline code ONLY; can assume implementation
+ ((LegacyRemoteInputLifetimeExtender) mRemoteInputListener)
+ .mKeysKeptForRemoteInputHistory.remove(key);
+ cleanUpRemoteInputForUserRemoval(entry);
+ }
+
+ /**
+ * Disable remote input on the entry and remove the remote input view.
+ * This should be called when a user dismisses a notification that won't be lifetime extended.
+ */
+ public void cleanUpRemoteInputForUserRemoval(NotificationEntry entry) {
if (isRemoteInputActive(entry)) {
entry.mRemoteEditImeVisible = false;
mRemoteInputController.removeRemoteInput(entry, null);
}
}
+ /** Informs the remote input system that the panel has collapsed */
public void onPanelCollapsed() {
- for (int i = 0; i < mEntriesKeptForRemoteInputActive.size(); i++) {
- NotificationEntry entry = mEntriesKeptForRemoteInputActive.valueAt(i);
- if (mRemoteInputController != null) {
- mRemoteInputController.removeRemoteInput(entry, null);
- }
- if (mNotificationLifetimeFinishedCallback != null) {
- mNotificationLifetimeFinishedCallback.onSafeToRemove(entry.getKey());
- }
+ if (mRemoteInputListener != null) {
+ mRemoteInputListener.onPanelCollapsed();
}
- mEntriesKeptForRemoteInputActive.clear();
}
+ /** Returns whether the given notification is lifetime extended because of remote input */
public boolean isNotificationKeptForRemoteInputHistory(String key) {
- return mKeysKeptForRemoteInputHistory.contains(key);
+ return mRemoteInputListener != null
+ && mRemoteInputListener.isNotificationKeptForRemoteInputHistory(key);
}
+ /** Returns whether the notification should be lifetime extended for remote input history */
public boolean shouldKeepForRemoteInputHistory(NotificationEntry entry) {
if (!FORCE_REMOTE_INPUT_HISTORY) {
return false;
@@ -636,16 +630,12 @@
if (entry == null) {
return;
}
- final String key = entry.getKey();
- if (isNotificationKeptForRemoteInputHistory(key)) {
- mMainHandler.postDelayed(() -> {
- if (isNotificationKeptForRemoteInputHistory(key)) {
- mNotificationLifetimeFinishedCallback.onSafeToRemove(key);
- }
- }, REMOTE_INPUT_KEPT_ENTRY_AUTO_CANCEL_DELAY);
+ if (mRemoteInputListener != null) {
+ mRemoteInputListener.releaseNotificationIfKeptForRemoteInputHistory(entry);
}
}
+ /** Returns whether the notification should be lifetime extended for smart reply history */
public boolean shouldKeepForSmartReplyHistory(NotificationEntry entry) {
if (!FORCE_REMOTE_INPUT_HISTORY) {
return false;
@@ -661,64 +651,11 @@
}
}
- @VisibleForTesting
- StatusBarNotification rebuildNotificationForCanceledSmartReplies(
- NotificationEntry entry) {
- return rebuildNotificationWithRemoteInputInserted(entry, null /* remoteInputTest */,
- false /* showSpinner */, null /* mimeType */, null /* uri */);
- }
-
- @VisibleForTesting
- StatusBarNotification rebuildNotificationWithRemoteInputInserted(NotificationEntry entry,
- CharSequence remoteInputText, boolean showSpinner, String mimeType, Uri uri) {
- StatusBarNotification sbn = entry.getSbn();
-
- Notification.Builder b = Notification.Builder
- .recoverBuilder(mContext, sbn.getNotification().clone());
- if (remoteInputText != null || uri != null) {
- RemoteInputHistoryItem newItem = uri != null
- ? new RemoteInputHistoryItem(mimeType, uri, remoteInputText)
- : new RemoteInputHistoryItem(remoteInputText);
- Parcelable[] oldHistoryItems = sbn.getNotification().extras
- .getParcelableArray(Notification.EXTRA_REMOTE_INPUT_HISTORY_ITEMS);
- RemoteInputHistoryItem[] newHistoryItems = oldHistoryItems != null
- ? Stream.concat(
- Stream.of(newItem),
- Arrays.stream(oldHistoryItems).map(p -> (RemoteInputHistoryItem) p))
- .toArray(RemoteInputHistoryItem[]::new)
- : new RemoteInputHistoryItem[] { newItem };
- b.setRemoteInputHistory(newHistoryItems);
- }
- b.setShowRemoteInputSpinner(showSpinner);
- b.setHideSmartReplies(true);
-
- Notification newNotification = b.build();
-
- // Undo any compatibility view inflation
- newNotification.contentView = sbn.getNotification().contentView;
- newNotification.bigContentView = sbn.getNotification().bigContentView;
- newNotification.headsUpContentView = sbn.getNotification().headsUpContentView;
-
- return new StatusBarNotification(
- sbn.getPackageName(),
- sbn.getOpPkg(),
- sbn.getId(),
- sbn.getTag(),
- sbn.getUid(),
- sbn.getInitialPid(),
- newNotification,
- sbn.getUser(),
- sbn.getOverrideGroupKey(),
- sbn.getPostTime());
- }
-
@Override
public void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
- pw.println("NotificationRemoteInputManager state:");
- pw.print(" mKeysKeptForRemoteInputHistory: ");
- pw.println(mKeysKeptForRemoteInputHistory);
- pw.print(" mEntriesKeptForRemoteInputActive: ");
- pw.println(mEntriesKeptForRemoteInputActive);
+ if (mRemoteInputListener instanceof Dumpable) {
+ ((Dumpable) mRemoteInputListener).dump(fd, pw, args);
+ }
}
public void bindRow(ExpandableNotificationRow row) {
@@ -734,11 +671,6 @@
return mInteractionHandler;
}
- @VisibleForTesting
- public Set<NotificationEntry> getEntriesKeptForRemoteInputActive() {
- return mEntriesKeptForRemoteInputActive;
- }
-
public boolean isRemoteInputActive() {
return mRemoteInputController != null && mRemoteInputController.isRemoteInputActive();
}
@@ -758,131 +690,6 @@
}
/**
- * NotificationRemoteInputManager has multiple reasons to keep notification lifetime extended
- * so we implement multiple NotificationLifetimeExtenders
- */
- protected abstract class RemoteInputExtender implements NotificationLifetimeExtender {
- @Override
- public void setCallback(NotificationSafeToRemoveCallback callback) {
- if (mNotificationLifetimeFinishedCallback == null) {
- mNotificationLifetimeFinishedCallback = callback;
- }
- }
- }
-
- /**
- * Notification is kept alive as it was cancelled in response to a remote input interaction.
- * This allows us to show what you replied and allows you to continue typing into it.
- */
- protected class RemoteInputHistoryExtender extends RemoteInputExtender {
- @Override
- public boolean shouldExtendLifetime(@NonNull NotificationEntry entry) {
- return shouldKeepForRemoteInputHistory(entry);
- }
-
- @Override
- public void setShouldManageLifetime(NotificationEntry entry,
- boolean shouldExtend) {
- if (shouldExtend) {
- CharSequence remoteInputText = entry.remoteInputText;
- if (TextUtils.isEmpty(remoteInputText)) {
- remoteInputText = entry.remoteInputTextWhenReset;
- }
- String remoteInputMimeType = entry.remoteInputMimeType;
- Uri remoteInputUri = entry.remoteInputUri;
- StatusBarNotification newSbn = rebuildNotificationWithRemoteInputInserted(entry,
- remoteInputText, false /* showSpinner */, remoteInputMimeType,
- remoteInputUri);
- entry.onRemoteInputInserted();
-
- if (newSbn == null) {
- return;
- }
-
- mEntryManager.updateNotification(newSbn, null);
-
- // Ensure the entry hasn't already been removed. This can happen if there is an
- // inflation exception while updating the remote history
- if (entry.isRemoved()) {
- return;
- }
-
- if (Log.isLoggable(TAG, Log.DEBUG)) {
- Log.d(TAG, "Keeping notification around after sending remote input "
- + entry.getKey());
- }
-
- mKeysKeptForRemoteInputHistory.add(entry.getKey());
- } else {
- mKeysKeptForRemoteInputHistory.remove(entry.getKey());
- }
- }
- }
-
- /**
- * Notification is kept alive for smart reply history. Similar to REMOTE_INPUT_HISTORY but with
- * {@link SmartReplyController} specific logic
- */
- protected class SmartReplyHistoryExtender extends RemoteInputExtender {
- @Override
- public boolean shouldExtendLifetime(@NonNull NotificationEntry entry) {
- return shouldKeepForSmartReplyHistory(entry);
- }
-
- @Override
- public void setShouldManageLifetime(NotificationEntry entry,
- boolean shouldExtend) {
- if (shouldExtend) {
- StatusBarNotification newSbn = rebuildNotificationForCanceledSmartReplies(entry);
-
- if (newSbn == null) {
- return;
- }
-
- mEntryManager.updateNotification(newSbn, null);
-
- if (entry.isRemoved()) {
- return;
- }
-
- if (Log.isLoggable(TAG, Log.DEBUG)) {
- Log.d(TAG, "Keeping notification around after sending smart reply "
- + entry.getKey());
- }
-
- mKeysKeptForRemoteInputHistory.add(entry.getKey());
- } else {
- mKeysKeptForRemoteInputHistory.remove(entry.getKey());
- mSmartReplyController.stopSending(entry);
- }
- }
- }
-
- /**
- * Notification is kept alive because the user is still using the remote input
- */
- protected class RemoteInputActiveExtender extends RemoteInputExtender {
- @Override
- public boolean shouldExtendLifetime(@NonNull NotificationEntry entry) {
- return isRemoteInputActive(entry);
- }
-
- @Override
- public void setShouldManageLifetime(NotificationEntry entry,
- boolean shouldExtend) {
- if (shouldExtend) {
- if (Log.isLoggable(TAG, Log.DEBUG)) {
- Log.d(TAG, "Keeping notification around while remote input active "
- + entry.getKey());
- }
- mEntriesKeptForRemoteInputActive.add(entry);
- } else {
- mEntriesKeptForRemoteInputActive.remove(entry);
- }
- }
- }
-
- /**
* Callback for various remote input related events, or for providing information that
* NotificationRemoteInputManager needs to know to decide what to do.
*/
@@ -975,4 +782,256 @@
*/
boolean showBouncerIfNecessary();
}
+
+ /** An interface for listening to remote input events that relate to notification lifetime */
+ public interface RemoteInputListener {
+ /** Called when remote input pending intent has been sent */
+ void onRemoteInputSent(@NonNull NotificationEntry entry);
+
+ /** Called when the notification shade becomes fully closed */
+ void onPanelCollapsed();
+
+ /** @return whether lifetime of a notification is being extended by the listener */
+ boolean isNotificationKeptForRemoteInputHistory(@NonNull String key);
+
+ /** Called on user interaction to end lifetime extension for history */
+ void releaseNotificationIfKeptForRemoteInputHistory(@NonNull NotificationEntry entry);
+
+ /** Called when the RemoteInputController is attached to the manager */
+ void setRemoteInputController(@NonNull RemoteInputController remoteInputController);
+ }
+
+ @VisibleForTesting
+ protected class LegacyRemoteInputLifetimeExtender implements RemoteInputListener, Dumpable {
+
+ /**
+ * How long to wait before auto-dismissing a notification that was kept for remote input,
+ * and has now sent a remote input. We auto-dismiss, because the app may not see a reason to
+ * cancel these given that they technically don't exist anymore. We wait a bit in case the
+ * app issues an update.
+ */
+ private static final int REMOTE_INPUT_KEPT_ENTRY_AUTO_CANCEL_DELAY = 200;
+
+ /**
+ * Notifications that are already removed but are kept around because we want to show the
+ * remote input history. See {@link RemoteInputHistoryExtender} and
+ * {@link SmartReplyHistoryExtender}.
+ */
+ protected final ArraySet<String> mKeysKeptForRemoteInputHistory = new ArraySet<>();
+
+ /**
+ * Notifications that are already removed but are kept around because the remote input is
+ * actively being used (i.e. user is typing in it). See {@link RemoteInputActiveExtender}.
+ */
+ protected final ArraySet<NotificationEntry> mEntriesKeptForRemoteInputActive =
+ new ArraySet<>();
+
+ protected NotificationLifetimeExtender.NotificationSafeToRemoveCallback
+ mNotificationLifetimeFinishedCallback;
+
+ protected final ArrayList<NotificationLifetimeExtender> mLifetimeExtenders =
+ new ArrayList<>();
+ private RemoteInputController mRemoteInputController;
+
+ LegacyRemoteInputLifetimeExtender() {
+ addLifetimeExtenders();
+ }
+
+ /**
+ * Adds all the notification lifetime extenders. Each extender represents a reason for the
+ * NotificationRemoteInputManager to keep a notification lifetime extended.
+ */
+ protected void addLifetimeExtenders() {
+ mLifetimeExtenders.add(new RemoteInputHistoryExtender());
+ mLifetimeExtenders.add(new SmartReplyHistoryExtender());
+ mLifetimeExtenders.add(new RemoteInputActiveExtender());
+ }
+
+ @Override
+ public void setRemoteInputController(@NonNull RemoteInputController remoteInputController) {
+ mRemoteInputController= remoteInputController;
+ }
+
+ @Override
+ public void onRemoteInputSent(@NonNull NotificationEntry entry) {
+ if (FORCE_REMOTE_INPUT_HISTORY
+ && isNotificationKeptForRemoteInputHistory(entry.getKey())) {
+ mNotificationLifetimeFinishedCallback.onSafeToRemove(entry.getKey());
+ } else if (mEntriesKeptForRemoteInputActive.contains(entry)) {
+ // We're currently holding onto this notification, but from the apps point of
+ // view it is already canceled, so we'll need to cancel it on the apps behalf
+ // after sending - unless the app posts an update in the mean time, so wait a
+ // bit.
+ mMainHandler.postDelayed(() -> {
+ if (mEntriesKeptForRemoteInputActive.remove(entry)) {
+ mNotificationLifetimeFinishedCallback.onSafeToRemove(entry.getKey());
+ }
+ }, REMOTE_INPUT_KEPT_ENTRY_AUTO_CANCEL_DELAY);
+ }
+ }
+
+ @Override
+ public void onPanelCollapsed() {
+ for (int i = 0; i < mEntriesKeptForRemoteInputActive.size(); i++) {
+ NotificationEntry entry = mEntriesKeptForRemoteInputActive.valueAt(i);
+ if (mRemoteInputController != null) {
+ mRemoteInputController.removeRemoteInput(entry, null);
+ }
+ if (mNotificationLifetimeFinishedCallback != null) {
+ mNotificationLifetimeFinishedCallback.onSafeToRemove(entry.getKey());
+ }
+ }
+ mEntriesKeptForRemoteInputActive.clear();
+ }
+
+ @Override
+ public boolean isNotificationKeptForRemoteInputHistory(@NonNull String key) {
+ return mKeysKeptForRemoteInputHistory.contains(key);
+ }
+
+ @Override
+ public void releaseNotificationIfKeptForRemoteInputHistory(
+ @NonNull NotificationEntry entry) {
+ final String key = entry.getKey();
+ if (isNotificationKeptForRemoteInputHistory(key)) {
+ mMainHandler.postDelayed(() -> {
+ if (isNotificationKeptForRemoteInputHistory(key)) {
+ mNotificationLifetimeFinishedCallback.onSafeToRemove(key);
+ }
+ }, REMOTE_INPUT_KEPT_ENTRY_AUTO_CANCEL_DELAY);
+ }
+ }
+
+ @VisibleForTesting
+ public Set<NotificationEntry> getEntriesKeptForRemoteInputActive() {
+ return mEntriesKeptForRemoteInputActive;
+ }
+
+ @Override
+ public void dump(@NonNull FileDescriptor fd, @NonNull PrintWriter pw,
+ @NonNull String[] args) {
+ pw.println("LegacyRemoteInputLifetimeExtender:");
+ pw.print(" mKeysKeptForRemoteInputHistory: ");
+ pw.println(mKeysKeptForRemoteInputHistory);
+ pw.print(" mEntriesKeptForRemoteInputActive: ");
+ pw.println(mEntriesKeptForRemoteInputActive);
+ }
+
+ /**
+ * NotificationRemoteInputManager has multiple reasons to keep notification lifetime
+ * extended so we implement multiple NotificationLifetimeExtenders
+ */
+ protected abstract class RemoteInputExtender implements NotificationLifetimeExtender {
+ @Override
+ public void setCallback(NotificationSafeToRemoveCallback callback) {
+ if (mNotificationLifetimeFinishedCallback == null) {
+ mNotificationLifetimeFinishedCallback = callback;
+ }
+ }
+ }
+
+ /**
+ * Notification is kept alive as it was cancelled in response to a remote input interaction.
+ * This allows us to show what you replied and allows you to continue typing into it.
+ */
+ protected class RemoteInputHistoryExtender extends RemoteInputExtender {
+ @Override
+ public boolean shouldExtendLifetime(@NonNull NotificationEntry entry) {
+ return shouldKeepForRemoteInputHistory(entry);
+ }
+
+ @Override
+ public void setShouldManageLifetime(NotificationEntry entry,
+ boolean shouldExtend) {
+ if (shouldExtend) {
+ StatusBarNotification newSbn = mRebuilder.rebuildForRemoteInputReply(entry);
+ entry.onRemoteInputInserted();
+
+ if (newSbn == null) {
+ return;
+ }
+
+ mEntryManager.updateNotification(newSbn, null);
+
+ // Ensure the entry hasn't already been removed. This can happen if there is an
+ // inflation exception while updating the remote history
+ if (entry.isRemoved()) {
+ return;
+ }
+
+ if (Log.isLoggable(TAG, Log.DEBUG)) {
+ Log.d(TAG, "Keeping notification around after sending remote input "
+ + entry.getKey());
+ }
+
+ mKeysKeptForRemoteInputHistory.add(entry.getKey());
+ } else {
+ mKeysKeptForRemoteInputHistory.remove(entry.getKey());
+ }
+ }
+ }
+
+ /**
+ * Notification is kept alive for smart reply history. Similar to REMOTE_INPUT_HISTORY but
+ * with {@link SmartReplyController} specific logic
+ */
+ protected class SmartReplyHistoryExtender extends RemoteInputExtender {
+ @Override
+ public boolean shouldExtendLifetime(@NonNull NotificationEntry entry) {
+ return shouldKeepForSmartReplyHistory(entry);
+ }
+
+ @Override
+ public void setShouldManageLifetime(NotificationEntry entry,
+ boolean shouldExtend) {
+ if (shouldExtend) {
+ StatusBarNotification newSbn = mRebuilder.rebuildForCanceledSmartReplies(entry);
+
+ if (newSbn == null) {
+ return;
+ }
+
+ mEntryManager.updateNotification(newSbn, null);
+
+ if (entry.isRemoved()) {
+ return;
+ }
+
+ if (Log.isLoggable(TAG, Log.DEBUG)) {
+ Log.d(TAG, "Keeping notification around after sending smart reply "
+ + entry.getKey());
+ }
+
+ mKeysKeptForRemoteInputHistory.add(entry.getKey());
+ } else {
+ mKeysKeptForRemoteInputHistory.remove(entry.getKey());
+ mSmartReplyController.stopSending(entry);
+ }
+ }
+ }
+
+ /**
+ * Notification is kept alive because the user is still using the remote input
+ */
+ protected class RemoteInputActiveExtender extends RemoteInputExtender {
+ @Override
+ public boolean shouldExtendLifetime(@NonNull NotificationEntry entry) {
+ return isRemoteInputActive(entry);
+ }
+
+ @Override
+ public void setShouldManageLifetime(NotificationEntry entry,
+ boolean shouldExtend) {
+ if (shouldExtend) {
+ if (Log.isLoggable(TAG, Log.DEBUG)) {
+ Log.d(TAG, "Keeping notification around while remote input active "
+ + entry.getKey());
+ }
+ mEntriesKeptForRemoteInputActive.add(entry);
+ } else {
+ mEntriesKeptForRemoteInputActive.remove(entry);
+ }
+ }
+ }
+ }
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationShelf.java b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationShelf.java
index 0b93fff..51a66aa 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationShelf.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationShelf.java
@@ -30,6 +30,7 @@
import android.view.animation.PathInterpolator;
import com.android.internal.annotations.VisibleForTesting;
+import com.android.internal.policy.SystemBarUtils;
import com.android.systemui.R;
import com.android.systemui.animation.ShadeInterpolation;
import com.android.systemui.plugins.statusbar.StatusBarStateController.StateListener;
@@ -114,7 +115,7 @@
private void initDimens() {
Resources res = getResources();
- mStatusBarHeight = res.getDimensionPixelOffset(R.dimen.status_bar_height);
+ mStatusBarHeight = SystemBarUtils.getStatusBarHeight(mContext);
mPaddingBetweenElements = res.getDimensionPixelSize(R.dimen.notification_divider_height);
ViewGroup.LayoutParams layoutParams = getLayoutParams();
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationViewHierarchyManager.java b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationViewHierarchyManager.java
index 396d86b..be3364b 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationViewHierarchyManager.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationViewHierarchyManager.java
@@ -27,6 +27,7 @@
import com.android.systemui.R;
import com.android.systemui.dagger.qualifiers.Main;
+import com.android.systemui.flags.FeatureFlags;
import com.android.systemui.plugins.statusbar.StatusBarStateController;
import com.android.systemui.statusbar.dagger.StatusBarModule;
import com.android.systemui.statusbar.notification.AssistantFeedbackController;
@@ -72,6 +73,7 @@
// Dependencies:
private final DynamicChildBindController mDynamicChildBindController;
+ private final FeatureFlags mFeatureFlags;
protected final NotificationLockscreenUserManager mLockscreenUserManager;
protected final NotificationGroupManagerLegacy mGroupManager;
protected final VisualStabilityManager mVisualStabilityManager;
@@ -107,6 +109,7 @@
public NotificationViewHierarchyManager(
Context context,
@Main Handler mainHandler,
+ FeatureFlags featureFlags,
NotificationLockscreenUserManager notificationLockscreenUserManager,
NotificationGroupManagerLegacy groupManager,
VisualStabilityManager visualStabilityManager,
@@ -121,6 +124,7 @@
AssistantFeedbackController assistantFeedbackController) {
mContext = context;
mHandler = mainHandler;
+ mFeatureFlags = featureFlags;
mLockscreenUserManager = notificationLockscreenUserManager;
mBypassController = bypassController;
mGroupManager = groupManager;
@@ -151,6 +155,10 @@
//TODO: Rewrite this to focus on Entries, or some other data object instead of views
public void updateNotificationViews() {
Assert.isMainThread();
+ if (!mFeatureFlags.checkLegacyPipelineEnabled()) {
+ return;
+ }
+
beginUpdate();
List<NotificationEntry> activeNotifications = mEntryManager.getVisibleNotifications();
@@ -425,6 +433,10 @@
*/
public void updateRowStates() {
Assert.isMainThread();
+ if (!mFeatureFlags.checkLegacyPipelineEnabled()) {
+ return;
+ }
+
beginUpdate();
updateRowStatesInternal();
endUpdate();
@@ -510,6 +522,9 @@
@Override
public void onDynamicPrivacyChanged() {
+ if (!mFeatureFlags.checkLegacyPipelineEnabled()) {
+ return;
+ }
if (mPerformingUpdate) {
Log.w(TAG, "onDynamicPrivacyChanged made a re-entrant call");
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/RemoteInputController.java b/packages/SystemUI/src/com/android/systemui/statusbar/RemoteInputController.java
index 83701a0..cde3b0e 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/RemoteInputController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/RemoteInputController.java
@@ -299,6 +299,9 @@
default void onRemoteInputSent(NotificationEntry entry) {}
}
+ /**
+ * This is a delegate which implements some view controller pieces of the remote input process
+ */
public interface Delegate {
/**
* Activate remote input if necessary.
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/RemoteInputNotificationRebuilder.java b/packages/SystemUI/src/com/android/systemui/statusbar/RemoteInputNotificationRebuilder.java
new file mode 100644
index 0000000..90abec1
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/RemoteInputNotificationRebuilder.java
@@ -0,0 +1,141 @@
+/*
+ * Copyright (C) 2021 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;
+
+import android.annotation.NonNull;
+import android.app.Notification;
+import android.app.RemoteInputHistoryItem;
+import android.content.Context;
+import android.net.Uri;
+import android.os.Parcelable;
+import android.service.notification.StatusBarNotification;
+import android.text.TextUtils;
+
+import com.android.internal.annotations.VisibleForTesting;
+import com.android.systemui.dagger.SysUISingleton;
+import com.android.systemui.statusbar.notification.collection.NotificationEntry;
+
+import java.util.Arrays;
+import java.util.stream.Stream;
+
+import javax.inject.Inject;
+
+/**
+ * A helper class which will augment the notifications using arguments and other information
+ * accessible to the entry in order to provide intermediate remote input states.
+ */
+@SysUISingleton
+public class RemoteInputNotificationRebuilder {
+
+ private final Context mContext;
+
+ @Inject
+ RemoteInputNotificationRebuilder(Context context) {
+ mContext = context;
+ }
+
+ /**
+ * When a smart reply is sent off to the app, we insert the text into the remote input history,
+ * and show a spinner to indicate that the app has yet to respond.
+ */
+ @NonNull
+ public StatusBarNotification rebuildForSendingSmartReply(NotificationEntry entry,
+ CharSequence reply) {
+ return rebuildWithRemoteInputInserted(entry, reply,
+ true /* showSpinner */,
+ null /* mimeType */, null /* uri */);
+ }
+
+ /**
+ * When the app cancels a notification in response to a smart reply, we remove the spinner
+ * and leave the previously-added reply. This is the lifetime-extended appearance of the
+ * notification.
+ */
+ @NonNull
+ public StatusBarNotification rebuildForCanceledSmartReplies(
+ NotificationEntry entry) {
+ return rebuildWithRemoteInputInserted(entry, null /* remoteInputTest */,
+ false /* showSpinner */, null /* mimeType */, null /* uri */);
+ }
+
+ /**
+ * When the app cancels a notification in response to a remote input reply, we update the
+ * notification with the reply text and/or attachment. This is the lifetime-extended
+ * appearance of the notification.
+ */
+ @NonNull
+ public StatusBarNotification rebuildForRemoteInputReply(NotificationEntry entry) {
+ CharSequence remoteInputText = entry.remoteInputText;
+ if (TextUtils.isEmpty(remoteInputText)) {
+ remoteInputText = entry.remoteInputTextWhenReset;
+ }
+ String remoteInputMimeType = entry.remoteInputMimeType;
+ Uri remoteInputUri = entry.remoteInputUri;
+ StatusBarNotification newSbn = rebuildWithRemoteInputInserted(entry,
+ remoteInputText, false /* showSpinner */, remoteInputMimeType,
+ remoteInputUri);
+ return newSbn;
+ }
+
+ /** Inner method for generating the SBN */
+ @VisibleForTesting
+ @NonNull
+ StatusBarNotification rebuildWithRemoteInputInserted(NotificationEntry entry,
+ CharSequence remoteInputText, boolean showSpinner, String mimeType, Uri uri) {
+ StatusBarNotification sbn = entry.getSbn();
+
+ Notification.Builder b = Notification.Builder
+ .recoverBuilder(mContext, sbn.getNotification().clone());
+ if (remoteInputText != null || uri != null) {
+ RemoteInputHistoryItem newItem = uri != null
+ ? new RemoteInputHistoryItem(mimeType, uri, remoteInputText)
+ : new RemoteInputHistoryItem(remoteInputText);
+ Parcelable[] oldHistoryItems = sbn.getNotification().extras
+ .getParcelableArray(Notification.EXTRA_REMOTE_INPUT_HISTORY_ITEMS);
+ RemoteInputHistoryItem[] newHistoryItems = oldHistoryItems != null
+ ? Stream.concat(
+ Stream.of(newItem),
+ Arrays.stream(oldHistoryItems).map(p -> (RemoteInputHistoryItem) p))
+ .toArray(RemoteInputHistoryItem[]::new)
+ : new RemoteInputHistoryItem[] { newItem };
+ b.setRemoteInputHistory(newHistoryItems);
+ }
+ b.setShowRemoteInputSpinner(showSpinner);
+ b.setHideSmartReplies(true);
+
+ Notification newNotification = b.build();
+
+ // Undo any compatibility view inflation
+ newNotification.contentView = sbn.getNotification().contentView;
+ newNotification.bigContentView = sbn.getNotification().bigContentView;
+ newNotification.headsUpContentView = sbn.getNotification().headsUpContentView;
+
+ return new StatusBarNotification(
+ sbn.getPackageName(),
+ sbn.getOpPkg(),
+ sbn.getId(),
+ sbn.getTag(),
+ sbn.getUid(),
+ sbn.getInitialPid(),
+ newNotification,
+ sbn.getUser(),
+ sbn.getOverrideGroupKey(),
+ sbn.getPostTime());
+ }
+
+
+}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/SmartReplyController.java b/packages/SystemUI/src/com/android/systemui/statusbar/SmartReplyController.java
index 7fc18b7..e288b1530 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/SmartReplyController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/SmartReplyController.java
@@ -19,35 +19,44 @@
import android.os.RemoteException;
import android.util.ArraySet;
+import androidx.annotation.NonNull;
+
import com.android.internal.statusbar.IStatusBarService;
import com.android.internal.statusbar.NotificationVisibility;
+import com.android.systemui.Dumpable;
+import com.android.systemui.dump.DumpManager;
import com.android.systemui.statusbar.dagger.StatusBarModule;
import com.android.systemui.statusbar.notification.NotificationEntryManager;
import com.android.systemui.statusbar.notification.collection.NotificationEntry;
import com.android.systemui.statusbar.notification.logging.NotificationLogger;
+import java.io.FileDescriptor;
+import java.io.PrintWriter;
import java.util.Set;
/**
* Handles when smart replies are added to a notification
* and clicked upon.
*/
-public class SmartReplyController {
+public class SmartReplyController implements Dumpable {
private final IStatusBarService mBarService;
private final NotificationEntryManager mEntryManager;
private final NotificationClickNotifier mClickNotifier;
- private Set<String> mSendingKeys = new ArraySet<>();
+ private final Set<String> mSendingKeys = new ArraySet<>();
private Callback mCallback;
/**
* Injected constructor. See {@link StatusBarModule}.
*/
- public SmartReplyController(NotificationEntryManager entryManager,
+ public SmartReplyController(
+ DumpManager dumpManager,
+ NotificationEntryManager entryManager,
IStatusBarService statusBarService,
NotificationClickNotifier clickNotifier) {
mBarService = statusBarService;
mEntryManager = entryManager;
mClickNotifier = clickNotifier;
+ dumpManager.registerDumpable(this);
}
public void setCallback(Callback callback) {
@@ -75,6 +84,7 @@
public void smartActionClicked(
NotificationEntry entry, int actionIndex, Notification.Action action,
boolean generatedByAssistant) {
+ // TODO(b/204183781): get this from the current pipeline
final int count = mEntryManager.getActiveNotificationsCount();
final int rank = entry.getRanking().getRank();
NotificationVisibility.NotificationLocation location =
@@ -112,6 +122,14 @@
}
}
+ @Override
+ public void dump(@NonNull FileDescriptor fd, @NonNull PrintWriter pw, @NonNull String[] args) {
+ pw.println("mSendingKeys: " + mSendingKeys.size());
+ for (String key : mSendingKeys) {
+ pw.println(" * " + key);
+ }
+ }
+
/**
* Callback for any class that needs to do something in response to a smart reply being sent.
*/
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/StatusBarStateControllerImpl.java b/packages/SystemUI/src/com/android/systemui/statusbar/StatusBarStateControllerImpl.java
index 6da981b..cbb3aba 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/StatusBarStateControllerImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/StatusBarStateControllerImpl.java
@@ -28,7 +28,6 @@
import android.animation.ObjectAnimator;
import android.animation.ValueAnimator;
import android.os.SystemProperties;
-import android.os.Trace;
import android.text.format.DateFormat;
import android.util.FloatProperty;
import android.util.Log;
@@ -182,7 +181,6 @@
}
synchronized (mListeners) {
- Trace.beginSection(TAG + "#setState(" + StatusBarState.toShortString(state) + ")");
String tag = getClass().getSimpleName() + "#setState(" + state + ")";
DejankUtils.startDetectingBlockingIpcs(tag);
for (RankedListener rl : new ArrayList<>(mListeners)) {
@@ -200,7 +198,6 @@
rl.mListener.onStatePostChange();
}
DejankUtils.stopDetectingBlockingIpcs(tag);
- Trace.endSection();
}
return true;
@@ -265,14 +262,12 @@
mIsDozing = isDozing;
synchronized (mListeners) {
- Trace.beginSection(TAG + "#setDozing(" + isDozing + ")");
String tag = getClass().getSimpleName() + "#setIsDozing";
DejankUtils.startDetectingBlockingIpcs(tag);
for (RankedListener rl : new ArrayList<>(mListeners)) {
rl.mListener.onDozingChanged(isDozing);
}
DejankUtils.stopDetectingBlockingIpcs(tag);
- Trace.endSection();
}
return true;
@@ -338,14 +333,12 @@
mDozeAmount = dozeAmount;
float interpolatedAmount = mDozeInterpolator.getInterpolation(dozeAmount);
synchronized (mListeners) {
- Trace.beginSection(TAG + "#setDozeAmount");
String tag = getClass().getSimpleName() + "#setDozeAmount";
DejankUtils.startDetectingBlockingIpcs(tag);
for (RankedListener rl : new ArrayList<>(mListeners)) {
rl.mListener.onDozeAmountChanged(mDozeAmount, interpolatedAmount);
}
DejankUtils.stopDetectingBlockingIpcs(tag);
- Trace.endSection();
}
}
@@ -476,13 +469,11 @@
public void setPulsing(boolean pulsing) {
if (mPulsing != pulsing) {
mPulsing = pulsing;
- Trace.beginSection(TAG + "#setPulsing(" + pulsing + ")");
synchronized (mListeners) {
for (RankedListener rl : new ArrayList<>(mListeners)) {
rl.mListener.onPulsingChanged(pulsing);
}
}
- Trace.endSection();
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/connectivity/NetworkControllerImpl.java b/packages/SystemUI/src/com/android/systemui/statusbar/connectivity/NetworkControllerImpl.java
index 23ad4ea..a4a648e 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/connectivity/NetworkControllerImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/connectivity/NetworkControllerImpl.java
@@ -811,7 +811,8 @@
break;
case Settings.Panel.ACTION_INTERNET_CONNECTIVITY:
mMainHandler.post(() -> mInternetDialogFactory.create(true,
- mAccessPoints.canConfigMobileData(), mAccessPoints.canConfigWifi()));
+ mAccessPoints.canConfigMobileData(), mAccessPoints.canConfigWifi(),
+ null /* view */));
break;
default:
int subId = intent.getIntExtra(SubscriptionManager.EXTRA_SUBSCRIPTION_INDEX,
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/dagger/StatusBarDependenciesModule.java b/packages/SystemUI/src/com/android/systemui/statusbar/dagger/StatusBarDependenciesModule.java
index d297d95..bb697c3 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/dagger/StatusBarDependenciesModule.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/dagger/StatusBarDependenciesModule.java
@@ -43,6 +43,7 @@
import com.android.systemui.statusbar.NotificationRemoteInputManager;
import com.android.systemui.statusbar.NotificationShadeWindowController;
import com.android.systemui.statusbar.NotificationViewHierarchyManager;
+import com.android.systemui.statusbar.RemoteInputNotificationRebuilder;
import com.android.systemui.statusbar.SmartReplyController;
import com.android.systemui.statusbar.StatusBarStateControllerImpl;
import com.android.systemui.statusbar.SysuiStatusBarStateController;
@@ -96,9 +97,11 @@
@Provides
static NotificationRemoteInputManager provideNotificationRemoteInputManager(
Context context,
+ FeatureFlags featureFlags,
NotificationLockscreenUserManager lockscreenUserManager,
SmartReplyController smartReplyController,
NotificationEntryManager notificationEntryManager,
+ RemoteInputNotificationRebuilder rebuilder,
Lazy<Optional<StatusBar>> statusBarOptionalLazy,
StatusBarStateController statusBarStateController,
Handler mainHandler,
@@ -108,9 +111,11 @@
DumpManager dumpManager) {
return new NotificationRemoteInputManager(
context,
+ featureFlags,
lockscreenUserManager,
smartReplyController,
notificationEntryManager,
+ rebuilder,
statusBarOptionalLazy,
statusBarStateController,
mainHandler,
@@ -166,10 +171,11 @@
@SysUISingleton
@Provides
static SmartReplyController provideSmartReplyController(
+ DumpManager dumpManager,
NotificationEntryManager entryManager,
IStatusBarService statusBarService,
NotificationClickNotifier clickNotifier) {
- return new SmartReplyController(entryManager, statusBarService, clickNotifier);
+ return new SmartReplyController(dumpManager, entryManager, statusBarService, clickNotifier);
}
@@ -184,6 +190,7 @@
static NotificationViewHierarchyManager provideNotificationViewHierarchyManager(
Context context,
@Main Handler mainHandler,
+ FeatureFlags featureFlags,
NotificationLockscreenUserManager notificationLockscreenUserManager,
NotificationGroupManagerLegacy groupManager,
VisualStabilityManager visualStabilityManager,
@@ -199,6 +206,7 @@
return new NotificationViewHierarchyManager(
context,
mainHandler,
+ featureFlags,
notificationLockscreenUserManager,
groupManager,
visualStabilityManager,
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/lockscreen/LockscreenSmartspaceController.kt b/packages/SystemUI/src/com/android/systemui/statusbar/lockscreen/LockscreenSmartspaceController.kt
index bacb85a..4e5bc8e 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/lockscreen/LockscreenSmartspaceController.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/lockscreen/LockscreenSmartspaceController.kt
@@ -188,13 +188,23 @@
val ssView = plugin.getView(parent)
ssView.registerDataProvider(plugin)
+
ssView.setIntentStarter(object : BcSmartspaceDataPlugin.IntentStarter {
- override fun startIntent(v: View?, i: Intent?) {
- activityStarter.startActivity(i, true /* dismissShade */)
+ override fun startIntent(view: View, intent: Intent, showOnLockscreen: Boolean) {
+ activityStarter.startActivity(
+ intent,
+ true, /* dismissShade */
+ null, /* launch animator - looks bad with the transparent smartspace bg */
+ showOnLockscreen
+ )
}
- override fun startPendingIntent(pi: PendingIntent?) {
- activityStarter.startPendingIntentDismissingKeyguard(pi)
+ override fun startPendingIntent(pi: PendingIntent, showOnLockscreen: Boolean) {
+ if (showOnLockscreen) {
+ pi.send()
+ } else {
+ activityStarter.startPendingIntentDismissingKeyguard(pi)
+ }
}
})
ssView.setFalsingManager(falsingManager)
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationEntryManager.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationEntryManager.java
index 60f44a0d..8bc41c2 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationEntryManager.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationEntryManager.java
@@ -689,8 +689,9 @@
for (NotificationEntryListener listener : mNotificationEntryListeners) {
listener.onPreEntryUpdated(entry);
}
+ final boolean fromSystem = ranking != null;
for (NotifCollectionListener listener : mNotifCollectionListeners) {
- listener.onEntryUpdated(entry);
+ listener.onEntryUpdated(entry, fromSystem);
}
if (!mFeatureFlags.isNewNotifPipelineRenderingEnabled()) {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/NotifCollection.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/NotifCollection.java
index dfdc548..4440c3b 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/NotifCollection.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/NotifCollection.java
@@ -47,6 +47,7 @@
import android.annotation.Nullable;
import android.annotation.UserIdInt;
import android.app.Notification;
+import android.os.Handler;
import android.os.RemoteException;
import android.os.UserHandle;
import android.service.notification.NotificationListenerService;
@@ -61,6 +62,7 @@
import com.android.internal.statusbar.IStatusBarService;
import com.android.systemui.Dumpable;
import com.android.systemui.dagger.SysUISingleton;
+import com.android.systemui.dagger.qualifiers.Main;
import com.android.systemui.dump.DumpManager;
import com.android.systemui.dump.LogBufferEulogizer;
import com.android.systemui.flags.FeatureFlags;
@@ -75,6 +77,7 @@
import com.android.systemui.statusbar.notification.collection.notifcollection.EntryRemovedEvent;
import com.android.systemui.statusbar.notification.collection.notifcollection.EntryUpdatedEvent;
import com.android.systemui.statusbar.notification.collection.notifcollection.InitEntryEvent;
+import com.android.systemui.statusbar.notification.collection.notifcollection.InternalNotifUpdater;
import com.android.systemui.statusbar.notification.collection.notifcollection.NotifCollectionListener;
import com.android.systemui.statusbar.notification.collection.notifcollection.NotifCollectionLogger;
import com.android.systemui.statusbar.notification.collection.notifcollection.NotifDismissInterceptor;
@@ -130,6 +133,7 @@
private final SystemClock mClock;
private final FeatureFlags mFeatureFlags;
private final NotifCollectionLogger mLogger;
+ private final Handler mMainHandler;
private final LogBufferEulogizer mEulogizer;
private final Map<String, NotificationEntry> mNotificationSet = new ArrayMap<>();
@@ -153,6 +157,7 @@
SystemClock clock,
FeatureFlags featureFlags,
NotifCollectionLogger logger,
+ @Main Handler mainHandler,
LogBufferEulogizer logBufferEulogizer,
DumpManager dumpManager) {
Assert.isMainThread();
@@ -160,6 +165,7 @@
mClock = clock;
mFeatureFlags = featureFlags;
mLogger = logger;
+ mMainHandler = mainHandler;
mEulogizer = logBufferEulogizer;
dumpManager.registerDumpable(TAG, this);
@@ -441,7 +447,7 @@
mEventQueue.add(new BindEntryEvent(entry, sbn));
mLogger.logNotifUpdated(sbn.getKey());
- mEventQueue.add(new EntryUpdatedEvent(entry));
+ mEventQueue.add(new EntryUpdatedEvent(entry, true /* fromSystem */));
}
}
@@ -788,6 +794,51 @@
private static final String TAG = "NotifCollection";
+ /**
+ * Get an object which can be used to update a notification (internally to the pipeline)
+ * in response to a user action.
+ *
+ * @param name the name of the component that will update notifiations
+ * @return an updater
+ */
+ public InternalNotifUpdater getInternalNotifUpdater(String name) {
+ return (sbn, reason) -> mMainHandler.post(
+ () -> updateNotificationInternally(sbn, name, reason));
+ }
+
+ /**
+ * Provide an updated StatusBarNotification for an existing entry. If no entry exists for the
+ * given notification key, this method does nothing.
+ *
+ * @param sbn the updated notification
+ * @param name the component which is updating the notification
+ * @param reason the reason the notification is being updated
+ */
+ private void updateNotificationInternally(StatusBarNotification sbn, String name,
+ String reason) {
+ Assert.isMainThread();
+ checkForReentrantCall();
+
+ // Make sure we have the notification to update
+ NotificationEntry entry = mNotificationSet.get(sbn.getKey());
+ if (entry == null) {
+ mLogger.logNotifInternalUpdateFailed(sbn.getKey(), name, reason);
+ return;
+ }
+ mLogger.logNotifInternalUpdate(sbn.getKey(), name, reason);
+
+ // First do the pieces of postNotification which are not about assuming the notification
+ // was sent by the app
+ entry.setSbn(sbn);
+ mEventQueue.add(new BindEntryEvent(entry, sbn));
+
+ mLogger.logNotifUpdated(sbn.getKey());
+ mEventQueue.add(new EntryUpdatedEvent(entry, false /* fromSystem */));
+
+ // Skip the applyRanking step and go straight to dispatching the events
+ dispatchEventsAndRebuildList();
+ }
+
@IntDef(prefix = { "REASON_" }, value = {
REASON_NOT_CANCELED,
REASON_UNKNOWN,
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/NotifPipeline.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/NotifPipeline.java
index 47939f0..27ba4c2 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/NotifPipeline.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/NotifPipeline.java
@@ -16,6 +16,8 @@
package com.android.systemui.statusbar.notification.collection;
+import android.os.Handler;
+
import androidx.annotation.Nullable;
import com.android.systemui.dagger.SysUISingleton;
@@ -23,12 +25,14 @@
import com.android.systemui.statusbar.notification.collection.listbuilder.OnBeforeRenderListListener;
import com.android.systemui.statusbar.notification.collection.listbuilder.OnBeforeSortListener;
import com.android.systemui.statusbar.notification.collection.listbuilder.OnBeforeTransformGroupsListener;
+import com.android.systemui.statusbar.notification.collection.listbuilder.pluggable.Invalidator;
import com.android.systemui.statusbar.notification.collection.listbuilder.pluggable.NotifComparator;
import com.android.systemui.statusbar.notification.collection.listbuilder.pluggable.NotifFilter;
import com.android.systemui.statusbar.notification.collection.listbuilder.pluggable.NotifPromoter;
import com.android.systemui.statusbar.notification.collection.listbuilder.pluggable.NotifSectioner;
import com.android.systemui.statusbar.notification.collection.listbuilder.pluggable.NotifStabilityManager;
import com.android.systemui.statusbar.notification.collection.notifcollection.CommonNotifCollection;
+import com.android.systemui.statusbar.notification.collection.notifcollection.InternalNotifUpdater;
import com.android.systemui.statusbar.notification.collection.notifcollection.NotifCollectionListener;
import com.android.systemui.statusbar.notification.collection.notifcollection.NotifDismissInterceptor;
import com.android.systemui.statusbar.notification.collection.notifcollection.NotifLifetimeExtender;
@@ -216,6 +220,22 @@
mShadeListBuilder.addOnBeforeRenderListListener(listener);
}
+ /** Registers an invalidator that can be used to invalidate the entire notif list. */
+ public void addPreRenderInvalidator(Invalidator invalidator) {
+ mShadeListBuilder.addPreRenderInvalidator(invalidator);
+ }
+
+ /**
+ * Get an object which can be used to update a notification (internally to the pipeline)
+ * in response to a user action.
+ *
+ * @param name the name of the component that will update notifiations
+ * @return an updater
+ */
+ public InternalNotifUpdater getInternalNotifUpdater(String name) {
+ return mNotifCollection.getInternalNotifUpdater(name);
+ }
+
/**
* Returns a read-only view in to the current shade list, i.e. the list of notifications that
* are currently present in the shade. If this method is called during pipeline execution it
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/ShadeListBuilder.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/ShadeListBuilder.java
index 3730524..9faec7b 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/ShadeListBuilder.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/ShadeListBuilder.java
@@ -45,6 +45,7 @@
import com.android.systemui.statusbar.notification.collection.listbuilder.OnBeforeTransformGroupsListener;
import com.android.systemui.statusbar.notification.collection.listbuilder.PipelineState;
import com.android.systemui.statusbar.notification.collection.listbuilder.ShadeListBuilderLogger;
+import com.android.systemui.statusbar.notification.collection.listbuilder.pluggable.Invalidator;
import com.android.systemui.statusbar.notification.collection.listbuilder.pluggable.NotifComparator;
import com.android.systemui.statusbar.notification.collection.listbuilder.pluggable.NotifFilter;
import com.android.systemui.statusbar.notification.collection.listbuilder.pluggable.NotifPromoter;
@@ -174,6 +175,13 @@
mOnBeforeRenderListListeners.add(listener);
}
+ void addPreRenderInvalidator(Invalidator invalidator) {
+ Assert.isMainThread();
+
+ mPipelineState.requireState(STATE_IDLE);
+ invalidator.setInvalidationListener(this::onPreRenderInvalidated);
+ }
+
void addPreGroupFilter(NotifFilter filter) {
Assert.isMainThread();
mPipelineState.requireState(STATE_IDLE);
@@ -256,6 +264,14 @@
}
};
+ private void onPreRenderInvalidated(Invalidator invalidator) {
+ Assert.isMainThread();
+
+ mLogger.logPreRenderInvalidated(invalidator.getName(), mPipelineState.getState());
+
+ rebuildListIfBefore(STATE_FINALIZING);
+ }
+
private void onPreGroupFilterInvalidated(NotifFilter filter) {
Assert.isMainThread();
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/AppOpsCoordinator.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/AppOpsCoordinator.java
index 301b185..3a39c39 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/AppOpsCoordinator.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/AppOpsCoordinator.java
@@ -23,11 +23,11 @@
import com.android.systemui.ForegroundServiceController;
import com.android.systemui.appops.AppOpsController;
-import com.android.systemui.dagger.SysUISingleton;
import com.android.systemui.dagger.qualifiers.Main;
import com.android.systemui.statusbar.notification.collection.ListEntry;
import com.android.systemui.statusbar.notification.collection.NotifPipeline;
import com.android.systemui.statusbar.notification.collection.NotificationEntry;
+import com.android.systemui.statusbar.notification.collection.coordinator.dagger.CoordinatorScope;
import com.android.systemui.statusbar.notification.collection.listbuilder.pluggable.NotifFilter;
import com.android.systemui.statusbar.notification.collection.listbuilder.pluggable.NotifSectioner;
import com.android.systemui.statusbar.notification.stack.NotificationPriorityBucketKt;
@@ -48,7 +48,7 @@
* frameworks/base/packages/SystemUI/src/com/android/systemui/ForegroundServiceNotificationListener
* frameworks/base/packages/SystemUI/src/com/android/systemui/ForegroundServiceLifetimeExtender
*/
-@SysUISingleton
+@CoordinatorScope
public class AppOpsCoordinator implements Coordinator {
private static final String TAG = "AppOpsCoordinator";
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/BubbleCoordinator.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/BubbleCoordinator.java
index 29a030f..15f0d88 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/BubbleCoordinator.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/BubbleCoordinator.java
@@ -16,10 +16,10 @@
package com.android.systemui.statusbar.notification.collection.coordinator;
-import com.android.systemui.dagger.SysUISingleton;
import com.android.systemui.statusbar.notification.collection.NotifCollection;
import com.android.systemui.statusbar.notification.collection.NotifPipeline;
import com.android.systemui.statusbar.notification.collection.NotificationEntry;
+import com.android.systemui.statusbar.notification.collection.coordinator.dagger.CoordinatorScope;
import com.android.systemui.statusbar.notification.collection.listbuilder.pluggable.NotifFilter;
import com.android.systemui.statusbar.notification.collection.notifcollection.DismissedByUserStats;
import com.android.systemui.statusbar.notification.collection.notifcollection.NotifDismissInterceptor;
@@ -53,7 +53,7 @@
* respond to app-cancellations (ie: remove the bubble if the app cancels the notification).
*
*/
-@SysUISingleton
+@CoordinatorScope
public class BubbleCoordinator implements Coordinator {
private static final String TAG = "BubbleCoordinator";
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/CommunalCoordinator.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/CommunalCoordinator.java
index 369e52f..992d898 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/CommunalCoordinator.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/CommunalCoordinator.java
@@ -23,6 +23,7 @@
import com.android.systemui.statusbar.notification.NotificationEntryManager;
import com.android.systemui.statusbar.notification.collection.NotifPipeline;
import com.android.systemui.statusbar.notification.collection.NotificationEntry;
+import com.android.systemui.statusbar.notification.collection.coordinator.dagger.CoordinatorScope;
import com.android.systemui.statusbar.notification.collection.listbuilder.pluggable.NotifFilter;
import javax.inject.Inject;
@@ -31,6 +32,7 @@
* {@link CommunalCoordinator} prevents notifications from showing on the keyguard when the communal
* view is present.
*/
+@CoordinatorScope
public class CommunalCoordinator implements Coordinator {
final CommunalStateController mCommunalStateController;
final NotificationEntryManager mNotificationEntryManager;
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/ConversationCoordinator.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/ConversationCoordinator.kt
index c385836..e59f4a6 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/ConversationCoordinator.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/ConversationCoordinator.kt
@@ -16,10 +16,10 @@
package com.android.systemui.statusbar.notification.collection.coordinator
-import com.android.systemui.dagger.SysUISingleton
import com.android.systemui.statusbar.notification.collection.ListEntry
import com.android.systemui.statusbar.notification.collection.NotifPipeline
import com.android.systemui.statusbar.notification.collection.NotificationEntry
+import com.android.systemui.statusbar.notification.collection.coordinator.dagger.CoordinatorScope
import com.android.systemui.statusbar.notification.collection.listbuilder.pluggable.NotifPromoter
import com.android.systemui.statusbar.notification.collection.listbuilder.pluggable.NotifSectioner
import com.android.systemui.statusbar.notification.collection.render.NodeController
@@ -34,7 +34,7 @@
* - Elevates important conversation notifications
* - Puts conversations into its own people section. @see [NotifCoordinators] for section ordering.
*/
-@SysUISingleton
+@CoordinatorScope
class ConversationCoordinator @Inject constructor(
private val peopleNotificationIdentifier: PeopleNotificationIdentifier,
@PeopleHeader peopleHeaderController: NodeController
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/DeviceProvisionedCoordinator.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/DeviceProvisionedCoordinator.java
index 47928b4..e865249 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/DeviceProvisionedCoordinator.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/DeviceProvisionedCoordinator.java
@@ -23,9 +23,9 @@
import android.os.RemoteException;
import android.service.notification.StatusBarNotification;
-import com.android.systemui.dagger.SysUISingleton;
import com.android.systemui.statusbar.notification.collection.NotifPipeline;
import com.android.systemui.statusbar.notification.collection.NotificationEntry;
+import com.android.systemui.statusbar.notification.collection.coordinator.dagger.CoordinatorScope;
import com.android.systemui.statusbar.notification.collection.listbuilder.pluggable.NotifFilter;
import com.android.systemui.statusbar.policy.DeviceProvisionedController;
@@ -36,7 +36,7 @@
* Special notifications with extra permissions and tags won't be filtered out even when the
* device is unprovisioned.
*/
-@SysUISingleton
+@CoordinatorScope
public class DeviceProvisionedCoordinator implements Coordinator {
private static final String TAG = "DeviceProvisionedCoordinator";
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/GutsCoordinator.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/GutsCoordinator.kt
index 8948969..dbecf1c 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/GutsCoordinator.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/GutsCoordinator.kt
@@ -17,17 +17,17 @@
import android.util.ArraySet
import com.android.systemui.Dumpable
-import com.android.systemui.dagger.SysUISingleton
import com.android.systemui.dump.DumpManager
import com.android.systemui.statusbar.notification.collection.ListEntry
import com.android.systemui.statusbar.notification.collection.NotifPipeline
import com.android.systemui.statusbar.notification.collection.NotificationEntry
+import com.android.systemui.statusbar.notification.collection.coordinator.dagger.CoordinatorScope
import com.android.systemui.statusbar.notification.collection.notifcollection.NotifLifetimeExtender
import com.android.systemui.statusbar.notification.collection.notifcollection.NotifLifetimeExtender.OnEndLifetimeExtensionCallback
-import com.android.systemui.statusbar.notification.row.NotificationGuts
-import com.android.systemui.statusbar.notification.row.NotificationGutsManager
import com.android.systemui.statusbar.notification.collection.render.NotifGutsViewListener
import com.android.systemui.statusbar.notification.collection.render.NotifGutsViewManager
+import com.android.systemui.statusbar.notification.row.NotificationGuts
+import com.android.systemui.statusbar.notification.row.NotificationGutsManager
import java.io.FileDescriptor
import java.io.PrintWriter
import javax.inject.Inject
@@ -38,7 +38,7 @@
* Coordinates the guts displayed by the [NotificationGutsManager] with the pipeline.
* Specifically, this just adds the lifetime extension necessary to keep guts from disappearing.
*/
-@SysUISingleton
+@CoordinatorScope
class GutsCoordinator @Inject constructor(
private val notifGutsViewManager: NotifGutsViewManager,
private val logger: GutsCoordinatorLogger,
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/GutsCoordinatorLogger.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/GutsCoordinatorLogger.kt
index bac5223..e8f352f 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/GutsCoordinatorLogger.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/GutsCoordinatorLogger.kt
@@ -15,7 +15,7 @@
fun logGutsOpened(key: String, guts: NotificationGuts) {
buffer.log(TAG, LogLevel.DEBUG, {
str1 = key
- str2 = guts::class.simpleName
+ str2 = guts.gutsContent::class.simpleName
bool1 = guts.isLeavebehind
}, {
"Guts of type $str2 (leave behind: $bool1) opened for class $str1"
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/HeadsUpCoordinator.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/HeadsUpCoordinator.java
index 8c8a8a9..f8b4274 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/HeadsUpCoordinator.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/HeadsUpCoordinator.java
@@ -22,11 +22,11 @@
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
-import com.android.systemui.dagger.SysUISingleton;
import com.android.systemui.statusbar.NotificationRemoteInputManager;
import com.android.systemui.statusbar.notification.collection.ListEntry;
import com.android.systemui.statusbar.notification.collection.NotifPipeline;
import com.android.systemui.statusbar.notification.collection.NotificationEntry;
+import com.android.systemui.statusbar.notification.collection.coordinator.dagger.CoordinatorScope;
import com.android.systemui.statusbar.notification.collection.listbuilder.pluggable.NotifPromoter;
import com.android.systemui.statusbar.notification.collection.listbuilder.pluggable.NotifSectioner;
import com.android.systemui.statusbar.notification.collection.notifcollection.NotifCollectionListener;
@@ -57,7 +57,7 @@
*
* Note: The inflation callback in {@link PreparationCoordinator} handles showing HUNs.
*/
-@SysUISingleton
+@CoordinatorScope
public class HeadsUpCoordinator implements Coordinator {
private static final String TAG = "HeadsUpCoordinator";
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/HideLocallyDismissedNotifsCoordinator.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/HideLocallyDismissedNotifsCoordinator.java
index 0059e7b..6684237 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/HideLocallyDismissedNotifsCoordinator.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/HideLocallyDismissedNotifsCoordinator.java
@@ -20,13 +20,21 @@
import com.android.systemui.statusbar.notification.collection.NotifPipeline;
import com.android.systemui.statusbar.notification.collection.NotificationEntry;
+import com.android.systemui.statusbar.notification.collection.coordinator.dagger.CoordinatorScope;
import com.android.systemui.statusbar.notification.collection.listbuilder.pluggable.NotifFilter;
+import javax.inject.Inject;
+
/**
* Filters out notifications that have been dismissed locally (by the user) but that system server
* hasn't yet confirmed the removal of.
*/
+@CoordinatorScope
public class HideLocallyDismissedNotifsCoordinator implements Coordinator {
+
+ @Inject
+ HideLocallyDismissedNotifsCoordinator() { }
+
@Override
public void attach(NotifPipeline pipeline) {
pipeline.addPreGroupFilter(mFilter);
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/HideNotifsForOtherUsersCoordinator.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/HideNotifsForOtherUsersCoordinator.java
index e595dd4..7b5cf85 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/HideNotifsForOtherUsersCoordinator.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/HideNotifsForOtherUsersCoordinator.java
@@ -23,6 +23,7 @@
import com.android.systemui.statusbar.NotificationLockscreenUserManager.UserChangedListener;
import com.android.systemui.statusbar.notification.collection.NotifPipeline;
import com.android.systemui.statusbar.notification.collection.NotificationEntry;
+import com.android.systemui.statusbar.notification.collection.coordinator.dagger.CoordinatorScope;
import com.android.systemui.statusbar.notification.collection.listbuilder.pluggable.NotifFilter;
import javax.inject.Inject;
@@ -37,6 +38,7 @@
* TODO: The NotificationLockscreenUserManager currently maintains the list of active user profiles.
* We should spin that off into a standalone section at some point.
*/
+@CoordinatorScope
public class HideNotifsForOtherUsersCoordinator implements Coordinator {
private final NotificationLockscreenUserManager mLockscreenUserManager;
private final SharedCoordinatorLogger mLogger;
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/KeyguardCoordinator.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/KeyguardCoordinator.java
index 23d5369..fe1cd7b 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/KeyguardCoordinator.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/KeyguardCoordinator.java
@@ -34,13 +34,13 @@
import com.android.keyguard.KeyguardUpdateMonitor;
import com.android.keyguard.KeyguardUpdateMonitorCallback;
import com.android.systemui.broadcast.BroadcastDispatcher;
-import com.android.systemui.dagger.SysUISingleton;
import com.android.systemui.plugins.statusbar.StatusBarStateController;
import com.android.systemui.statusbar.NotificationLockscreenUserManager;
import com.android.systemui.statusbar.notification.collection.GroupEntry;
import com.android.systemui.statusbar.notification.collection.ListEntry;
import com.android.systemui.statusbar.notification.collection.NotifPipeline;
import com.android.systemui.statusbar.notification.collection.NotificationEntry;
+import com.android.systemui.statusbar.notification.collection.coordinator.dagger.CoordinatorScope;
import com.android.systemui.statusbar.notification.collection.listbuilder.pluggable.NotifFilter;
import com.android.systemui.statusbar.notification.collection.provider.HighPriorityProvider;
import com.android.systemui.statusbar.policy.KeyguardStateController;
@@ -50,7 +50,7 @@
/**
* Filters low priority and privacy-sensitive notifications from the lockscreen.
*/
-@SysUISingleton
+@CoordinatorScope
public class KeyguardCoordinator implements Coordinator {
private static final String TAG = "KeyguardCoordinator";
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/MediaCoordinator.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/MediaCoordinator.java
index 026a3ff..8769969 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/MediaCoordinator.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/MediaCoordinator.java
@@ -21,6 +21,7 @@
import com.android.systemui.media.MediaFeatureFlag;
import com.android.systemui.statusbar.notification.collection.NotifPipeline;
import com.android.systemui.statusbar.notification.collection.NotificationEntry;
+import com.android.systemui.statusbar.notification.collection.coordinator.dagger.CoordinatorScope;
import com.android.systemui.statusbar.notification.collection.listbuilder.pluggable.NotifFilter;
import javax.inject.Inject;
@@ -28,6 +29,7 @@
/**
* Coordinates hiding (filtering) of media notifications.
*/
+@CoordinatorScope
public class MediaCoordinator implements Coordinator {
private static final String TAG = "MediaCoordinator";
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/NotifCoordinators.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/NotifCoordinators.java
deleted file mode 100644
index 18f3b45..0000000
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/NotifCoordinators.java
+++ /dev/null
@@ -1,126 +0,0 @@
-/*
- * 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.
- */
-
-package com.android.systemui.statusbar.notification.collection.coordinator;
-
-import com.android.systemui.Dumpable;
-import com.android.systemui.dagger.SysUISingleton;
-import com.android.systemui.dump.DumpManager;
-import com.android.systemui.flags.FeatureFlags;
-import com.android.systemui.statusbar.notification.collection.NotifPipeline;
-import com.android.systemui.statusbar.notification.collection.listbuilder.pluggable.NotifSectioner;
-import com.android.systemui.statusbar.notification.collection.listbuilder.pluggable.Pluggable;
-import com.android.systemui.statusbar.notification.collection.notifcollection.NotifCollectionListener;
-import com.android.systemui.statusbar.notification.collection.notifcollection.NotifLifetimeExtender;
-
-import java.io.FileDescriptor;
-import java.io.PrintWriter;
-import java.util.ArrayList;
-import java.util.List;
-
-import javax.inject.Inject;
-
-/**
- * Handles the attachment of {@link Coordinator}s to the {@link NotifPipeline} so that the
- * Coordinators can register their respective callbacks.
- */
-@SysUISingleton
-public class NotifCoordinators implements Dumpable {
- private static final String TAG = "NotifCoordinators";
- private final List<Coordinator> mCoordinators = new ArrayList<>();
- private final List<NotifSectioner> mOrderedSections = new ArrayList<>();
-
- /**
- * Creates all the coordinators.
- */
- @Inject
- public NotifCoordinators(
- DumpManager dumpManager,
- FeatureFlags featureFlags,
- HideNotifsForOtherUsersCoordinator hideNotifsForOtherUsersCoordinator,
- KeyguardCoordinator keyguardCoordinator,
- RankingCoordinator rankingCoordinator,
- AppOpsCoordinator appOpsCoordinator,
- DeviceProvisionedCoordinator deviceProvisionedCoordinator,
- BubbleCoordinator bubbleCoordinator,
- HeadsUpCoordinator headsUpCoordinator,
- GutsCoordinator gutsCoordinator,
- ConversationCoordinator conversationCoordinator,
- PreparationCoordinator preparationCoordinator,
- MediaCoordinator mediaCoordinator,
- SmartspaceDedupingCoordinator smartspaceDedupingCoordinator,
- VisualStabilityCoordinator visualStabilityCoordinator,
- CommunalCoordinator communalCoordinator) {
- dumpManager.registerDumpable(TAG, this);
-
- mCoordinators.add(new HideLocallyDismissedNotifsCoordinator());
- mCoordinators.add(hideNotifsForOtherUsersCoordinator);
- mCoordinators.add(keyguardCoordinator);
- mCoordinators.add(rankingCoordinator);
- mCoordinators.add(appOpsCoordinator);
- mCoordinators.add(deviceProvisionedCoordinator);
- mCoordinators.add(bubbleCoordinator);
- mCoordinators.add(conversationCoordinator);
- mCoordinators.add(mediaCoordinator);
- mCoordinators.add(visualStabilityCoordinator);
- mCoordinators.add(communalCoordinator);
-
- if (featureFlags.isSmartspaceDedupingEnabled()) {
- mCoordinators.add(smartspaceDedupingCoordinator);
- }
-
- if (featureFlags.isNewNotifPipelineRenderingEnabled()) {
- mCoordinators.add(headsUpCoordinator);
- mCoordinators.add(gutsCoordinator);
- mCoordinators.add(preparationCoordinator);
- }
-
- // Manually add Ordered Sections
- // HeadsUp > FGS > People > Alerting > Silent > Unknown/Default
- if (featureFlags.isNewNotifPipelineRenderingEnabled()) {
- mOrderedSections.add(headsUpCoordinator.getSectioner()); // HeadsUp
- }
- mOrderedSections.add(appOpsCoordinator.getSectioner()); // ForegroundService
- mOrderedSections.add(conversationCoordinator.getSectioner()); // People
- mOrderedSections.add(rankingCoordinator.getAlertingSectioner()); // Alerting
- mOrderedSections.add(rankingCoordinator.getSilentSectioner()); // Silent
- }
-
- /**
- * Sends the pipeline to each coordinator when the pipeline is ready to accept
- * {@link Pluggable}s, {@link NotifCollectionListener}s and {@link NotifLifetimeExtender}s.
- */
- public void attach(NotifPipeline pipeline) {
- for (Coordinator c : mCoordinators) {
- c.attach(pipeline);
- }
-
- pipeline.setSections(mOrderedSections);
- }
-
- @Override
- public void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
- pw.println();
- pw.println(TAG + ":");
- for (Coordinator c : mCoordinators) {
- pw.println("\t" + c.getClass());
- }
-
- for (NotifSectioner s : mOrderedSections) {
- pw.println("\t" + s.getName());
- }
- }
-}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/NotifCoordinators.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/NotifCoordinators.kt
new file mode 100644
index 0000000..bf3e712
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/NotifCoordinators.kt
@@ -0,0 +1,128 @@
+/*
+ * 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.
+ */
+package com.android.systemui.statusbar.notification.collection.coordinator
+
+import com.android.systemui.Dumpable
+import com.android.systemui.dump.DumpManager
+import com.android.systemui.flags.FeatureFlags
+import com.android.systemui.statusbar.notification.collection.NotifPipeline
+import com.android.systemui.statusbar.notification.collection.coordinator.dagger.CoordinatorScope
+import com.android.systemui.statusbar.notification.collection.listbuilder.pluggable.NotifSectioner
+import java.io.FileDescriptor
+import java.io.PrintWriter
+import java.util.ArrayList
+import javax.inject.Inject
+
+/**
+ * Handles the attachment of [Coordinator]s to the [NotifPipeline] so that the
+ * Coordinators can register their respective callbacks.
+ */
+interface NotifCoordinators : Coordinator, Dumpable
+
+@CoordinatorScope
+class NotifCoordinatorsImpl @Inject constructor(
+ dumpManager: DumpManager,
+ featureFlags: FeatureFlags,
+ hideLocallyDismissedNotifsCoordinator: HideLocallyDismissedNotifsCoordinator,
+ hideNotifsForOtherUsersCoordinator: HideNotifsForOtherUsersCoordinator,
+ keyguardCoordinator: KeyguardCoordinator,
+ rankingCoordinator: RankingCoordinator,
+ appOpsCoordinator: AppOpsCoordinator,
+ deviceProvisionedCoordinator: DeviceProvisionedCoordinator,
+ bubbleCoordinator: BubbleCoordinator,
+ headsUpCoordinator: HeadsUpCoordinator,
+ gutsCoordinator: GutsCoordinator,
+ conversationCoordinator: ConversationCoordinator,
+ preparationCoordinator: PreparationCoordinator,
+ mediaCoordinator: MediaCoordinator,
+ remoteInputCoordinator: RemoteInputCoordinator,
+ shadeEventCoordinator: ShadeEventCoordinator,
+ smartspaceDedupingCoordinator: SmartspaceDedupingCoordinator,
+ viewConfigCoordinator: ViewConfigCoordinator,
+ visualStabilityCoordinator: VisualStabilityCoordinator,
+ communalCoordinator: CommunalCoordinator,
+ sensitiveContentCoordinator: SensitiveContentCoordinator
+) : NotifCoordinators {
+
+ private val mCoordinators: MutableList<Coordinator> = ArrayList()
+ private val mOrderedSections: MutableList<NotifSectioner> = ArrayList()
+
+ /**
+ * Creates all the coordinators.
+ */
+ init {
+ dumpManager.registerDumpable(TAG, this)
+ mCoordinators.add(hideLocallyDismissedNotifsCoordinator)
+ mCoordinators.add(hideNotifsForOtherUsersCoordinator)
+ mCoordinators.add(keyguardCoordinator)
+ mCoordinators.add(rankingCoordinator)
+ mCoordinators.add(appOpsCoordinator)
+ mCoordinators.add(deviceProvisionedCoordinator)
+ mCoordinators.add(bubbleCoordinator)
+ mCoordinators.add(conversationCoordinator)
+ mCoordinators.add(mediaCoordinator)
+ mCoordinators.add(remoteInputCoordinator)
+ mCoordinators.add(shadeEventCoordinator)
+ mCoordinators.add(viewConfigCoordinator)
+ mCoordinators.add(visualStabilityCoordinator)
+ mCoordinators.add(communalCoordinator)
+ mCoordinators.add(sensitiveContentCoordinator)
+ if (featureFlags.isSmartspaceDedupingEnabled) {
+ mCoordinators.add(smartspaceDedupingCoordinator)
+ }
+ if (featureFlags.isNewNotifPipelineRenderingEnabled) {
+ mCoordinators.add(headsUpCoordinator)
+ mCoordinators.add(gutsCoordinator)
+ mCoordinators.add(preparationCoordinator)
+ }
+
+ // Manually add Ordered Sections
+ // HeadsUp > FGS > People > Alerting > Silent > Unknown/Default
+ if (featureFlags.isNewNotifPipelineRenderingEnabled) {
+ mOrderedSections.add(headsUpCoordinator.sectioner) // HeadsUp
+ }
+ mOrderedSections.add(appOpsCoordinator.sectioner) // ForegroundService
+ mOrderedSections.add(conversationCoordinator.sectioner) // People
+ mOrderedSections.add(rankingCoordinator.alertingSectioner) // Alerting
+ mOrderedSections.add(rankingCoordinator.silentSectioner) // Silent
+ }
+
+ /**
+ * Sends the pipeline to each coordinator when the pipeline is ready to accept
+ * [Pluggable]s, [NotifCollectionListener]s and [NotifLifetimeExtender]s.
+ */
+ override fun attach(pipeline: NotifPipeline) {
+ for (c in mCoordinators) {
+ c.attach(pipeline)
+ }
+ pipeline.setSections(mOrderedSections)
+ }
+
+ override fun dump(fd: FileDescriptor, pw: PrintWriter, args: Array<String>) {
+ pw.println()
+ pw.println("$TAG:")
+ for (c in mCoordinators) {
+ pw.println("\t${c.javaClass}")
+ }
+ for (s in mOrderedSections) {
+ pw.println("\t${s.name}")
+ }
+ }
+
+ companion object {
+ private const val TAG = "NotifCoordinators"
+ }
+}
\ No newline at end of file
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/PreparationCoordinator.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/PreparationCoordinator.java
index 31826c7..afdfb3b 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/PreparationCoordinator.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/PreparationCoordinator.java
@@ -57,6 +57,7 @@
* If a notification was uninflated, this coordinator will filter the notification out from the
* {@link ShadeListBuilder} until it is inflated.
*/
+// TODO(b/204468557): Move to @CoordinatorScope
@SysUISingleton
public class PreparationCoordinator implements Coordinator {
private static final String TAG = "PreparationCoordinator";
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/RankingCoordinator.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/RankingCoordinator.java
index 1a6a63a..2ab2dd0 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/RankingCoordinator.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/RankingCoordinator.java
@@ -19,11 +19,11 @@
import android.annotation.NonNull;
import android.annotation.Nullable;
-import com.android.systemui.dagger.SysUISingleton;
import com.android.systemui.plugins.statusbar.StatusBarStateController;
import com.android.systemui.statusbar.notification.collection.ListEntry;
import com.android.systemui.statusbar.notification.collection.NotifPipeline;
import com.android.systemui.statusbar.notification.collection.NotificationEntry;
+import com.android.systemui.statusbar.notification.collection.coordinator.dagger.CoordinatorScope;
import com.android.systemui.statusbar.notification.collection.listbuilder.pluggable.NotifFilter;
import com.android.systemui.statusbar.notification.collection.listbuilder.pluggable.NotifSectioner;
import com.android.systemui.statusbar.notification.collection.provider.HighPriorityProvider;
@@ -44,7 +44,7 @@
* - whether the notification's app is suspended or hiding its notifications
* - whether DND settings are hiding notifications from ambient display or the notification list
*/
-@SysUISingleton
+@CoordinatorScope
public class RankingCoordinator implements Coordinator {
public static final boolean SHOW_ALL_SECTIONS = false;
private final StatusBarStateController mStatusBarStateController;
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/RemoteInputCoordinator.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/RemoteInputCoordinator.kt
new file mode 100644
index 0000000..3397815
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/RemoteInputCoordinator.kt
@@ -0,0 +1,225 @@
+/*
+ * Copyright (C) 2021 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.notification.collection.coordinator
+
+import android.os.Handler
+import android.service.notification.NotificationListenerService.REASON_CANCEL
+import android.service.notification.NotificationListenerService.REASON_CLICK
+import android.util.Log
+import androidx.annotation.VisibleForTesting
+import com.android.systemui.Dumpable
+import com.android.systemui.dagger.SysUISingleton
+import com.android.systemui.dagger.qualifiers.Main
+import com.android.systemui.dump.DumpManager
+import com.android.systemui.statusbar.NotificationRemoteInputManager
+import com.android.systemui.statusbar.NotificationRemoteInputManager.RemoteInputListener
+import com.android.systemui.statusbar.RemoteInputController
+import com.android.systemui.statusbar.RemoteInputNotificationRebuilder
+import com.android.systemui.statusbar.SmartReplyController
+import com.android.systemui.statusbar.notification.collection.NotifPipeline
+import com.android.systemui.statusbar.notification.collection.NotificationEntry
+import com.android.systemui.statusbar.notification.collection.notifcollection.SelfTrackingLifetimeExtender
+import com.android.systemui.statusbar.notification.collection.notifcollection.InternalNotifUpdater
+import com.android.systemui.statusbar.notification.collection.notifcollection.NotifCollectionListener
+import com.android.systemui.statusbar.notification.collection.notifcollection.NotifLifetimeExtender
+import java.io.FileDescriptor
+import java.io.PrintWriter
+import javax.inject.Inject
+
+private const val TAG = "RemoteInputCoordinator"
+
+/**
+ * How long to wait before auto-dismissing a notification that was kept for active remote input, and
+ * has now sent a remote input. We auto-dismiss, because the app may not cannot cancel
+ * these given that they technically don't exist anymore. We wait a bit in case the app issues
+ * an update, and to also give the other lifetime extenders a beat to decide they want it.
+ */
+private const val REMOTE_INPUT_ACTIVE_EXTENDER_AUTO_CANCEL_DELAY: Long = 500
+
+/**
+ * How long to wait before releasing a lifetime extension when requested to do so due to a user
+ * interaction (such as tapping another action).
+ * We wait a bit in case the app issues an update in response to the action, but not too long or we
+ * risk appearing unresponsive to the user.
+ */
+private const val REMOTE_INPUT_EXTENDER_RELEASE_DELAY: Long = 200
+
+/** Whether this class should print spammy debug logs */
+private val DEBUG: Boolean by lazy { Log.isLoggable(TAG, Log.DEBUG) }
+
+@SysUISingleton
+class RemoteInputCoordinator @Inject constructor(
+ dumpManager: DumpManager,
+ private val mRebuilder: RemoteInputNotificationRebuilder,
+ private val mNotificationRemoteInputManager: NotificationRemoteInputManager,
+ @Main private val mMainHandler: Handler,
+ private val mSmartReplyController: SmartReplyController
+) : Coordinator, RemoteInputListener, Dumpable {
+
+ @VisibleForTesting val mRemoteInputHistoryExtender = RemoteInputHistoryExtender()
+ @VisibleForTesting val mSmartReplyHistoryExtender = SmartReplyHistoryExtender()
+ @VisibleForTesting val mRemoteInputActiveExtender = RemoteInputActiveExtender()
+ private val mRemoteInputLifetimeExtenders = listOf(
+ mRemoteInputHistoryExtender,
+ mSmartReplyHistoryExtender,
+ mRemoteInputActiveExtender
+ )
+
+ private lateinit var mNotifUpdater: InternalNotifUpdater
+
+ init {
+ dumpManager.registerDumpable(this)
+ }
+
+ fun getLifetimeExtenders(): List<NotifLifetimeExtender> = mRemoteInputLifetimeExtenders
+
+ override fun attach(pipeline: NotifPipeline) {
+ mNotificationRemoteInputManager.setRemoteInputListener(this)
+ mRemoteInputLifetimeExtenders.forEach { pipeline.addNotificationLifetimeExtender(it) }
+ mNotifUpdater = pipeline.getInternalNotifUpdater(TAG)
+ pipeline.addCollectionListener(mCollectionListener)
+ }
+
+ val mCollectionListener = object : NotifCollectionListener {
+ override fun onEntryUpdated(entry: NotificationEntry, fromSystem: Boolean) {
+ if (DEBUG) {
+ Log.d(TAG, "mCollectionListener.onEntryUpdated(entry=${entry.key}," +
+ " fromSystem=$fromSystem)")
+ }
+ if (fromSystem) {
+ // Mark smart replies as sent whenever a notification is updated by the app,
+ // otherwise the smart replies are never marked as sent.
+ mSmartReplyController.stopSending(entry)
+ }
+ }
+
+ override fun onEntryRemoved(entry: NotificationEntry, reason: Int) {
+ if (DEBUG) Log.d(TAG, "mCollectionListener.onEntryRemoved(entry=${entry.key})")
+ // We're removing the notification, the smart reply controller can forget about it.
+ // TODO(b/145659174): track 'sending' state on the entry to avoid having to clear it.
+ mSmartReplyController.stopSending(entry)
+
+ // When we know the entry will not be lifetime extended, clean up the remote input view
+ // TODO: Share code with NotifCollection.cannotBeLifetimeExtended
+ if (reason == REASON_CANCEL || reason == REASON_CLICK) {
+ mNotificationRemoteInputManager.cleanUpRemoteInputForUserRemoval(entry)
+ }
+ }
+ }
+
+ override fun dump(fd: FileDescriptor, pw: PrintWriter, args: Array<out String>) {
+ mRemoteInputLifetimeExtenders.forEach { it.dump(fd, pw, args) }
+ }
+
+ override fun onRemoteInputSent(entry: NotificationEntry) {
+ if (DEBUG) Log.d(TAG, "onRemoteInputSent(entry=${entry.key})")
+ // These calls effectively ensure the freshness of the lifetime extensions.
+ // NOTE: This is some trickery! By removing the lifetime extensions when we know they should
+ // be immediately re-upped, we ensure that the side-effects of the lifetime extenders get to
+ // fire again, thus ensuring that we add subsequent replies to the notification.
+ mRemoteInputHistoryExtender.endLifetimeExtension(entry.key)
+ mSmartReplyHistoryExtender.endLifetimeExtension(entry.key)
+
+ // If we're extending for remote input being active, then from the apps point of
+ // view it is already canceled, so we'll need to cancel it on the apps behalf
+ // now that a reply has been sent. However, delay so that the app has time to posts an
+ // update in the mean time, and to give another lifetime extender time to pick it up.
+ mRemoteInputActiveExtender.endLifetimeExtensionAfterDelay(entry.key,
+ REMOTE_INPUT_ACTIVE_EXTENDER_AUTO_CANCEL_DELAY)
+ }
+
+ private fun onSmartReplySent(entry: NotificationEntry, reply: CharSequence) {
+ if (DEBUG) Log.d(TAG, "onSmartReplySent(entry=${entry.key})")
+ val newSbn = mRebuilder.rebuildForSendingSmartReply(entry, reply)
+ mNotifUpdater.onInternalNotificationUpdate(newSbn,
+ "Adding smart reply spinner for sent")
+
+ // If we're extending for remote input being active, then from the apps point of
+ // view it is already canceled, so we'll need to cancel it on the apps behalf
+ // now that a reply has been sent. However, delay so that the app has time to posts an
+ // update in the mean time, and to give another lifetime extender time to pick it up.
+ mRemoteInputActiveExtender.endLifetimeExtensionAfterDelay(entry.key,
+ REMOTE_INPUT_ACTIVE_EXTENDER_AUTO_CANCEL_DELAY)
+ }
+
+ override fun onPanelCollapsed() {
+ mRemoteInputActiveExtender.endAllLifetimeExtensions()
+ }
+
+ override fun isNotificationKeptForRemoteInputHistory(key: String) =
+ mRemoteInputHistoryExtender.isExtending(key) ||
+ mSmartReplyHistoryExtender.isExtending(key)
+
+ override fun releaseNotificationIfKeptForRemoteInputHistory(entry: NotificationEntry) {
+ if (DEBUG) Log.d(TAG, "releaseNotificationIfKeptForRemoteInputHistory(entry=${entry.key})")
+ mRemoteInputHistoryExtender.endLifetimeExtensionAfterDelay(entry.key,
+ REMOTE_INPUT_EXTENDER_RELEASE_DELAY)
+ mSmartReplyHistoryExtender.endLifetimeExtensionAfterDelay(entry.key,
+ REMOTE_INPUT_EXTENDER_RELEASE_DELAY)
+ mRemoteInputActiveExtender.endLifetimeExtensionAfterDelay(entry.key,
+ REMOTE_INPUT_EXTENDER_RELEASE_DELAY)
+ }
+
+ override fun setRemoteInputController(remoteInputController: RemoteInputController) {
+ mSmartReplyController.setCallback(this::onSmartReplySent)
+ }
+
+ @VisibleForTesting
+ inner class RemoteInputHistoryExtender :
+ SelfTrackingLifetimeExtender(TAG, "RemoteInputHistory", DEBUG, mMainHandler) {
+
+ override fun queryShouldExtendLifetime(entry: NotificationEntry): Boolean =
+ mNotificationRemoteInputManager.shouldKeepForRemoteInputHistory(entry)
+
+ override fun onStartedLifetimeExtension(entry: NotificationEntry) {
+ val newSbn = mRebuilder.rebuildForRemoteInputReply(entry)
+ entry.onRemoteInputInserted()
+ mNotifUpdater.onInternalNotificationUpdate(newSbn,
+ "Extending lifetime of notification with remote input")
+ // TODO: Check if the entry was removed due perhaps to an inflation exception?
+ }
+ }
+
+ @VisibleForTesting
+ inner class SmartReplyHistoryExtender :
+ SelfTrackingLifetimeExtender(TAG, "SmartReplyHistory", DEBUG, mMainHandler) {
+
+ override fun queryShouldExtendLifetime(entry: NotificationEntry): Boolean =
+ mNotificationRemoteInputManager.shouldKeepForSmartReplyHistory(entry)
+
+ override fun onStartedLifetimeExtension(entry: NotificationEntry) {
+ val newSbn = mRebuilder.rebuildForCanceledSmartReplies(entry)
+ mSmartReplyController.stopSending(entry)
+ mNotifUpdater.onInternalNotificationUpdate(newSbn,
+ "Extending lifetime of notification with smart reply")
+ // TODO: Check if the entry was removed due perhaps to an inflation exception?
+ }
+
+ override fun onCanceledLifetimeExtension(entry: NotificationEntry) {
+ // TODO(b/145659174): track 'sending' state on the entry to avoid having to clear it.
+ mSmartReplyController.stopSending(entry)
+ }
+ }
+
+ @VisibleForTesting
+ inner class RemoteInputActiveExtender :
+ SelfTrackingLifetimeExtender(TAG, "RemoteInputActive", DEBUG, mMainHandler) {
+
+ override fun queryShouldExtendLifetime(entry: NotificationEntry): Boolean =
+ mNotificationRemoteInputManager.isRemoteInputActive(entry)
+ }
+}
\ No newline at end of file
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/SensitiveContentCoordinator.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/SensitiveContentCoordinator.kt
new file mode 100644
index 0000000..4ae8e4c
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/SensitiveContentCoordinator.kt
@@ -0,0 +1,104 @@
+/*
+ * Copyright (C) 2021 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.notification.collection.coordinator
+
+import android.os.UserHandle
+import com.android.systemui.statusbar.NotificationLockscreenUserManager
+import com.android.systemui.statusbar.notification.DynamicPrivacyController
+import com.android.systemui.statusbar.notification.collection.GroupEntry
+import com.android.systemui.statusbar.notification.collection.ListEntry
+import com.android.systemui.statusbar.notification.collection.NotifPipeline
+import com.android.systemui.statusbar.notification.collection.NotificationEntry
+import com.android.systemui.statusbar.notification.collection.coordinator.dagger.CoordinatorScope
+import com.android.systemui.statusbar.notification.collection.listbuilder.OnBeforeRenderListListener
+import com.android.systemui.statusbar.notification.collection.listbuilder.pluggable.Invalidator
+import dagger.Module
+import dagger.Provides
+
+@Module
+object SensitiveContentCoordinatorModule {
+ @Provides
+ @CoordinatorScope
+ fun provideCoordinator(
+ dynamicPrivacyController: DynamicPrivacyController,
+ lockscreenUserManager: NotificationLockscreenUserManager
+ ): SensitiveContentCoordinator =
+ SensitiveContentCoordinatorImpl(dynamicPrivacyController, lockscreenUserManager)
+}
+
+/** Coordinates re-inflation and post-processing of sensitive notification content. */
+interface SensitiveContentCoordinator : Coordinator
+
+private class SensitiveContentCoordinatorImpl(
+ private val dynamicPrivacyController: DynamicPrivacyController,
+ private val lockscreenUserManager: NotificationLockscreenUserManager
+) : Invalidator("SensitiveContentInvalidator"),
+ SensitiveContentCoordinator,
+ DynamicPrivacyController.Listener,
+ OnBeforeRenderListListener {
+
+ override fun attach(pipeline: NotifPipeline) {
+ dynamicPrivacyController.addListener(this)
+ pipeline.addOnBeforeRenderListListener(this)
+ pipeline.addPreRenderInvalidator(this)
+ }
+
+ override fun onDynamicPrivacyChanged(): Unit = invalidateList()
+
+ override fun onBeforeRenderList(entries: List<ListEntry>) {
+ val currentUserId = lockscreenUserManager.currentUserId
+ val devicePublic = lockscreenUserManager.isLockscreenPublicMode(currentUserId)
+ val deviceSensitive = devicePublic &&
+ !lockscreenUserManager.userAllowsPrivateNotificationsInPublic(currentUserId)
+ val dynamicallyUnlocked = dynamicPrivacyController.isDynamicallyUnlocked
+ for (entry in extractAllRepresentativeEntries(entries).filter { it.rowExists() }) {
+ val notifUserId = entry.sbn.user.identifier
+ val userLockscreen = devicePublic ||
+ lockscreenUserManager.isLockscreenPublicMode(notifUserId)
+ val userPublic = when {
+ // if we're not on the lockscreen, we're definitely private
+ !userLockscreen -> false
+ // we are on the lockscreen, so unless we're dynamically unlocked, we're
+ // definitely public
+ !dynamicallyUnlocked -> true
+ // we're dynamically unlocked, but check if the notification needs
+ // a separate challenge if it's from a work profile
+ else -> when (notifUserId) {
+ currentUserId -> false
+ UserHandle.USER_ALL -> false
+ else -> lockscreenUserManager.needsSeparateWorkChallenge(notifUserId)
+ }
+ }
+ val needsRedaction = lockscreenUserManager.needsRedaction(entry)
+ val isSensitive = userPublic && needsRedaction
+ entry.setSensitive(isSensitive, deviceSensitive)
+ }
+ }
+}
+
+private fun extractAllRepresentativeEntries(
+ entries: List<ListEntry>
+): Sequence<NotificationEntry> =
+ entries.asSequence().flatMap(::extractAllRepresentativeEntries)
+
+private fun extractAllRepresentativeEntries(listEntry: ListEntry): Sequence<NotificationEntry> =
+ sequence {
+ listEntry.representativeEntry?.let { yield(it) }
+ if (listEntry is GroupEntry) {
+ yieldAll(extractAllRepresentativeEntries(listEntry.children))
+ }
+ }
\ No newline at end of file
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/ShadeEventCoordinator.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/ShadeEventCoordinator.kt
new file mode 100644
index 0000000..2d5c331
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/ShadeEventCoordinator.kt
@@ -0,0 +1,79 @@
+/*
+ * Copyright (C) 2021 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.notification.collection.coordinator
+
+import android.service.notification.NotificationListenerService
+import com.android.systemui.dagger.SysUISingleton
+import com.android.systemui.statusbar.notification.collection.ListEntry
+import com.android.systemui.statusbar.notification.collection.NotifPipeline
+import com.android.systemui.statusbar.notification.collection.NotificationEntry
+import com.android.systemui.statusbar.notification.collection.notifcollection.NotifCollectionListener
+import com.android.systemui.statusbar.notification.collection.render.NotifShadeEventSource
+import javax.inject.Inject
+
+/**
+ * A coordinator which provides callbacks to a view surfaces for various events relevant to the
+ * shade, such as when the user removes a notification, or when the shade is emptied.
+ */
+// TODO(b/204468557): Move to @CoordinatorScope
+@SysUISingleton
+class ShadeEventCoordinator @Inject internal constructor(
+ private val mLogger: ShadeEventCoordinatorLogger
+) : Coordinator, NotifShadeEventSource {
+ private var mNotifRemovedByUserCallback: Runnable? = null
+ private var mShadeEmptiedCallback: Runnable? = null
+ private var mEntryRemoved = false
+ private var mEntryRemovedByUser = false
+
+ override fun attach(pipeline: NotifPipeline) {
+ pipeline.addCollectionListener(mNotifCollectionListener)
+ pipeline.addOnBeforeRenderListListener(this::onBeforeRenderList)
+ }
+
+ private val mNotifCollectionListener = object : NotifCollectionListener {
+ override fun onEntryRemoved(entry: NotificationEntry, reason: Int) {
+ mEntryRemoved = true
+ mEntryRemovedByUser =
+ reason == NotificationListenerService.REASON_CLICK ||
+ reason == NotificationListenerService.REASON_CANCEL_ALL ||
+ reason == NotificationListenerService.REASON_CANCEL
+ }
+ }
+
+ override fun setNotifRemovedByUserCallback(callback: Runnable) {
+ check(mNotifRemovedByUserCallback == null) { "mNotifRemovedByUserCallback already set" }
+ mNotifRemovedByUserCallback = callback
+ }
+
+ override fun setShadeEmptiedCallback(callback: Runnable) {
+ check(mShadeEmptiedCallback == null) { "mShadeEmptiedCallback already set" }
+ mShadeEmptiedCallback = callback
+ }
+
+ private fun onBeforeRenderList(entries: List<ListEntry>) {
+ if (mEntryRemoved && entries.isEmpty()) {
+ mLogger.logShadeEmptied()
+ mShadeEmptiedCallback?.run()
+ }
+ if (mEntryRemoved && mEntryRemovedByUser) {
+ mLogger.logNotifRemovedByUser()
+ mNotifRemovedByUserCallback?.run()
+ }
+ mEntryRemoved = false
+ mEntryRemovedByUser = false
+ }
+}
\ No newline at end of file
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/ShadeEventCoordinatorLogger.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/ShadeEventCoordinatorLogger.kt
new file mode 100644
index 0000000..c687e1b
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/ShadeEventCoordinatorLogger.kt
@@ -0,0 +1,38 @@
+/*
+ * Copyright (C) 2021 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.notification.collection.coordinator
+
+import com.android.systemui.log.LogBuffer
+import com.android.systemui.log.LogLevel
+import com.android.systemui.log.dagger.NotificationLog
+import javax.inject.Inject
+
+private const val TAG = "ShadeEventCoordinator"
+
+/** Logger for the [ShadeEventCoordinator] */
+class ShadeEventCoordinatorLogger @Inject constructor(
+ @NotificationLog private val buffer: LogBuffer
+) {
+
+ fun logShadeEmptied() {
+ buffer.log(TAG, LogLevel.DEBUG, { }, { "Shade emptied" })
+ }
+
+ fun logNotifRemovedByUser() {
+ buffer.log(TAG, LogLevel.DEBUG, { }, { "Notification removed by user" })
+ }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/SmartspaceDedupingCoordinator.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/SmartspaceDedupingCoordinator.kt
index 442d9d2..519d75f 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/SmartspaceDedupingCoordinator.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/SmartspaceDedupingCoordinator.kt
@@ -18,7 +18,6 @@
import android.app.smartspace.SmartspaceTarget
import android.os.Parcelable
-import com.android.systemui.dagger.SysUISingleton
import com.android.systemui.dagger.qualifiers.Main
import com.android.systemui.plugins.statusbar.StatusBarStateController
import com.android.systemui.statusbar.NotificationLockscreenUserManager
@@ -28,6 +27,7 @@
import com.android.systemui.statusbar.notification.NotificationEntryManager
import com.android.systemui.statusbar.notification.collection.NotifPipeline
import com.android.systemui.statusbar.notification.collection.NotificationEntry
+import com.android.systemui.statusbar.notification.collection.coordinator.dagger.CoordinatorScope
import com.android.systemui.statusbar.notification.collection.listbuilder.pluggable.NotifFilter
import com.android.systemui.statusbar.notification.collection.notifcollection.NotifCollectionListener
import com.android.systemui.util.concurrency.DelayableExecutor
@@ -45,7 +45,7 @@
*/
// This class is a singleton so that the same instance can be accessed by both the old and new
// pipelines
-@SysUISingleton
+@CoordinatorScope
class SmartspaceDedupingCoordinator @Inject constructor(
private val statusBarStateController: SysuiStatusBarStateController,
private val smartspaceController: LockscreenSmartspaceController,
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/ViewConfigCoordinator.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/ViewConfigCoordinator.kt
new file mode 100644
index 0000000..5b86de2
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/ViewConfigCoordinator.kt
@@ -0,0 +1,109 @@
+/*
+ * Copyright (C) 2021 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.notification.collection.coordinator
+
+import com.android.internal.widget.MessagingGroup
+import com.android.internal.widget.MessagingMessage
+import com.android.keyguard.KeyguardUpdateMonitor
+import com.android.systemui.flags.FeatureFlags
+import com.android.systemui.statusbar.NotificationLockscreenUserManager.UserChangedListener
+import com.android.systemui.statusbar.NotificationLockscreenUserManagerImpl
+import com.android.systemui.statusbar.notification.collection.NotifPipeline
+import com.android.systemui.statusbar.notification.collection.coordinator.dagger.CoordinatorScope
+import com.android.systemui.statusbar.notification.row.NotificationGutsManager
+import com.android.systemui.statusbar.policy.ConfigurationController
+import javax.inject.Inject
+
+/**
+ * A coordinator which ensures that notifications within the new pipeline are correctly inflated
+ * for the current uiMode and screen properties; additionally deferring those changes when a user
+ * change is in progress until that process has completed.
+ */
+@CoordinatorScope
+class ViewConfigCoordinator @Inject internal constructor(
+ configurationController: ConfigurationController,
+ lockscreenUserManager: NotificationLockscreenUserManagerImpl,
+ featureFlags: FeatureFlags,
+ private val mGutsManager: NotificationGutsManager,
+ private val mKeyguardUpdateMonitor: KeyguardUpdateMonitor
+) : Coordinator, UserChangedListener, ConfigurationController.ConfigurationListener {
+
+ private var mReinflateNotificationsOnUserSwitched = false
+ private var mDispatchUiModeChangeOnUserSwitched = false
+ private var mPipeline: NotifPipeline? = null
+
+ init {
+ if (featureFlags.isNewNotifPipelineRenderingEnabled) {
+ lockscreenUserManager.addUserChangedListener(this)
+ configurationController.addCallback(this)
+ }
+ }
+
+ override fun attach(pipeline: NotifPipeline) {
+ mPipeline = pipeline
+ }
+
+ override fun onDensityOrFontScaleChanged() {
+ MessagingMessage.dropCache()
+ MessagingGroup.dropCache()
+ if (!mKeyguardUpdateMonitor.isSwitchingUser) {
+ updateNotificationsOnDensityOrFontScaleChanged()
+ } else {
+ mReinflateNotificationsOnUserSwitched = true
+ }
+ }
+
+ override fun onUiModeChanged() {
+ if (!mKeyguardUpdateMonitor.isSwitchingUser) {
+ updateNotificationsOnUiModeChanged()
+ } else {
+ mDispatchUiModeChangeOnUserSwitched = true
+ }
+ }
+
+ override fun onThemeChanged() {
+ onDensityOrFontScaleChanged()
+ }
+
+ override fun onUserChanged(userId: Int) {
+ if (mReinflateNotificationsOnUserSwitched) {
+ updateNotificationsOnDensityOrFontScaleChanged()
+ mReinflateNotificationsOnUserSwitched = false
+ }
+ if (mDispatchUiModeChangeOnUserSwitched) {
+ updateNotificationsOnUiModeChanged()
+ mDispatchUiModeChangeOnUserSwitched = false
+ }
+ }
+
+ private fun updateNotificationsOnUiModeChanged() {
+ mPipeline?.allNotifs?.forEach { entry ->
+ val row = entry.row
+ row?.onUiModeChanged()
+ }
+ }
+
+ private fun updateNotificationsOnDensityOrFontScaleChanged() {
+ mPipeline?.allNotifs?.forEach { entry ->
+ entry.onDensityOrFontScaleChanged()
+ val exposedGuts = entry.areGutsExposed()
+ if (exposedGuts) {
+ mGutsManager.onDensityOrFontScaleChanged(entry)
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/VisualStabilityCoordinator.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/VisualStabilityCoordinator.java
index 5d6c043..5ba4c2f 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/VisualStabilityCoordinator.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/VisualStabilityCoordinator.java
@@ -50,6 +50,7 @@
* This is now integrated in the data-layer via
* {@link com.android.systemui.statusbar.notification.collection.ShadeListBuilder}.
*/
+// TODO(b/204468557): Move to @CoordinatorScope
@SysUISingleton
public class VisualStabilityCoordinator implements Coordinator {
private final DelayableExecutor mDelayableExecutor;
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/dagger/CoordinatorsModule.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/dagger/CoordinatorsModule.kt
new file mode 100644
index 0000000..7575a90
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/dagger/CoordinatorsModule.kt
@@ -0,0 +1,64 @@
+/*
+ * Copyright (C) 2021 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.notification.collection.coordinator.dagger
+
+import com.android.systemui.dagger.SysUISingleton
+import com.android.systemui.statusbar.notification.collection.coordinator.NotifCoordinators
+import com.android.systemui.statusbar.notification.collection.coordinator.NotifCoordinatorsImpl
+import com.android.systemui.statusbar.notification.collection.coordinator.SensitiveContentCoordinatorModule
+import dagger.Binds
+import dagger.Module
+import dagger.Provides
+import dagger.Subcomponent
+import javax.inject.Qualifier
+import javax.inject.Scope
+
+@Module(subcomponents = [CoordinatorsSubcomponent::class])
+object CoordinatorsModule {
+ @SysUISingleton
+ @Provides
+ fun notifCoordinators(factory: CoordinatorsSubcomponent.Factory): NotifCoordinators =
+ factory.create().notifCoordinators
+}
+
+@CoordinatorScope
+@Subcomponent(modules = [InternalCoordinatorsModule::class])
+interface CoordinatorsSubcomponent {
+ @get:Internal val notifCoordinators: NotifCoordinators
+
+ @Subcomponent.Factory
+ interface Factory {
+ fun create(): CoordinatorsSubcomponent
+ }
+}
+
+@Module(includes = [SensitiveContentCoordinatorModule::class])
+private abstract class InternalCoordinatorsModule {
+ @Binds
+ @Internal
+ abstract fun bindNotifCoordinators(impl: NotifCoordinatorsImpl): NotifCoordinators
+}
+
+@Qualifier
+@MustBeDocumented
+@Retention(AnnotationRetention.RUNTIME)
+private annotation class Internal
+
+@Scope
+@MustBeDocumented
+@Retention(AnnotationRetention.RUNTIME)
+annotation class CoordinatorScope
\ No newline at end of file
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/legacy/LegacyNotificationPresenterExtensions.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/legacy/LegacyNotificationPresenterExtensions.java
new file mode 100644
index 0000000..4ee08ed
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/legacy/LegacyNotificationPresenterExtensions.java
@@ -0,0 +1,100 @@
+/*
+ * Copyright (C) 2010 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.notification.collection.legacy;
+
+import static com.android.systemui.statusbar.phone.StatusBar.SPEW;
+
+import android.service.notification.StatusBarNotification;
+import android.util.Log;
+
+import androidx.annotation.NonNull;
+
+import com.android.internal.statusbar.NotificationVisibility;
+import com.android.systemui.statusbar.notification.NotificationEntryListener;
+import com.android.systemui.statusbar.notification.NotificationEntryManager;
+import com.android.systemui.statusbar.notification.collection.NotificationEntry;
+import com.android.systemui.statusbar.notification.collection.render.NotifShadeEventSource;
+
+import org.jetbrains.annotations.NotNull;
+
+import javax.inject.Inject;
+
+/**
+ * This is some logic extracted from the
+ * {@link com.android.systemui.statusbar.phone.StatusBarNotificationPresenter}
+ * into a class that implements a new-pipeline interface so that the new pipeline can implement it
+ * correctly.
+ *
+ * Specifically, this is the logic which updates notifications when uiMode and screen properties
+ * change, and which closes the shade when the last notification disappears.
+ */
+public class LegacyNotificationPresenterExtensions implements NotifShadeEventSource {
+ private static final String TAG = "LegacyNotifPresenter";
+ private final NotificationEntryManager mEntryManager;
+ private boolean mEntryListenerAdded;
+ private Runnable mShadeEmptiedCallback;
+ private Runnable mNotifRemovedByUserCallback;
+
+ @Inject
+ public LegacyNotificationPresenterExtensions(NotificationEntryManager entryManager) {
+ mEntryManager = entryManager;
+ }
+
+ private void ensureEntryListenerAdded() {
+ if (mEntryListenerAdded) return;
+ mEntryListenerAdded = true;
+ mEntryManager.addNotificationEntryListener(new NotificationEntryListener() {
+ @Override
+ public void onEntryRemoved(
+ @NotNull NotificationEntry entry,
+ NotificationVisibility visibility,
+ boolean removedByUser,
+ int reason) {
+ StatusBarNotification old = entry.getSbn();
+ if (SPEW) {
+ Log.d(TAG, "removeNotification key=" + entry.getKey()
+ + " old=" + old + " reason=" + reason);
+ }
+
+ if (old != null && !mEntryManager.hasActiveNotifications()) {
+ if (mShadeEmptiedCallback != null) mShadeEmptiedCallback.run();
+ }
+ if (removedByUser) {
+ if (mNotifRemovedByUserCallback != null) mNotifRemovedByUserCallback.run();
+ }
+ }
+ });
+ }
+
+ @Override
+ public void setNotifRemovedByUserCallback(@NonNull Runnable callback) {
+ if (mNotifRemovedByUserCallback != null) {
+ throw new IllegalStateException("mNotifRemovedByUserCallback already set");
+ }
+ mNotifRemovedByUserCallback = callback;
+ ensureEntryListenerAdded();
+ }
+
+ @Override
+ public void setShadeEmptiedCallback(@NonNull Runnable callback) {
+ if (mShadeEmptiedCallback != null) {
+ throw new IllegalStateException("mShadeEmptiedCallback already set");
+ }
+ mShadeEmptiedCallback = callback;
+ ensureEntryListenerAdded();
+ }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/listbuilder/ShadeListBuilderLogger.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/listbuilder/ShadeListBuilderLogger.kt
index 5a35127..8fff905 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/listbuilder/ShadeListBuilderLogger.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/listbuilder/ShadeListBuilderLogger.kt
@@ -47,6 +47,15 @@
})
}
+ fun logPreRenderInvalidated(filterName: String, pipelineState: Int) {
+ buffer.log(TAG, DEBUG, {
+ str1 = filterName
+ int1 = pipelineState
+ }, {
+ """Pre-render Invalidator "$str1" invalidated; pipeline state is $int1"""
+ })
+ }
+
fun logPreGroupFilterInvalidated(filterName: String, pipelineState: Int) {
buffer.log(TAG, DEBUG, {
str1 = filterName
diff --git a/core/java/android/companion/Association.aidl b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/listbuilder/pluggable/Invalidator.java
similarity index 62%
copy from core/java/android/companion/Association.aidl
copy to packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/listbuilder/pluggable/Invalidator.java
index 2a28f1f..d7092ec 100644
--- a/core/java/android/companion/Association.aidl
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/listbuilder/pluggable/Invalidator.java
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2019 The Android Open Source Project
+ * Copyright (C) 2021 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.
@@ -13,6 +13,12 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-package android.companion;
-parcelable Association;
+package com.android.systemui.statusbar.notification.collection.listbuilder.pluggable;
+
+/** A {@link Pluggable} that can only invalidate. */
+public abstract class Invalidator extends Pluggable<Invalidator> {
+ protected Invalidator(String name) {
+ super(name);
+ }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/notifcollection/InternalNotifUpdater.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/notifcollection/InternalNotifUpdater.java
new file mode 100644
index 0000000..5692fb2
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/notifcollection/InternalNotifUpdater.java
@@ -0,0 +1,37 @@
+/*
+ * Copyright (C) 2021 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.notification.collection.notifcollection;
+
+import android.service.notification.StatusBarNotification;
+
+/**
+ * An object that allows Coordinators to update notifications internally to SystemUI.
+ * This is used when part of the UI involves updating the underlying appearance of a notification
+ * on behalf of an app, such as to add a spinner or remote input history.
+ */
+public interface InternalNotifUpdater {
+ /**
+ * Called when an already-existing notification needs to be updated to a new temporary
+ * appearance.
+ * This update is local to the SystemUI process.
+ * This has no effect if no notification with the given key exists in the pipeline.
+ *
+ * @param sbn a notification to update
+ * @param reason a debug reason for the update
+ */
+ void onInternalNotificationUpdate(StatusBarNotification sbn, String reason);
+}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/notifcollection/NotifCollectionListener.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/notifcollection/NotifCollectionListener.java
index db0c174..68a346f 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/notifcollection/NotifCollectionListener.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/notifcollection/NotifCollectionListener.java
@@ -56,6 +56,17 @@
/**
* Called whenever a notification with the same key as an existing notification is posted. By
* the time this listener is called, the entry's SBN and Ranking will already have been updated.
+ * This delegates to {@link #onEntryUpdated(NotificationEntry)} by default.
+ * @param fromSystem If true, this update came from the NotificationManagerService.
+ * If false, the notification update is an internal change within systemui.
+ */
+ default void onEntryUpdated(@NonNull NotificationEntry entry, boolean fromSystem) {
+ onEntryUpdated(entry);
+ }
+
+ /**
+ * Called whenever a notification with the same key as an existing notification is posted. By
+ * the time this listener is called, the entry's SBN and Ranking will already have been updated.
*/
default void onEntryUpdated(@NonNull NotificationEntry entry) {
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/notifcollection/NotifCollectionLogger.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/notifcollection/NotifCollectionLogger.kt
index f8a778d..1ebc66e 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/notifcollection/NotifCollectionLogger.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/notifcollection/NotifCollectionLogger.kt
@@ -121,6 +121,26 @@
})
}
+ fun logNotifInternalUpdate(key: String, name: String, reason: String) {
+ buffer.log(TAG, INFO, {
+ str1 = key
+ str2 = name
+ str3 = reason
+ }, {
+ "UPDATED INTERNALLY $str1 BY $str2 BECAUSE $str3"
+ })
+ }
+
+ fun logNotifInternalUpdateFailed(key: String, name: String, reason: String) {
+ buffer.log(TAG, INFO, {
+ str1 = key
+ str2 = name
+ str3 = reason
+ }, {
+ "FAILED INTERNAL UPDATE $str1 BY $str2 BECAUSE $str3"
+ })
+ }
+
fun logNoNotificationToRemoveWithKey(key: String) {
buffer.log(TAG, ERROR, {
str1 = key
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/notifcollection/NotifEvent.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/notifcollection/NotifEvent.kt
index 2810b89..179e953 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/notifcollection/NotifEvent.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/notifcollection/NotifEvent.kt
@@ -64,10 +64,11 @@
}
data class EntryUpdatedEvent(
- val entry: NotificationEntry
+ val entry: NotificationEntry,
+ val fromSystem: Boolean
) : NotifEvent() {
override fun dispatchToListener(listener: NotifCollectionListener) {
- listener.onEntryUpdated(entry)
+ listener.onEntryUpdated(entry, fromSystem)
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/notifcollection/SelfTrackingLifetimeExtender.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/notifcollection/SelfTrackingLifetimeExtender.kt
new file mode 100644
index 0000000..145c1e5
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/notifcollection/SelfTrackingLifetimeExtender.kt
@@ -0,0 +1,113 @@
+package com.android.systemui.statusbar.notification.collection.notifcollection
+
+import android.os.Handler
+import android.util.ArrayMap
+import android.util.Log
+import com.android.systemui.Dumpable
+import com.android.systemui.statusbar.notification.collection.NotificationEntry
+import java.io.FileDescriptor
+import java.io.PrintWriter
+
+/**
+ * A helpful class that implements the core contract of the lifetime extender internally,
+ * making it easier for coordinators to interact with them
+ */
+abstract class SelfTrackingLifetimeExtender(
+ private val tag: String,
+ private val name: String,
+ private val debug: Boolean,
+ private val mainHandler: Handler
+) : NotifLifetimeExtender, Dumpable {
+ private lateinit var mCallback: NotifLifetimeExtender.OnEndLifetimeExtensionCallback
+ protected val mEntriesExtended = ArrayMap<String, NotificationEntry>()
+ private var mEnding = false
+
+ /**
+ * When debugging, warn if the call is happening during and "end lifetime extension" call.
+ *
+ * Note: this will warn a lot! The pipeline explicitly re-invokes all lifetime extenders
+ * whenever one ends, giving all of them a chance to re-up their lifetime extension.
+ */
+ private fun warnIfEnding() {
+ if (debug && mEnding) Log.w(tag, "reentrant code while ending a lifetime extension")
+ }
+
+ fun endAllLifetimeExtensions() {
+ // clear the map before iterating over a copy of the items, because the pipeline will
+ // always give us another chance to extend the lifetime again, and we don't want
+ // concurrent modification
+ val entries = mEntriesExtended.values.toList()
+ if (debug) Log.d(tag, "$name.endAllLifetimeExtensions() entries=$entries")
+ mEntriesExtended.clear()
+ warnIfEnding()
+ mEnding = true
+ entries.forEach { mCallback.onEndLifetimeExtension(this, it) }
+ mEnding = false
+ }
+
+ fun endLifetimeExtensionAfterDelay(key: String, delayMillis: Long) {
+ if (debug) {
+ Log.d(tag, "$name.endLifetimeExtensionAfterDelay" +
+ "(key=$key, delayMillis=$delayMillis)" +
+ " isExtending=${isExtending(key)}")
+ }
+ if (isExtending(key)) {
+ mainHandler.postDelayed({ endLifetimeExtension(key) }, delayMillis)
+ }
+ }
+
+ fun endLifetimeExtension(key: String) {
+ if (debug) {
+ Log.d(tag, "$name.endLifetimeExtension(key=$key)" +
+ " isExtending=${isExtending(key)}")
+ }
+ warnIfEnding()
+ mEnding = true
+ mEntriesExtended.remove(key)?.let { removedEntry ->
+ mCallback.onEndLifetimeExtension(this, removedEntry)
+ }
+ mEnding = false
+ }
+
+ fun isExtending(key: String) = mEntriesExtended.contains(key)
+
+ final override fun getName(): String = name
+
+ final override fun shouldExtendLifetime(entry: NotificationEntry, reason: Int): Boolean {
+ val shouldExtend = queryShouldExtendLifetime(entry)
+ if (debug) {
+ Log.d(tag, "$name.shouldExtendLifetime(key=${entry.key}, reason=$reason)" +
+ " isExtending=${isExtending(entry.key)}" +
+ " shouldExtend=$shouldExtend")
+ }
+ warnIfEnding()
+ if (shouldExtend && mEntriesExtended.put(entry.key, entry) == null) {
+ onStartedLifetimeExtension(entry)
+ }
+ return shouldExtend
+ }
+
+ final override fun cancelLifetimeExtension(entry: NotificationEntry) {
+ if (debug) {
+ Log.d(tag, "$name.cancelLifetimeExtension(key=${entry.key})" +
+ " isExtending=${isExtending(entry.key)}")
+ }
+ warnIfEnding()
+ mEntriesExtended.remove(entry.key)
+ onCanceledLifetimeExtension(entry)
+ }
+
+ abstract fun queryShouldExtendLifetime(entry: NotificationEntry): Boolean
+ open fun onStartedLifetimeExtension(entry: NotificationEntry) {}
+ open fun onCanceledLifetimeExtension(entry: NotificationEntry) {}
+
+ final override fun setCallback(callback: NotifLifetimeExtender.OnEndLifetimeExtensionCallback) {
+ mCallback = callback
+ }
+
+ final override fun dump(fd: FileDescriptor, pw: PrintWriter, args: Array<out String>) {
+ pw.println("LifetimeExtender: $name:")
+ pw.println(" mEntriesExtended: ${mEntriesExtended.size}")
+ mEntriesExtended.forEach { pw.println(" * ${it.key}") }
+ }
+}
\ No newline at end of file
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/render/NotifShadeEventSource.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/render/NotifShadeEventSource.kt
new file mode 100644
index 0000000..e24f6a0
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/render/NotifShadeEventSource.kt
@@ -0,0 +1,35 @@
+/*
+ * Copyright (C) 2021 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.notification.collection.render
+
+/**
+ * This is an object which provides callbacks for certain important events related to the
+ * notification shade, such as notifications being removed by the user, or the shade becoming empty.
+ */
+interface NotifShadeEventSource {
+ /**
+ * Registers a callback to be invoked when the last notification has been removed from
+ * the shade for any reason
+ */
+ fun setShadeEmptiedCallback(callback: Runnable)
+
+ /**
+ * Registers a callback to be invoked when a notification has been removed from
+ * the shade by a user action
+ */
+ fun setNotifRemovedByUserCallback(callback: Runnable)
+}
\ No newline at end of file
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/dagger/NotificationsModule.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/dagger/NotificationsModule.java
index dfa1f5f..1eb007e 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/dagger/NotificationsModule.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/dagger/NotificationsModule.java
@@ -45,10 +45,13 @@
import com.android.systemui.statusbar.notification.collection.NotifCollection;
import com.android.systemui.statusbar.notification.collection.NotifInflaterImpl;
import com.android.systemui.statusbar.notification.collection.NotifPipeline;
+import com.android.systemui.statusbar.notification.collection.coordinator.ShadeEventCoordinator;
import com.android.systemui.statusbar.notification.collection.coordinator.VisualStabilityCoordinator;
+import com.android.systemui.statusbar.notification.collection.coordinator.dagger.CoordinatorsModule;
import com.android.systemui.statusbar.notification.collection.inflation.NotifInflater;
import com.android.systemui.statusbar.notification.collection.inflation.NotificationRowBinder;
import com.android.systemui.statusbar.notification.collection.inflation.OnUserInteractionCallbackImpl;
+import com.android.systemui.statusbar.notification.collection.legacy.LegacyNotificationPresenterExtensions;
import com.android.systemui.statusbar.notification.collection.legacy.NotificationGroupManagerLegacy;
import com.android.systemui.statusbar.notification.collection.legacy.OnUserInteractionCallbackImplLegacy;
import com.android.systemui.statusbar.notification.collection.legacy.VisualStabilityManager;
@@ -59,6 +62,7 @@
import com.android.systemui.statusbar.notification.collection.render.GroupMembershipManager;
import com.android.systemui.statusbar.notification.collection.render.GroupMembershipManagerImpl;
import com.android.systemui.statusbar.notification.collection.render.NotifGutsViewManager;
+import com.android.systemui.statusbar.notification.collection.render.NotifShadeEventSource;
import com.android.systemui.statusbar.notification.init.NotificationsController;
import com.android.systemui.statusbar.notification.init.NotificationsControllerImpl;
import com.android.systemui.statusbar.notification.init.NotificationsControllerStub;
@@ -90,7 +94,10 @@
/**
* Dagger Module for classes found within the com.android.systemui.statusbar.notification package.
*/
-@Module(includes = { NotificationSectionHeadersModule.class })
+@Module(includes = {
+ NotificationSectionHeadersModule.class,
+ CoordinatorsModule.class
+})
public interface NotificationsModule {
@Binds
StackScrollAlgorithm.SectionProvider bindSectionProvider(
@@ -271,6 +278,20 @@
}
/**
+ * Provide the active implementation for presenting notifications.
+ */
+ @Provides
+ @SysUISingleton
+ static NotifShadeEventSource provideNotifShadeEventSource(
+ FeatureFlags featureFlags,
+ Lazy<ShadeEventCoordinator> shadeEventCoordinatorLazy,
+ Lazy<LegacyNotificationPresenterExtensions> legacyNotificationPresenterExtensionsLazy) {
+ return featureFlags.isNewNotifPipelineRenderingEnabled()
+ ? shadeEventCoordinatorLazy.get()
+ : legacyNotificationPresenterExtensionsLazy.get();
+ }
+
+ /**
* Provide a dismissal callback that's triggered when a user manually dismissed a notification
* from the notification shade or it gets auto-cancelled by click.
*/
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ExpandableNotificationRow.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ExpandableNotificationRow.java
index e956046..02b1210 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ExpandableNotificationRow.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ExpandableNotificationRow.java
@@ -1249,6 +1249,7 @@
@Override
public void onConfigurationChanged(Configuration newConfig) {
+ super.onConfigurationChanged(newConfig);
if (mMenuRow != null && mMenuRow.getMenuView() != null) {
mMenuRow.onConfigurationChanged();
}
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 df91fa7..4795f08 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
@@ -71,6 +71,7 @@
import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.graphics.ColorUtils;
import com.android.internal.jank.InteractionJankMonitor;
+import com.android.internal.policy.SystemBarUtils;
import com.android.keyguard.KeyguardSliceView;
import com.android.settingslib.Utils;
import com.android.systemui.Dependency;
@@ -652,6 +653,10 @@
return 0f;
}
+ public float getNotificationSquishinessFraction() {
+ return mStackScrollAlgorithm.getNotificationSquishinessFraction(mAmbientState);
+ }
+
void reinflateViews() {
inflateFooterView();
inflateEmptyShadeView();
@@ -926,7 +931,7 @@
res.getDimensionPixelSize(R.dimen.notification_divider_height));
mMinTopOverScrollToEscape = res.getDimensionPixelSize(
R.dimen.min_top_overscroll_to_qs);
- mStatusBarHeight = res.getDimensionPixelSize(R.dimen.status_bar_height);
+ mStatusBarHeight = SystemBarUtils.getStatusBarHeight(mContext);
mBottomMargin = res.getDimensionPixelSize(R.dimen.notification_panel_margin_bottom);
mMinimumPaddings = res.getDimensionPixelSize(R.dimen.notification_side_paddings);
mQsTilePadding = res.getDimensionPixelOffset(R.dimen.qs_tile_margin_horizontal);
@@ -937,8 +942,7 @@
mCornerRadius = res.getDimensionPixelSize(R.dimen.notification_corner_radius);
mHeadsUpInset = mStatusBarHeight + res.getDimensionPixelSize(
R.dimen.heads_up_status_bar_padding);
- mQsScrollBoundaryPosition = res.getDimensionPixelSize(
- com.android.internal.R.dimen.quick_qs_offset_height);
+ mQsScrollBoundaryPosition = SystemBarUtils.getQuickQsOffsetHeight(mContext);
}
void updateSidePadding(int viewWidth) {
@@ -1696,7 +1700,7 @@
super.onConfigurationChanged(newConfig);
Resources res = getResources();
updateSplitNotificationShade();
- mStatusBarHeight = res.getDimensionPixelOffset(R.dimen.status_bar_height);
+ mStatusBarHeight = SystemBarUtils.getStatusBarHeight(mContext);
float densityScale = res.getDisplayMetrics().density;
mSwipeHelper.setDensityScale(densityScale);
float pagingTouchSlop = ViewConfiguration.get(getContext()).getScaledPagingTouchSlop();
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayoutController.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayoutController.java
index 09ab90e..8b8b64d 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayoutController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayoutController.java
@@ -811,8 +811,9 @@
return Unit.INSTANCE;
});
- // callback is invoked synchronously, updating mView immediately
+ // attach callback, and then call it to update mView immediately
mDeviceProvisionedController.addCallback(mDeviceProvisionedListener);
+ mDeviceProvisionedListener.onDeviceProvisionedChanged();
if (mView.isAttachedToWindow()) {
mOnAttachStateChangeListener.onViewAttachedToWindow(mView);
@@ -1078,6 +1079,10 @@
mView.setOnStackYChanged(onStackYChanged);
}
+ public float getNotificationSquishinessFraction() {
+ return mView.getNotificationSquishinessFraction();
+ }
+
public float calculateAppearFractionBypass() {
return mView.calculateAppearFractionBypass();
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/StackScrollAlgorithm.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/StackScrollAlgorithm.java
index 0accce8..015edb8 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/StackScrollAlgorithm.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/StackScrollAlgorithm.java
@@ -26,6 +26,7 @@
import androidx.annotation.VisibleForTesting;
+import com.android.internal.policy.SystemBarUtils;
import com.android.systemui.R;
import com.android.systemui.animation.ShadeInterpolation;
import com.android.systemui.statusbar.NotificationShelf;
@@ -77,7 +78,7 @@
R.dimen.notification_divider_height);
mCollapsedSize = res.getDimensionPixelSize(R.dimen.notification_min_height);
mClipNotificationScrollToTop = res.getBoolean(R.bool.config_clipNotificationScrollToTop);
- int statusBarHeight = res.getDimensionPixelSize(R.dimen.status_bar_height);
+ int statusBarHeight = SystemBarUtils.getStatusBarHeight(context);
mHeadsUpInset = statusBarHeight + res.getDimensionPixelSize(
R.dimen.heads_up_status_bar_padding);
mPinnedZTranslationExtra = res.getDimensionPixelSize(
@@ -109,6 +110,15 @@
getNotificationChildrenStates(algorithmState, ambientState);
}
+ /**
+ * How expanded or collapsed notifications are when pulling down the shade.
+ * @param ambientState Current ambient state.
+ * @return 0 when fully collapsed, 1 when expanded.
+ */
+ public float getNotificationSquishinessFraction(AmbientState ambientState) {
+ return getExpansionFractionWithoutShelf(mTempAlgorithmState, ambientState);
+ }
+
private void resetChildViewStates() {
int numChildren = mHostView.getChildCount();
for (int i = 0; i < numChildren; i++) {
@@ -363,7 +373,6 @@
final float stackHeight = ambientState.getStackHeight() - shelfHeight - scrimPadding;
final float stackEndHeight = ambientState.getStackEndHeight() - shelfHeight - scrimPadding;
-
return stackHeight / stackEndHeight;
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/HeadsUpManagerPhone.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/HeadsUpManagerPhone.java
index 5f402d0..c81196d 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/HeadsUpManagerPhone.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/HeadsUpManagerPhone.java
@@ -26,6 +26,7 @@
import androidx.collection.ArraySet;
import com.android.internal.annotations.VisibleForTesting;
+import com.android.internal.policy.SystemBarUtils;
import com.android.systemui.Dumpable;
import com.android.systemui.R;
import com.android.systemui.plugins.statusbar.StatusBarStateController;
@@ -137,9 +138,8 @@
private void updateResources() {
Resources resources = mContext.getResources();
- mHeadsUpInset =
- resources.getDimensionPixelSize(com.android.internal.R.dimen.status_bar_height)
- + resources.getDimensionPixelSize(R.dimen.heads_up_status_bar_padding);
+ mHeadsUpInset = SystemBarUtils.getStatusBarHeight(mContext)
+ + resources.getDimensionPixelSize(R.dimen.heads_up_status_bar_padding);
}
///////////////////////////////////////////////////////////////////////////////////////////////
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBottomAreaView.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBottomAreaView.java
index c639eec..e26f75f 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBottomAreaView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBottomAreaView.java
@@ -1078,10 +1078,14 @@
.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP | Intent.FLAG_ACTIVITY_NEW_TASK)
.putExtra(ControlsUiController.EXTRA_ANIMATE, true);
+ ActivityLaunchAnimator.Controller controller =
+ v != null ? ActivityLaunchAnimator.Controller.fromView(v, null /* cujType */)
+ : null;
if (mControlsComponent.getVisibility() == AVAILABLE) {
- mContext.startActivity(intent);
+ mActivityStarter.startActivity(intent, true /* dismissShade */, controller,
+ true /* showOverLockscreenWhenLocked */);
} else {
- mActivityStarter.postStartActivityDismissingKeyguard(intent, 0 /* delay */);
+ mActivityStarter.postStartActivityDismissingKeyguard(intent, 0 /* delay */, controller);
}
}
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 7abe9bf..353868b 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBouncer.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBouncer.java
@@ -30,6 +30,7 @@
import android.view.ViewGroup;
import android.view.WindowInsets;
+import com.android.internal.policy.SystemBarUtils;
import com.android.keyguard.KeyguardHostViewController;
import com.android.keyguard.KeyguardRootViewController;
import com.android.keyguard.KeyguardSecurityModel;
@@ -468,8 +469,7 @@
mKeyguardViewController.init();
mContainer.addView(mRoot, mContainer.getChildCount());
- mStatusBarHeight = mRoot.getResources().getDimensionPixelOffset(
- com.android.systemui.R.dimen.status_bar_height);
+ mStatusBarHeight = SystemBarUtils.getStatusBarHeight(mContext);
setVisibility(View.INVISIBLE);
final WindowInsets rootInsets = mRoot.getRootWindowInsets();
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardClockPositionAlgorithm.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardClockPositionAlgorithm.java
index e368aad..4f3bbdb 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardClockPositionAlgorithm.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardClockPositionAlgorithm.java
@@ -195,12 +195,21 @@
1.0f /* panelExpansion */, 1.0f /* darkAmount */);
result.clockAlpha = getClockAlpha(y);
result.stackScrollerPadding = getStackScrollerPadding(y);
- result.stackScrollerPaddingExpanded = mBypassEnabled ? mUnlockedStackScrollerPadding
- : getClockY(1.0f, mDarkAmount) + mKeyguardStatusHeight;
+ result.stackScrollerPaddingExpanded = getStackScrollerPaddingExpanded();
result.clockX = (int) interpolate(0, burnInPreventionOffsetX(), mDarkAmount);
result.clockScale = interpolate(getBurnInScale(), 1.0f, 1.0f - mDarkAmount);
}
+ private int getStackScrollerPaddingExpanded() {
+ if (mBypassEnabled) {
+ return mUnlockedStackScrollerPadding;
+ } else if (mIsSplitShade) {
+ return getClockY(1.0f, mDarkAmount);
+ } else {
+ return getClockY(1.0f, mDarkAmount) + mKeyguardStatusHeight;
+ }
+ }
+
private int getStackScrollerPadding(int clockYPosition) {
if (mBypassEnabled) {
return (int) (mUnlockedStackScrollerPadding + mOverStretchAmount);
@@ -212,8 +221,13 @@
}
public float getMinStackScrollerPadding() {
- return mBypassEnabled ? mUnlockedStackScrollerPadding
- : mMinTopMargin + mKeyguardStatusHeight;
+ if (mBypassEnabled) {
+ return mUnlockedStackScrollerPadding;
+ } else if (mIsSplitShade) {
+ return mMinTopMargin;
+ } else {
+ return mMinTopMargin + mKeyguardStatusHeight;
+ }
}
private int getExpandedPreferredClockY() {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardStatusBarView.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardStatusBarView.java
index fe154d2..03f3b0c 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardStatusBarView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardStatusBarView.java
@@ -18,6 +18,7 @@
import static com.android.systemui.DejankUtils.whitelistIpcs;
import static com.android.systemui.ScreenDecorations.DisplayCutoutView.boundsFromDirection;
+import static com.android.systemui.util.Utils.getStatusBarHeaderHeightKeyguard;
import android.annotation.ColorInt;
import android.content.Context;
@@ -162,11 +163,8 @@
}
private void updateKeyguardStatusBarHeight() {
- final int waterfallTop =
- mDisplayCutout == null ? 0 : mDisplayCutout.getWaterfallInsets().top;
MarginLayoutParams lp = (MarginLayoutParams) getLayoutParams();
- lp.height = getResources().getDimensionPixelSize(
- R.dimen.status_bar_header_height_keyguard) + waterfallTop;
+ lp.height = getStatusBarHeaderHeightKeyguard(mContext);
setLayoutParams(lp);
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/LockscreenWallpaper.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/LockscreenWallpaper.java
index 2a13e6b..e565a44 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/LockscreenWallpaper.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/LockscreenWallpaper.java
@@ -45,7 +45,6 @@
import com.android.systemui.dagger.SysUISingleton;
import com.android.systemui.dagger.qualifiers.Main;
import com.android.systemui.dump.DumpManager;
-import com.android.systemui.keyguard.FaceAuthScreenBrightnessController;
import com.android.systemui.statusbar.NotificationMediaManager;
import libcore.io.IoUtils;
@@ -53,7 +52,6 @@
import java.io.FileDescriptor;
import java.io.PrintWriter;
import java.util.Objects;
-import java.util.Optional;
import javax.inject.Inject;
@@ -70,7 +68,6 @@
private final WallpaperManager mWallpaperManager;
private final KeyguardUpdateMonitor mUpdateMonitor;
private final Handler mH;
- private final Optional<FaceAuthScreenBrightnessController> mFaceAuthScreenBrightnessController;
private boolean mCached;
private Bitmap mCache;
@@ -86,14 +83,12 @@
KeyguardUpdateMonitor keyguardUpdateMonitor,
DumpManager dumpManager,
NotificationMediaManager mediaManager,
- Optional<FaceAuthScreenBrightnessController> faceAuthScreenBrightnessController,
@Main Handler mainHandler) {
dumpManager.registerDumpable(getClass().getSimpleName(), this);
mWallpaperManager = wallpaperManager;
mCurrentUserId = ActivityManager.getCurrentUser();
mUpdateMonitor = keyguardUpdateMonitor;
mMediaManager = mediaManager;
- mFaceAuthScreenBrightnessController = faceAuthScreenBrightnessController;
mH = mainHandler;
if (iWallpaperManager != null) {
@@ -132,14 +127,6 @@
return LoaderResult.success(null);
}
- Bitmap faceAuthWallpaper = null;
- if (mFaceAuthScreenBrightnessController.isPresent()) {
- faceAuthWallpaper = mFaceAuthScreenBrightnessController.get().getFaceAuthWallpaper();
- if (faceAuthWallpaper != null) {
- return LoaderResult.success(faceAuthWallpaper);
- }
- }
-
// Prefer the selected user (when specified) over the current user for the FLAG_SET_LOCK
// wallpaper.
final int lockWallpaperUserId =
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelViewController.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelViewController.java
index 2e5cdec..4ce33b3 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelViewController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelViewController.java
@@ -95,6 +95,7 @@
import com.android.internal.logging.MetricsLogger;
import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
import com.android.internal.policy.ScreenDecorationsUtils;
+import com.android.internal.policy.SystemBarUtils;
import com.android.internal.util.LatencyTracker;
import com.android.keyguard.KeyguardStatusView;
import com.android.keyguard.KeyguardStatusViewController;
@@ -467,7 +468,6 @@
private boolean mPulsing;
private boolean mUserSetupComplete;
- private int mQsNotificationTopPadding;
private boolean mHideIconsDuringLaunchAnimation = true;
private int mStackScrollerMeasuringPass;
private ArrayList<Consumer<ExpandableNotificationRow>>
@@ -991,10 +991,8 @@
super.loadDimens();
mFlingAnimationUtils = mFlingAnimationUtilsBuilder.get()
.setMaxLengthSeconds(0.4f).build();
- mStatusBarMinHeight = mResources.getDimensionPixelSize(
- com.android.internal.R.dimen.status_bar_height);
- mStatusBarHeaderHeightKeyguard = mResources.getDimensionPixelSize(
- R.dimen.status_bar_header_height_keyguard);
+ mStatusBarMinHeight = SystemBarUtils.getStatusBarHeight(mView.getContext());
+ mStatusBarHeaderHeightKeyguard = Utils.getStatusBarHeaderHeightKeyguard(mView.getContext());
mQsPeekHeight = mResources.getDimensionPixelSize(R.dimen.qs_peek_height);
mClockPositionAlgorithm.loadDimens(mResources);
mQsFalsingThreshold = mResources.getDimensionPixelSize(R.dimen.qs_falsing_threshold);
@@ -1004,8 +1002,7 @@
R.dimen.keyguard_indication_bottom_padding);
mShelfHeight = mResources.getDimensionPixelSize(R.dimen.notification_shelf_height);
mDarkIconSize = mResources.getDimensionPixelSize(R.dimen.status_bar_icon_drawing_size_dark);
- int statusbarHeight = mResources.getDimensionPixelSize(
- com.android.internal.R.dimen.status_bar_height);
+ int statusbarHeight = SystemBarUtils.getStatusBarHeight(mView.getContext());
mHeadsUpInset = statusbarHeight + mResources.getDimensionPixelSize(
R.dimen.heads_up_status_bar_padding);
mDistanceForQSFullShadeTransition = mResources.getDimensionPixelSize(
@@ -1080,10 +1077,8 @@
}
public void updateResources() {
- mQuickQsOffsetHeight = mResources.getDimensionPixelSize(
- com.android.internal.R.dimen.quick_qs_offset_height);
- mSplitShadeStatusBarHeight =
- mResources.getDimensionPixelSize(R.dimen.split_shade_header_height);
+ mQuickQsOffsetHeight = SystemBarUtils.getQuickQsOffsetHeight(mView.getContext());
+ mSplitShadeStatusBarHeight = Utils.getSplitShadeStatusBarHeight(mView.getContext());
int qsWidth = mResources.getDimensionPixelSize(R.dimen.qs_panel_width);
int panelWidth = mResources.getDimensionPixelSize(R.dimen.notification_panel_width);
mShouldUseSplitNotificationShade =
@@ -1110,6 +1105,7 @@
constraintSet.connect(
R.id.notification_stack_scroller, START,
R.id.qs_edge_guideline, START);
+ constraintSet.constrainHeight(R.id.split_shade_status_bar, mSplitShadeStatusBarHeight);
} else {
constraintSet.connect(R.id.qs_frame, END, PARENT_ID, END);
constraintSet.connect(R.id.notification_stack_scroller, START, PARENT_ID, START);
@@ -2363,7 +2359,8 @@
private void updateQsExpansion() {
if (mQs == null) return;
float qsExpansionFraction = computeQsExpansionFraction();
- mQs.setQsExpansion(qsExpansionFraction, getExpandedFraction(), getHeaderTranslation());
+ mQs.setQsExpansion(qsExpansionFraction, getExpandedFraction(), getHeaderTranslation(),
+ mNotificationStackScrollLayoutController.getNotificationSquishinessFraction());
mMediaHierarchyManager.setQsExpansion(qsExpansionFraction);
int qsPanelBottomY = calculateQsBottomPosition(qsExpansionFraction);
mScrimController.setQsPosition(qsExpansionFraction, qsPanelBottomY);
@@ -2525,7 +2522,7 @@
// qsTranslation should only be positive during pulse expansion because it's
// already translating in from the top
qsTranslation = Math.max(0, (top - mQs.getHeader().getHeight()) / 2.0f);
- } else {
+ } else if (!mShouldUseSplitNotificationShade) {
qsTranslation = (top - mQs.getHeader().getHeight()) * QS_PARALLAX_AMOUNT;
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarView.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarView.java
index 06a31c9..883313b 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarView.java
@@ -35,6 +35,7 @@
import android.view.accessibility.AccessibilityEvent;
import android.widget.LinearLayout;
+import com.android.internal.policy.SystemBarUtils;
import com.android.systemui.Dependency;
import com.android.systemui.R;
import com.android.systemui.plugins.DarkIconDispatcher;
@@ -223,7 +224,7 @@
final int waterfallTopInset =
mDisplayCutout == null ? 0 : mDisplayCutout.getWaterfallInsets().top;
ViewGroup.LayoutParams layoutParams = getLayoutParams();
- mStatusBarHeight = getResources().getDimensionPixelSize(R.dimen.status_bar_height);
+ mStatusBarHeight = SystemBarUtils.getStatusBarHeight(mContext);
layoutParams.height = mStatusBarHeight - waterfallTopInset;
int statusBarPaddingTop = getResources().getDimensionPixelSize(
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/SplitShadeHeaderController.kt b/packages/SystemUI/src/com/android/systemui/statusbar/phone/SplitShadeHeaderController.kt
index a7ecd06..8732891 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/SplitShadeHeaderController.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/SplitShadeHeaderController.kt
@@ -41,15 +41,28 @@
private val iconManager: StatusBarIconController.IconManager
private val qsCarrierGroupController: QSCarrierGroupController
private var visible = false
+ set(value) {
+ if (field == value) {
+ return
+ }
+ field = value
+ updateListeners()
+ }
var shadeExpanded = false
set(value) {
+ if (field == value) {
+ return
+ }
field = value
updateVisibility()
}
var splitShadeMode = false
set(value) {
+ if (field == value) {
+ return
+ }
field = value
updateVisibility()
}
@@ -78,15 +91,20 @@
}
private fun updateVisibility() {
- val shouldBeVisible = shadeExpanded && splitShadeMode
- if (visible != shouldBeVisible) {
- visible = shouldBeVisible
- statusBar.visibility = if (shouldBeVisible) View.VISIBLE else View.GONE
- updateListeners(shouldBeVisible)
+ val visibility = if (!splitShadeMode) {
+ View.GONE
+ } else if (shadeExpanded) {
+ View.VISIBLE
+ } else {
+ View.INVISIBLE
+ }
+ if (statusBar.visibility != visibility) {
+ statusBar.visibility = visibility
+ visible = visibility == View.VISIBLE
}
}
- private fun updateListeners(visible: Boolean) {
+ private fun updateListeners() {
qsCarrierGroupController.setListening(visible)
if (visible) {
statusBarIconController.addIconGroup(iconManager)
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java
index 0e75a45..9e4ac49 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java
@@ -174,7 +174,7 @@
import com.android.systemui.qs.QSPanelController;
import com.android.systemui.recents.ScreenPinningRequest;
import com.android.systemui.scrim.ScrimView;
-import com.android.systemui.settings.brightness.BrightnessSlider;
+import com.android.systemui.settings.brightness.BrightnessSliderController;
import com.android.systemui.shared.plugins.PluginManager;
import com.android.systemui.statusbar.AutoHideUiElement;
import com.android.systemui.statusbar.BackDropView;
@@ -207,6 +207,7 @@
import com.android.systemui.statusbar.notification.NotificationLaunchAnimatorControllerProvider;
import com.android.systemui.statusbar.notification.NotificationWakeUpCoordinator;
import com.android.systemui.statusbar.notification.collection.legacy.VisualStabilityManager;
+import com.android.systemui.statusbar.notification.collection.render.NotifShadeEventSource;
import com.android.systemui.statusbar.notification.init.NotificationsController;
import com.android.systemui.statusbar.notification.interruption.BypassHeadsUpNotifier;
import com.android.systemui.statusbar.notification.interruption.NotificationInterruptStateProvider;
@@ -535,13 +536,14 @@
private final int[] mAbsPos = new int[2];
+ private final NotifShadeEventSource mNotifShadeEventSource;
protected final NotificationEntryManager mEntryManager;
private final NotificationGutsManager mGutsManager;
private final NotificationLogger mNotificationLogger;
private final NotificationViewHierarchyManager mViewHierarchyManager;
private final KeyguardViewMediator mKeyguardViewMediator;
protected final NotificationInterruptStateProvider mNotificationInterruptStateProvider;
- private final BrightnessSlider.Factory mBrightnessSliderFactory;
+ private final BrightnessSliderController.Factory mBrightnessSliderFactory;
private final FeatureFlags mFeatureFlags;
private final UnfoldTransitionConfig mUnfoldTransitionConfig;
private final Lazy<UnfoldLightRevealOverlayAnimation> mUnfoldLightRevealOverlayAnimation;
@@ -718,6 +720,7 @@
FalsingManager falsingManager,
FalsingCollector falsingCollector,
BroadcastDispatcher broadcastDispatcher,
+ NotifShadeEventSource notifShadeEventSource,
NotificationEntryManager notificationEntryManager,
NotificationGutsManager notificationGutsManager,
NotificationLogger notificationLogger,
@@ -781,7 +784,7 @@
Lazy<NotificationShadeDepthController> notificationShadeDepthControllerLazy,
StatusBarTouchableRegionManager statusBarTouchableRegionManager,
NotificationIconAreaController notificationIconAreaController,
- BrightnessSlider.Factory brightnessSliderFactory,
+ BrightnessSliderController.Factory brightnessSliderFactory,
UnfoldTransitionConfig unfoldTransitionConfig,
Lazy<UnfoldLightRevealOverlayAnimation> unfoldLightRevealOverlayAnimation,
Lazy<UnfoldTransitionWallpaperController> unfoldTransitionWallpaperController,
@@ -823,6 +826,7 @@
mFalsingCollector = falsingCollector;
mFalsingManager = falsingManager;
mBroadcastDispatcher = broadcastDispatcher;
+ mNotifShadeEventSource = notifShadeEventSource;
mEntryManager = notificationEntryManager;
mGutsManager = notificationGutsManager;
mNotificationLogger = notificationLogger;
@@ -1506,6 +1510,7 @@
mDynamicPrivacyController,
mKeyguardStateController,
mKeyguardIndicationController,
+ mFeatureFlags,
this /* statusBar */,
mShadeController,
mLockscreenShadeTransitionController,
@@ -1513,6 +1518,7 @@
mViewHierarchyManager,
mLockscreenUserManager,
mStatusBarStateController,
+ mNotifShadeEventSource,
mEntryManager,
mMediaManager,
mGutsManager,
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarContentInsetsProvider.kt b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarContentInsetsProvider.kt
index 5bfb236..6ae8331 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarContentInsetsProvider.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarContentInsetsProvider.kt
@@ -25,6 +25,7 @@
import android.view.View.LAYOUT_DIRECTION_RTL
import android.view.WindowMetrics
import androidx.annotation.VisibleForTesting
+import com.android.internal.policy.SystemBarUtils
import com.android.systemui.Dumpable
import com.android.systemui.R
import com.android.systemui.dagger.SysUISingleton
@@ -155,18 +156,21 @@
val isRtl = rotatedResources.configuration.layoutDirection == LAYOUT_DIRECTION_RTL
val roundedCornerPadding = rotatedResources
.getDimensionPixelSize(R.dimen.rounded_corner_content_padding)
- val minDotWidth = if (isPrivacyDotEnabled)
+ val minDotPadding = if (isPrivacyDotEnabled)
rotatedResources.getDimensionPixelSize(R.dimen.ongoing_appops_dot_min_padding)
else 0
+ val dotWidth = if (isPrivacyDotEnabled)
+ rotatedResources.getDimensionPixelSize(R.dimen.ongoing_appops_dot_diameter)
+ else 0
val minLeft: Int
val minRight: Int
if (isRtl) {
- minLeft = max(minDotWidth, roundedCornerPadding)
+ minLeft = max(minDotPadding, roundedCornerPadding)
minRight = roundedCornerPadding
} else {
minLeft = roundedCornerPadding
- minRight = max(minDotWidth, roundedCornerPadding)
+ minRight = max(minDotPadding, roundedCornerPadding)
}
return calculateInsetsForRotationWithRotatedResources(
@@ -174,9 +178,11 @@
targetRotation,
dc,
context.resources.configuration.windowConfiguration.maxBounds,
- rotatedResources.getDimensionPixelSize(R.dimen.status_bar_height),
+ SystemBarUtils.getStatusBarHeight(context),
minLeft,
- minRight)
+ minRight,
+ isRtl,
+ dotWidth)
}
fun getStatusBarPaddingTop(@Rotation rotation: Int? = null): Int {
@@ -245,10 +251,13 @@
*
* @param currentRotation current device rotation
* @param targetRotation rotation for which to calculate the status bar content rect
- * @param displayCutout [DisplayCutout] for the curren display. possibly null
+ * @param displayCutout [DisplayCutout] for the current display. possibly null
* @param windowMetrics [WindowMetrics] for the current window
* @param statusBarHeight height of the status bar for the target rotation
- * @param roundedCornerPadding from rounded_corner_content_padding
+ * @param minLeft the minimum padding to enforce on the left
+ * @param minRight the minimum padding to enforce on the right
+ * @param isRtl current layout direction is Right-To-Left or not
+ * @param dotWidth privacy dot image width (0 if privacy dot is disabled)
*
* @see [RotationUtils#getResourcesForRotation]
*/
@@ -259,7 +268,9 @@
maxBounds: Rect,
statusBarHeight: Int,
minLeft: Int,
- minRight: Int
+ minRight: Int,
+ isRtl: Boolean,
+ dotWidth: Int
): Rect {
/*
TODO: Check if this is ever used for devices with no rounded corners
@@ -278,6 +289,8 @@
maxBounds.height(),
minLeft,
minRight,
+ isRtl,
+ dotWidth,
targetRotation,
currentRotation)
@@ -295,6 +308,8 @@
* @param cHeight display height in our current rotation
* @param minLeft the minimum padding to enforce on the left
* @param minRight the minimum padding to enforce on the right
+ * @param isRtl current layout direction is Right-To-Left or not
+ * @param dotWidth privacy dot image width (0 if privacy dot is disabled)
* @param targetRotation the rotation for which to calculate margins
* @param currentRotation the rotation from which the display cutout was generated
*
@@ -310,6 +325,8 @@
cHeight: Int,
minLeft: Int,
minRight: Int,
+ isRtl: Boolean,
+ dotWidth: Int,
@Rotation targetRotation: Int,
@Rotation currentRotation: Int
): Rect {
@@ -344,13 +361,16 @@
}
if (cutoutRect.touchesLeftEdge(relativeRotation, cWidth, cHeight)) {
-
- val l = max(minLeft, cutoutRect.logicalWidth(relativeRotation))
- leftMargin = max(l, leftMargin)
+ var logicalWidth = cutoutRect.logicalWidth(relativeRotation)
+ if (isRtl) logicalWidth += dotWidth
+ leftMargin = max(logicalWidth, leftMargin)
} else if (cutoutRect.touchesRightEdge(relativeRotation, cWidth, cHeight)) {
- val logicalWidth = cutoutRect.logicalWidth(relativeRotation)
- rightMargin = max(minRight, logicalWidth)
+ var logicalWidth = cutoutRect.logicalWidth(relativeRotation)
+ if (!isRtl) logicalWidth += dotWidth
+ rightMargin = max(rightMargin, logicalWidth)
}
+ // TODO(b/203626889): Fix the scenario when config_mainBuiltInDisplayCutoutRectApproximation
+ // is very close to but not directly touch edges.
}
return Rect(leftMargin, 0, logicalDisplayWidth - rightMargin, sbHeight)
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 07489a9..cac66a3 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManager.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManager.java
@@ -51,7 +51,6 @@
import com.android.systemui.DejankUtils;
import com.android.systemui.dagger.SysUISingleton;
import com.android.systemui.dock.DockManager;
-import com.android.systemui.keyguard.FaceAuthScreenBrightnessController;
import com.android.systemui.keyguard.WakefulnessLifecycle;
import com.android.systemui.navigationbar.NavigationBarView;
import com.android.systemui.navigationbar.NavigationModeController;
@@ -70,7 +69,6 @@
import java.io.PrintWriter;
import java.util.ArrayList;
import java.util.Objects;
-import java.util.Optional;
import javax.inject.Inject;
@@ -109,7 +107,6 @@
private final ConfigurationController mConfigurationController;
private final NavigationModeController mNavigationModeController;
private final NotificationShadeWindowController mNotificationShadeWindowController;
- private final Optional<FaceAuthScreenBrightnessController> mFaceAuthScreenBrightnessController;
private final KeyguardBouncer.Factory mKeyguardBouncerFactory;
private final WakefulnessLifecycle mWakefulnessLifecycle;
private final UnlockedScreenOffAnimationController mUnlockedScreenOffAnimationController;
@@ -242,7 +239,6 @@
DockManager dockManager,
NotificationShadeWindowController notificationShadeWindowController,
KeyguardStateController keyguardStateController,
- Optional<FaceAuthScreenBrightnessController> faceAuthScreenBrightnessController,
NotificationMediaManager notificationMediaManager,
KeyguardBouncer.Factory keyguardBouncerFactory,
WakefulnessLifecycle wakefulnessLifecycle,
@@ -260,7 +256,6 @@
mKeyguardUpdateManager = keyguardUpdateMonitor;
mStatusBarStateController = sysuiStatusBarStateController;
mDockManager = dockManager;
- mFaceAuthScreenBrightnessController = faceAuthScreenBrightnessController;
mKeyguardBouncerFactory = keyguardBouncerFactory;
mWakefulnessLifecycle = wakefulnessLifecycle;
mUnlockedScreenOffAnimationController = unlockedScreenOffAnimationController;
@@ -285,11 +280,6 @@
mNotificationContainer = notificationContainer;
mKeyguardMessageAreaController = mKeyguardMessageAreaFactory.create(
KeyguardMessageArea.findSecurityMessageDisplay(container));
- mFaceAuthScreenBrightnessController.ifPresent((it) -> {
- View overlay = new View(mContext);
- container.addView(overlay);
- it.attach(overlay);
- });
registerListeners();
}
@@ -917,7 +907,7 @@
@Override
public boolean bouncerIsOrWillBeShowing() {
- return mBouncer.isShowing() || mBouncer.getShowingSoon();
+ return isBouncerShowing() || mBouncer.getShowingSoon();
}
public boolean isFullscreenBouncer() {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarNotificationPresenter.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarNotificationPresenter.java
index c655964..ecd5c98 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarNotificationPresenter.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarNotificationPresenter.java
@@ -17,9 +17,7 @@
import static com.android.systemui.statusbar.phone.StatusBar.CLOSE_PANEL_WHEN_EMPTIED;
import static com.android.systemui.statusbar.phone.StatusBar.DEBUG;
import static com.android.systemui.statusbar.phone.StatusBar.MULTIUSER_DEBUG;
-import static com.android.systemui.statusbar.phone.StatusBar.SPEW;
-import android.annotation.Nullable;
import android.app.KeyguardManager;
import android.content.Context;
import android.os.RemoteException;
@@ -36,7 +34,6 @@
import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
import com.android.internal.statusbar.IStatusBarService;
-import com.android.internal.statusbar.NotificationVisibility;
import com.android.internal.widget.MessagingGroup;
import com.android.internal.widget.MessagingMessage;
import com.android.keyguard.KeyguardUpdateMonitor;
@@ -44,6 +41,7 @@
import com.android.systemui.ForegroundServiceNotificationListener;
import com.android.systemui.InitController;
import com.android.systemui.R;
+import com.android.systemui.flags.FeatureFlags;
import com.android.systemui.plugins.ActivityStarter;
import com.android.systemui.plugins.ActivityStarter.OnDismissAction;
import com.android.systemui.statusbar.CommandQueue;
@@ -59,10 +57,10 @@
import com.android.systemui.statusbar.SysuiStatusBarStateController;
import com.android.systemui.statusbar.notification.AboveShelfObserver;
import com.android.systemui.statusbar.notification.DynamicPrivacyController;
-import com.android.systemui.statusbar.notification.NotificationEntryListener;
import com.android.systemui.statusbar.notification.NotificationEntryManager;
import com.android.systemui.statusbar.notification.collection.NotificationEntry;
import com.android.systemui.statusbar.notification.collection.inflation.NotificationRowBinderImpl;
+import com.android.systemui.statusbar.notification.collection.render.NotifShadeEventSource;
import com.android.systemui.statusbar.notification.interruption.NotificationInterruptStateProvider;
import com.android.systemui.statusbar.notification.interruption.NotificationInterruptSuppressor;
import com.android.systemui.statusbar.notification.row.ActivatableNotificationView;
@@ -88,6 +86,7 @@
private final NotificationViewHierarchyManager mViewHierarchyManager;
private final NotificationLockscreenUserManager mLockscreenUserManager;
private final SysuiStatusBarStateController mStatusBarStateController;
+ private final NotifShadeEventSource mNotifShadeEventSource;
private final NotificationEntryManager mEntryManager;
private final NotificationMediaManager mMediaManager;
private final NotificationGutsManager mGutsManager;
@@ -100,6 +99,7 @@
private final DozeScrimController mDozeScrimController;
private final ScrimController mScrimController;
private final KeyguardIndicationController mKeyguardIndicationController;
+ private final FeatureFlags mFeatureFlags;
private final StatusBar mStatusBar;
private final ShadeController mShadeController;
private final LockscreenShadeTransitionController mShadeTransitionController;
@@ -127,6 +127,7 @@
DynamicPrivacyController dynamicPrivacyController,
KeyguardStateController keyguardStateController,
KeyguardIndicationController keyguardIndicationController,
+ FeatureFlags featureFlags,
StatusBar statusBar,
ShadeController shadeController,
LockscreenShadeTransitionController shadeTransitionController,
@@ -134,6 +135,7 @@
NotificationViewHierarchyManager notificationViewHierarchyManager,
NotificationLockscreenUserManager lockscreenUserManager,
SysuiStatusBarStateController sysuiStatusBarStateController,
+ NotifShadeEventSource notifShadeEventSource,
NotificationEntryManager notificationEntryManager,
NotificationMediaManager notificationMediaManager,
NotificationGutsManager notificationGutsManager,
@@ -148,6 +150,7 @@
mHeadsUpManager = headsUp;
mDynamicPrivacyController = dynamicPrivacyController;
mKeyguardIndicationController = keyguardIndicationController;
+ mFeatureFlags = featureFlags;
// TODO: use KeyguardStateController#isOccluded to remove this dependency
mStatusBar = statusBar;
mShadeController = shadeController;
@@ -156,6 +159,7 @@
mViewHierarchyManager = notificationViewHierarchyManager;
mLockscreenUserManager = lockscreenUserManager;
mStatusBarStateController = sysuiStatusBarStateController;
+ mNotifShadeEventSource = notifShadeEventSource;
mEntryManager = notificationEntryManager;
mMediaManager = notificationMediaManager;
mGutsManager = notificationGutsManager;
@@ -186,30 +190,18 @@
mNotificationPanel.createRemoteInputDelegate());
initController.addPostInitTask(() -> {
- NotificationEntryListener notificationEntryListener = new NotificationEntryListener() {
- @Override
- public void onEntryRemoved(
- @Nullable NotificationEntry entry,
- NotificationVisibility visibility,
- boolean removedByUser,
- int reason) {
- StatusBarNotificationPresenter.this.onNotificationRemoved(
- entry.getKey(), entry.getSbn(), reason);
- if (removedByUser) {
- maybeEndAmbientPulse();
- }
- }
- };
-
mKeyguardIndicationController.init();
mViewHierarchyManager.setUpWithPresenter(this,
stackScrollerController.getNotificationListContainer());
- mEntryManager.setUpWithPresenter(this);
- mEntryManager.addNotificationEntryListener(notificationEntryListener);
- mEntryManager.addNotificationLifetimeExtender(mHeadsUpManager);
- mEntryManager.addNotificationLifetimeExtender(mGutsManager);
- mEntryManager.addNotificationLifetimeExtenders(
- remoteInputManager.getLifetimeExtenders());
+ mNotifShadeEventSource.setShadeEmptiedCallback(this::maybeClosePanelForShadeEmptied);
+ mNotifShadeEventSource.setNotifRemovedByUserCallback(this::maybeEndAmbientPulse);
+ if (!mFeatureFlags.isNewNotifPipelineRenderingEnabled()) {
+ mEntryManager.setUpWithPresenter(this);
+ mEntryManager.addNotificationLifetimeExtender(mHeadsUpManager);
+ mEntryManager.addNotificationLifetimeExtender(mGutsManager);
+ mEntryManager.addNotificationLifetimeExtenders(
+ remoteInputManager.getLifetimeExtenders());
+ }
notificationInterruptStateProvider.addSuppressor(mInterruptSuppressor);
mLockscreenUserManager.setUpWithPresenter(this);
mMediaManager.setUpWithPresenter(this);
@@ -226,8 +218,21 @@
configurationController.addCallback(this);
}
+ /** Called when the shade has been emptied to attempt to close the shade */
+ private void maybeClosePanelForShadeEmptied() {
+ if (CLOSE_PANEL_WHEN_EMPTIED
+ && !mNotificationPanel.isTracking()
+ && !mNotificationPanel.isQsExpanded()
+ && mStatusBarStateController.getState() == StatusBarState.SHADE_LOCKED
+ && !isCollapsing()) {
+ mStatusBarStateController.setState(StatusBarState.KEYGUARD);
+ }
+ }
+
@Override
public void onDensityOrFontScaleChanged() {
+ // TODO(b/145659174): Remove legacy pipeline code
+ if (mFeatureFlags.isNewNotifPipelineRenderingEnabled()) return;
MessagingMessage.dropCache();
MessagingGroup.dropCache();
if (!mKeyguardUpdateMonitor.isSwitchingUser()) {
@@ -239,8 +244,10 @@
@Override
public void onUiModeChanged() {
+ // TODO(b/145659174): Remove legacy pipeline code
+ if (mFeatureFlags.isNewNotifPipelineRenderingEnabled()) return;
if (!mKeyguardUpdateMonitor.isSwitchingUser()) {
- updateNotificationOnUiModeChanged();
+ updateNotificationsOnUiModeChanged();
} else {
mDispatchUiModeChangeOnUserSwitched = true;
}
@@ -251,7 +258,9 @@
onDensityOrFontScaleChanged();
}
- private void updateNotificationOnUiModeChanged() {
+ private void updateNotificationsOnUiModeChanged() {
+ // TODO(b/145659174): Remove legacy pipeline code
+ if (mFeatureFlags.isNewNotifPipelineRenderingEnabled()) return;
List<NotificationEntry> userNotifications =
mEntryManager.getActiveNotificationsForCurrentUser();
for (int i = 0; i < userNotifications.size(); i++) {
@@ -264,6 +273,8 @@
}
private void updateNotificationsOnDensityOrFontScaleChanged() {
+ // TODO(b/145659174): Remove legacy pipeline code
+ if (mFeatureFlags.isNewNotifPipelineRenderingEnabled()) return;
List<NotificationEntry> userNotifications =
mEntryManager.getActiveNotificationsForCurrentUser();
for (int i = 0; i < userNotifications.size(); i++) {
@@ -276,6 +287,7 @@
}
}
+
@Override
public boolean isCollapsing() {
return mNotificationPanel.isCollapsing()
@@ -302,27 +314,10 @@
mShadeController.addPostCollapseAction(() -> updateNotificationViews(reason));
return;
}
-
mViewHierarchyManager.updateNotificationViews();
-
mNotificationPanel.updateNotificationViews(reason);
}
- private void onNotificationRemoved(String key, StatusBarNotification old, int reason) {
- if (SPEW) Log.d(TAG, "removeNotification key=" + key + " old=" + old);
-
- if (old != null && CLOSE_PANEL_WHEN_EMPTIED && !hasActiveNotifications()
- && !mNotificationPanel.isTracking() && !mNotificationPanel.isQsExpanded()
- && mStatusBarStateController.getState() == StatusBarState.SHADE_LOCKED
- && !isCollapsing()) {
- mStatusBarStateController.setState(StatusBarState.KEYGUARD);
- }
- }
-
- public boolean hasActiveNotifications() {
- return mEntryManager.hasActiveNotifications();
- }
-
@Override
public void onUserSwitched(int newUserId) {
// Begin old BaseStatusBar.userSwitched
@@ -335,7 +330,7 @@
mReinflateNotificationsOnUserSwitched = false;
}
if (mDispatchUiModeChangeOnUserSwitched) {
- updateNotificationOnUiModeChanged();
+ updateNotificationsOnUiModeChanged();
mDispatchUiModeChangeOnUserSwitched = false;
}
updateNotificationViews("user switched");
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarTouchableRegionManager.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarTouchableRegionManager.java
index eb405e9..b742394 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarTouchableRegionManager.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarTouchableRegionManager.java
@@ -29,6 +29,7 @@
import android.view.ViewTreeObserver.OnComputeInternalInsetsListener;
import android.view.WindowInsets;
+import com.android.internal.policy.SystemBarUtils;
import com.android.systemui.Dumpable;
import com.android.systemui.R;
import com.android.systemui.ScreenDecorations;
@@ -172,8 +173,7 @@
Resources resources = mContext.getResources();
mDisplayCutoutTouchableRegionSize = resources.getDimensionPixelSize(
com.android.internal.R.dimen.display_cutout_touchable_region_size);
- mStatusBarHeight =
- resources.getDimensionPixelSize(com.android.internal.R.dimen.status_bar_height);
+ mStatusBarHeight = SystemBarUtils.getStatusBarHeight(mContext);
}
/**
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarWindowController.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarWindowController.java
index 235a8e8..9d2dbc1 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarWindowController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarWindowController.java
@@ -40,6 +40,7 @@
import android.view.ViewGroup;
import android.view.WindowManager;
+import com.android.internal.policy.SystemBarUtils;
import com.android.systemui.R;
import com.android.systemui.dagger.SysUISingleton;
import com.android.systemui.dagger.qualifiers.Main;
@@ -86,8 +87,7 @@
mResources = resources;
if (mBarHeight < 0) {
- mBarHeight = mResources.getDimensionPixelSize(
- com.android.internal.R.dimen.status_bar_height);
+ mBarHeight = SystemBarUtils.getStatusBarHeight(mContext);
}
}
@@ -96,12 +96,11 @@
}
/**
- * Rereads the status_bar_height from configuration and reapplys the current state if the height
+ * Rereads the status bar height and reapplys the current state if the height
* is different.
*/
public void refreshStatusBarHeight() {
- int heightFromConfig = mResources.getDimensionPixelSize(
- com.android.internal.R.dimen.status_bar_height);
+ int heightFromConfig = SystemBarUtils.getStatusBarHeight(mContext);
if (mBarHeight != heightFromConfig) {
mBarHeight = heightFromConfig;
@@ -139,29 +138,20 @@
private WindowManager.LayoutParams getBarLayoutParamsForRotation(int rotation) {
int height = mBarHeight;
if (INSETS_LAYOUT_GENERALIZATION) {
- Rect displayBounds = mWindowManager.getCurrentWindowMetrics().getBounds();
- int defaultAndUpsideDownHeight;
- int theOtherHeight;
- if (displayBounds.width() > displayBounds.height()) {
- defaultAndUpsideDownHeight = mContext.getResources().getDimensionPixelSize(
- com.android.internal.R.dimen.status_bar_height_landscape);
- theOtherHeight = mContext.getResources().getDimensionPixelSize(
- com.android.internal.R.dimen.status_bar_height_portrait);
- } else {
- defaultAndUpsideDownHeight = mContext.getResources().getDimensionPixelSize(
- com.android.internal.R.dimen.status_bar_height_portrait);
- theOtherHeight = mContext.getResources().getDimensionPixelSize(
- com.android.internal.R.dimen.status_bar_height_landscape);
- }
switch (rotation) {
case ROTATION_UNDEFINED:
case Surface.ROTATION_0:
case Surface.ROTATION_180:
- height = defaultAndUpsideDownHeight;
+ height = SystemBarUtils.getStatusBarHeightForRotation(
+ mContext, Surface.ROTATION_0);
break;
case Surface.ROTATION_90:
+ height = SystemBarUtils.getStatusBarHeightForRotation(
+ mContext, Surface.ROTATION_90);
+ break;
case Surface.ROTATION_270:
- height = theOtherHeight;
+ height = SystemBarUtils.getStatusBarHeightForRotation(
+ mContext, Surface.ROTATION_270);
break;
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/SystemUIDialog.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/SystemUIDialog.java
index 9415d50..18aa689 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/SystemUIDialog.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/SystemUIDialog.java
@@ -22,7 +22,11 @@
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
+import android.os.Bundle;
+import android.os.SystemProperties;
import android.os.UserHandle;
+import android.util.TypedValue;
+import android.view.ViewGroup;
import android.view.Window;
import android.view.WindowInsets.Type;
import android.view.WindowManager;
@@ -45,6 +49,10 @@
* and dismisses itself when it receives the broadcast.
*/
public class SystemUIDialog extends AlertDialog implements ListenableDialog {
+ // TODO(b/203389579): Remove this once the dialog width on large screens has been agreed on.
+ private static final String FLAG_TABLET_DIALOG_WIDTH =
+ "persist.systemui.flag_tablet_dialog_width";
+
private final Context mContext;
private final DismissReceiver mDismissReceiver;
private final Set<DialogListener> mDialogListeners = new LinkedHashSet<>();
@@ -66,6 +74,41 @@
}
@Override
+ protected void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+
+ // Set the dialog window size.
+ getWindow().setLayout(getDialogWidth(), ViewGroup.LayoutParams.WRAP_CONTENT);
+ }
+
+ private int getDialogWidth() {
+ boolean isOnTablet =
+ mContext.getResources().getConfiguration().smallestScreenWidthDp >= 600;
+ if (!isOnTablet) {
+ return ViewGroup.LayoutParams.MATCH_PARENT;
+ }
+
+ int flagValue = SystemProperties.getInt(FLAG_TABLET_DIALOG_WIDTH, 0);
+ if (flagValue == -1) {
+ // The width of bottom sheets (624dp).
+ return Math.round(TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 624,
+ mContext.getResources().getDisplayMetrics()));
+ } else if (flagValue == -2) {
+ // The suggested small width for all dialogs (348dp)
+ return Math.round(TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 348,
+ mContext.getResources().getDisplayMetrics()));
+ } else if (flagValue > 0) {
+ // Any given width.
+ return Math.round(
+ TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, flagValue,
+ mContext.getResources().getDisplayMetrics()));
+ } else {
+ // By default we use the same width as the notification shade in portrait mode (504dp).
+ return mContext.getResources().getDimensionPixelSize(R.dimen.large_dialog_width);
+ }
+ }
+
+ @Override
protected void onStart() {
super.onStart();
mDismissReceiver.register();
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/UnlockedScreenOffAnimationController.kt b/packages/SystemUI/src/com/android/systemui/statusbar/phone/UnlockedScreenOffAnimationController.kt
index e2332e9..cddde64 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/UnlockedScreenOffAnimationController.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/UnlockedScreenOffAnimationController.kt
@@ -161,6 +161,8 @@
// Done going to sleep, reset this flag.
decidedToAnimateGoingToSleep = null
+ // We need to unset the listener. These are persistent for future animators
+ keyguardView.animate().setListener(null)
}
})
.start()
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/dagger/StatusBarPhoneModule.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/dagger/StatusBarPhoneModule.java
index c452a48..959c673 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/dagger/StatusBarPhoneModule.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/dagger/StatusBarPhoneModule.java
@@ -48,7 +48,7 @@
import com.android.systemui.plugins.FalsingManager;
import com.android.systemui.plugins.PluginDependencyProvider;
import com.android.systemui.recents.ScreenPinningRequest;
-import com.android.systemui.settings.brightness.BrightnessSlider;
+import com.android.systemui.settings.brightness.BrightnessSliderController;
import com.android.systemui.shared.plugins.PluginManager;
import com.android.systemui.statusbar.CommandQueue;
import com.android.systemui.statusbar.KeyguardIndicationController;
@@ -68,6 +68,7 @@
import com.android.systemui.statusbar.notification.NotificationEntryManager;
import com.android.systemui.statusbar.notification.NotificationWakeUpCoordinator;
import com.android.systemui.statusbar.notification.collection.legacy.VisualStabilityManager;
+import com.android.systemui.statusbar.notification.collection.render.NotifShadeEventSource;
import com.android.systemui.statusbar.notification.init.NotificationsController;
import com.android.systemui.statusbar.notification.interruption.BypassHeadsUpNotifier;
import com.android.systemui.statusbar.notification.interruption.NotificationInterruptStateProvider;
@@ -157,6 +158,7 @@
FalsingManager falsingManager,
FalsingCollector falsingCollector,
BroadcastDispatcher broadcastDispatcher,
+ NotifShadeEventSource notifShadeEventSource,
NotificationEntryManager notificationEntryManager,
NotificationGutsManager notificationGutsManager,
NotificationLogger notificationLogger,
@@ -220,7 +222,7 @@
Lazy<NotificationShadeDepthController> notificationShadeDepthController,
StatusBarTouchableRegionManager statusBarTouchableRegionManager,
NotificationIconAreaController notificationIconAreaController,
- BrightnessSlider.Factory brightnessSliderFactory,
+ BrightnessSliderController.Factory brightnessSliderFactory,
UnfoldTransitionConfig unfoldTransitionConfig,
Lazy<UnfoldLightRevealOverlayAnimation> unfoldLightRevealOverlayAnimation,
Lazy<NaturalRotationUnfoldProgressProvider> naturalRotationUnfoldProgressProvider,
@@ -260,6 +262,7 @@
falsingManager,
falsingCollector,
broadcastDispatcher,
+ notifShadeEventSource,
notificationEntryManager,
notificationGutsManager,
notificationLogger,
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/ongoingcall/OngoingCallController.kt b/packages/SystemUI/src/com/android/systemui/statusbar/phone/ongoingcall/OngoingCallController.kt
index 3806d9a..31cc823 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/ongoingcall/OngoingCallController.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/ongoingcall/OngoingCallController.kt
@@ -86,7 +86,7 @@
//
// TODO(b/183229367): Remove this function override when b/178406514 is fixed.
override fun onEntryAdded(entry: NotificationEntry) {
- onEntryUpdated(entry)
+ onEntryUpdated(entry, true)
}
override fun onEntryUpdated(entry: NotificationEntry) {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/BrightnessMirrorController.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/BrightnessMirrorController.java
index 1e52511..5bd20ff 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/BrightnessMirrorController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/BrightnessMirrorController.java
@@ -26,7 +26,7 @@
import android.widget.FrameLayout;
import com.android.systemui.R;
-import com.android.systemui.settings.brightness.BrightnessSlider;
+import com.android.systemui.settings.brightness.BrightnessSliderController;
import com.android.systemui.settings.brightness.ToggleSlider;
import com.android.systemui.statusbar.NotificationShadeDepthController;
import com.android.systemui.statusbar.phone.NotificationPanelViewController;
@@ -46,8 +46,8 @@
private final NotificationPanelViewController mNotificationPanel;
private final NotificationShadeDepthController mDepthController;
private final ArraySet<BrightnessMirrorListener> mBrightnessMirrorListeners = new ArraySet<>();
- private final BrightnessSlider.Factory mToggleSliderFactory;
- private BrightnessSlider mToggleSliderController;
+ private final BrightnessSliderController.Factory mToggleSliderFactory;
+ private BrightnessSliderController mToggleSliderController;
private final int[] mInt2Cache = new int[2];
private FrameLayout mBrightnessMirror;
private int mBrightnessMirrorBackgroundPadding;
@@ -56,7 +56,7 @@
public BrightnessMirrorController(NotificationShadeWindowView statusBarWindow,
NotificationPanelViewController notificationPanelViewController,
NotificationShadeDepthController notificationShadeDepthController,
- BrightnessSlider.Factory factory,
+ BrightnessSliderController.Factory factory,
@NonNull Consumer<Boolean> visibilityCallback) {
mStatusBarWindow = statusBarWindow;
mToggleSliderFactory = factory;
@@ -135,9 +135,10 @@
reinflate();
}
- private BrightnessSlider setMirrorLayout() {
+ private BrightnessSliderController setMirrorLayout() {
Context context = mBrightnessMirror.getContext();
- BrightnessSlider controller = mToggleSliderFactory.create(context, mBrightnessMirror);
+ BrightnessSliderController controller = mToggleSliderFactory.create(context,
+ mBrightnessMirror);
controller.init();
mBrightnessMirror.addView(controller.getRootView(), ViewGroup.LayoutParams.MATCH_PARENT,
diff --git a/packages/SystemUI/src/com/android/systemui/usb/UsbAccessoryUriActivity.java b/packages/SystemUI/src/com/android/systemui/usb/UsbAccessoryUriActivity.java
index 89297fd..d5d3efd 100644
--- a/packages/SystemUI/src/com/android/systemui/usb/UsbAccessoryUriActivity.java
+++ b/packages/SystemUI/src/com/android/systemui/usb/UsbAccessoryUriActivity.java
@@ -26,6 +26,7 @@
import android.os.Bundle;
import android.os.UserHandle;
import android.util.Log;
+import android.view.WindowManager;
import com.android.internal.app.AlertActivity;
import com.android.internal.app.AlertController;
@@ -47,6 +48,8 @@
@Override
public void onCreate(Bundle icicle) {
+ getWindow().addSystemFlags(
+ WindowManager.LayoutParams.SYSTEM_FLAG_HIDE_NON_SYSTEM_OVERLAY_WINDOWS);
super.onCreate(icicle);
Intent intent = getIntent();
diff --git a/packages/SystemUI/src/com/android/systemui/usb/UsbDebuggingSecondaryUserActivity.java b/packages/SystemUI/src/com/android/systemui/usb/UsbDebuggingSecondaryUserActivity.java
index 4850a02..2871263 100644
--- a/packages/SystemUI/src/com/android/systemui/usb/UsbDebuggingSecondaryUserActivity.java
+++ b/packages/SystemUI/src/com/android/systemui/usb/UsbDebuggingSecondaryUserActivity.java
@@ -30,6 +30,7 @@
import android.os.ServiceManager;
import android.os.SystemProperties;
import android.util.Log;
+import android.view.WindowManager;
import com.android.internal.app.AlertActivity;
import com.android.internal.app.AlertController;
@@ -51,6 +52,8 @@
@Override
public void onCreate(Bundle icicle) {
+ getWindow().addSystemFlags(
+ WindowManager.LayoutParams.SYSTEM_FLAG_HIDE_NON_SYSTEM_OVERLAY_WINDOWS);
super.onCreate(icicle);
if (SystemProperties.getInt("service.adb.tcp.port", 0) == 0) {
diff --git a/packages/SystemUI/src/com/android/systemui/usb/UsbResolverActivity.java b/packages/SystemUI/src/com/android/systemui/usb/UsbResolverActivity.java
index c420a6d..02a7637 100644
--- a/packages/SystemUI/src/com/android/systemui/usb/UsbResolverActivity.java
+++ b/packages/SystemUI/src/com/android/systemui/usb/UsbResolverActivity.java
@@ -33,6 +33,7 @@
import android.os.ServiceManager;
import android.os.UserHandle;
import android.util.Log;
+import android.view.WindowManager;
import android.widget.CheckBox;
import com.android.internal.app.ResolverActivity;
@@ -60,6 +61,8 @@
@Override
protected void onCreate(Bundle savedInstanceState) {
+ getWindow().addSystemFlags(
+ WindowManager.LayoutParams.SYSTEM_FLAG_HIDE_NON_SYSTEM_OVERLAY_WINDOWS);
Intent intent = getIntent();
Parcelable targetParcelable = intent.getParcelableExtra(Intent.EXTRA_INTENT);
if (!(targetParcelable instanceof Intent)) {
diff --git a/packages/SystemUI/src/com/android/systemui/util/Utils.java b/packages/SystemUI/src/com/android/systemui/util/Utils.java
index a1cdfd8..407dc5e 100644
--- a/packages/SystemUI/src/com/android/systemui/util/Utils.java
+++ b/packages/SystemUI/src/com/android/systemui/util/Utils.java
@@ -24,8 +24,10 @@
import android.content.res.TypedArray;
import android.provider.Settings;
import android.view.ContextThemeWrapper;
+import android.view.DisplayCutout;
import android.view.View;
+import com.android.internal.policy.SystemBarUtils;
import com.android.systemui.R;
import com.android.systemui.shared.system.QuickStepContract;
import com.android.systemui.statusbar.CommandQueue;
@@ -186,4 +188,39 @@
return color;
}
+ /**
+ * Gets the {@link R.dimen#split_shade_header_height}.
+ *
+ * Currently, it's the same as {@link com.android.internal.R.dimen#quick_qs_offset_height}.
+ */
+ public static int getSplitShadeStatusBarHeight(Context context) {
+ return SystemBarUtils.getQuickQsOffsetHeight(context);
+ }
+
+ /**
+ * Gets the {@link R.dimen#qs_header_system_icons_area_height}.
+ *
+ * It's the same as {@link com.android.internal.R.dimen#quick_qs_offset_height} except for
+ * sw600dp-land.
+ */
+ public static int getQsHeaderSystemIconsAreaHeight(Context context) {
+ final Resources res = context.getResources();
+ if (Utils.shouldUseSplitNotificationShade(res)) {
+ return res.getDimensionPixelSize(R.dimen.qs_header_system_icons_area_height);
+ } else {
+ return SystemBarUtils.getQuickQsOffsetHeight(context);
+ }
+ }
+
+ /**
+ * Gets the {@link R.dimen#status_bar_header_height_keyguard}.
+ */
+ public static int getStatusBarHeaderHeightKeyguard(Context context) {
+ final int statusBarHeight = SystemBarUtils.getStatusBarHeight(context);
+ final DisplayCutout cutout = context.getDisplay().getCutout();
+ final int waterfallInsetTop = cutout == null ? 0 : cutout.getWaterfallInsets().top;
+ final int statusBarHeaderHeightKeyguard = context.getResources()
+ .getDimensionPixelSize(R.dimen.status_bar_header_height_keyguard);
+ return Math.max(statusBarHeight, statusBarHeaderHeightKeyguard + waterfallInsetTop);
+ }
}
diff --git a/packages/SystemUI/src/com/android/systemui/util/sensors/ProximitySensorImpl.java b/packages/SystemUI/src/com/android/systemui/util/sensors/ProximitySensorImpl.java
index e639313a..5568f64 100644
--- a/packages/SystemUI/src/com/android/systemui/util/sensors/ProximitySensorImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/util/sensors/ProximitySensorImpl.java
@@ -17,6 +17,7 @@
package com.android.systemui.util.sensors;
import android.hardware.SensorManager;
+import android.os.Build;
import android.util.Log;
import com.android.internal.annotations.VisibleForTesting;
@@ -56,7 +57,7 @@
*/
class ProximitySensorImpl implements ProximitySensor {
private static final String TAG = "ProxSensor";
- private static final boolean DEBUG = Log.isLoggable(TAG, Log.DEBUG);
+ private static final boolean DEBUG = Log.isLoggable(TAG, Log.DEBUG) || Build.IS_DEBUGGABLE;
private static final long SECONDARY_PING_INTERVAL_MS = 5000;
ThresholdSensor mPrimaryThresholdSensor;
diff --git a/packages/SystemUI/src/com/android/systemui/util/service/ObservableServiceConnection.java b/packages/SystemUI/src/com/android/systemui/util/service/ObservableServiceConnection.java
new file mode 100644
index 0000000..bad0c37
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/util/service/ObservableServiceConnection.java
@@ -0,0 +1,259 @@
+/*
+ * Copyright (C) 2021 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.util.service;
+
+import android.annotation.CallbackExecutor;
+import android.annotation.IntDef;
+import android.annotation.NonNull;
+import android.content.ComponentName;
+import android.content.Context;
+import android.content.Intent;
+import android.content.ServiceConnection;
+import android.os.IBinder;
+import android.util.Log;
+
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.ref.WeakReference;
+import java.util.ArrayList;
+import java.util.Iterator;
+import java.util.Optional;
+import java.util.concurrent.Executor;
+import java.util.function.Consumer;
+
+/**
+ * {@link ObservableServiceConnection} is a concrete implementation of {@link ServiceConnection}
+ * that enables monitoring the status of a binder connection. It also aides in automatically
+ * converting a proxy into an internal wrapper type.
+ * @param <T> The type of the wrapper over the resulting service.
+ */
+public class ObservableServiceConnection<T> implements ServiceConnection {
+ private static final String TAG = "ObservableSvcConn";
+ private static final boolean DEBUG = Log.isLoggable(TAG, Log.DEBUG);
+ /**
+ * An interface for converting the service proxy into a given internal wrapper type.
+ * @param <T> The type of the wrapper over the resulting service.
+ */
+ public interface ServiceTransformer<T> {
+ /**
+ * Called to convert the service proxy to the wrapper type.
+ * @param service The service proxy to create the wrapper type from.
+ * @return The wrapper type.
+ */
+ T convert(IBinder service);
+ }
+
+ /**
+ * An interface for listening to the connection status.
+ * @param <T> The wrapper type.
+ */
+ public interface Callback<T> {
+ /**
+ * Invoked when the service has been successfully connected to.
+ * @param connection The {@link ObservableServiceConnection} instance that is now connected
+ * @param proxy The service proxy converted into the typed wrapper.
+ */
+ void onConnected(ObservableServiceConnection<T> connection, T proxy);
+
+ /**
+ * Invoked when the service has been disconnected.
+ * @param connection The {@link ObservableServiceConnection} that is now disconnected.
+ * @param reason The reason for the disconnection.
+ */
+ void onDisconnected(ObservableServiceConnection<T> connection,
+ @DisconnectReason int reason);
+ }
+
+ /**
+ * Disconnection was due to the resulting binding being {@code null}.
+ */
+ public static final int DISCONNECT_REASON_NULL_BINDING = 1;
+ /**
+ * Disconnection was due to the remote end disconnecting.
+ */
+ public static final int DISCONNECT_REASON_DISCONNECTED = 2;
+ /**
+ * Disconnection due to the binder dying.
+ */
+ public static final int DISCONNECT_REASON_BINDING_DIED = 3;
+ /**
+ * Disconnection from an explicit unbinding.
+ */
+ public static final int DISCONNECT_REASON_UNBIND = 4;
+
+ @Retention(RetentionPolicy.SOURCE)
+ @IntDef({
+ DISCONNECT_REASON_NULL_BINDING,
+ DISCONNECT_REASON_DISCONNECTED,
+ DISCONNECT_REASON_BINDING_DIED,
+ DISCONNECT_REASON_UNBIND
+ })
+ public @interface DisconnectReason {}
+
+ private final Context mContext;
+ private final Intent mServiceIntent;
+ private final int mFlags;
+ private final Executor mExecutor;
+ private final ServiceTransformer<T> mTransformer;
+ private final ArrayList<WeakReference<Callback<T>>> mCallbacks;
+ private Optional<Integer> mLastDisconnectReason;
+ private T mProxy;
+
+ private boolean mBoundCalled;
+
+ /**
+ * Default constructor for {@link ObservableServiceConnection}.
+ * @param context The context from which the service will be bound with.
+ * @param serviceIntent The intent to bind service with.
+ * @param flags The flags to use during the binding
+ * @param executor The executor for connection callbacks to be delivered on
+ * @param transformer A {@link ServiceTransformer} for transforming the resulting service
+ * into a desired type.
+ */
+ public ObservableServiceConnection(Context context, Intent serviceIntent,
+ @Context.BindServiceFlags int flags, @NonNull @CallbackExecutor Executor executor,
+ ServiceTransformer<T> transformer) {
+ mContext = context;
+ mServiceIntent = serviceIntent;
+ mFlags = flags;
+ mExecutor = executor;
+ mTransformer = transformer;
+ mCallbacks = new ArrayList<>();
+ mLastDisconnectReason = Optional.empty();
+ }
+
+ /**
+ * Initiate binding to the service.
+ * @return {@code true} if initiating binding succeed, {@code false} otherwise.
+ */
+ public boolean bind() {
+ final boolean bindResult = mContext.bindService(mServiceIntent, mFlags, mExecutor, this);
+ mBoundCalled = true;
+ if (DEBUG) {
+ Log.d(TAG, "bind. bound:" + bindResult);
+ }
+ return bindResult;
+ }
+
+ /**
+ * Disconnect from the service if bound.
+ */
+ public void unbind() {
+ if (!mBoundCalled) {
+ return;
+ }
+ mBoundCalled = false;
+ mContext.unbindService(this);
+ onDisconnected(DISCONNECT_REASON_UNBIND);
+ }
+
+ /**
+ * Adds a callback for receiving connection updates.
+ * @param callback The {@link Callback} to receive future updates.
+ */
+ public void addCallback(Callback<T> callback) {
+ if (DEBUG) {
+ Log.d(TAG, "addCallback:" + callback);
+ }
+
+ mExecutor.execute(() -> {
+ final Iterator<WeakReference<Callback<T>>> iterator = mCallbacks.iterator();
+
+ while (iterator.hasNext()) {
+ if (iterator.next().get() == callback) {
+ return;
+ }
+ }
+
+ mCallbacks.add(new WeakReference<>(callback));
+
+ // If not connected anymore, immediately inform new callback of disconnection and
+ // remove.
+ if (mProxy != null) {
+ callback.onConnected(this, mProxy);
+ } else if (mLastDisconnectReason.isPresent()) {
+ callback.onDisconnected(this, mLastDisconnectReason.get());
+ }
+ });
+ }
+
+ /**
+ * Removes previously added callback from receiving future connection updates.
+ * @param callback The {@link Callback} to be removed.
+ */
+ public void removeCallback(Callback callback) {
+ if (DEBUG) {
+ Log.d(TAG, "removeCallback:" + callback);
+ }
+
+ mExecutor.execute(()-> mCallbacks.removeIf(el -> el.get() == callback));
+ }
+
+ private void onDisconnected(@DisconnectReason int reason) {
+ if (DEBUG) {
+ Log.d(TAG, "onDisconnected:" + reason);
+ }
+
+ if (!mBoundCalled) {
+ return;
+ }
+
+ mLastDisconnectReason = Optional.of(reason);
+ unbind();
+ mProxy = null;
+
+ applyToCallbacksLocked(callback-> callback.onDisconnected(this,
+ mLastDisconnectReason.get()));
+ }
+
+ @Override
+ public void onServiceConnected(ComponentName name, IBinder service) {
+ if (DEBUG) {
+ Log.d(TAG, "onServiceConnected");
+ }
+ mProxy = mTransformer.convert(service);
+ applyToCallbacksLocked(callback -> callback.onConnected(this, mProxy));
+ }
+
+ private void applyToCallbacksLocked(Consumer<Callback<T>> applicator) {
+ final Iterator<WeakReference<Callback<T>>> iterator = mCallbacks.iterator();
+
+ while (iterator.hasNext()) {
+ final Callback cb = iterator.next().get();
+ if (cb != null) {
+ applicator.accept(cb);
+ } else {
+ iterator.remove();
+ }
+ }
+ }
+
+ @Override
+ public void onServiceDisconnected(ComponentName name) {
+ onDisconnected(DISCONNECT_REASON_DISCONNECTED);
+ }
+
+ @Override
+ public void onBindingDied(ComponentName name) {
+ onDisconnected(DISCONNECT_REASON_DISCONNECTED);
+ }
+
+ @Override
+ public void onNullBinding(ComponentName name) {
+ onDisconnected(DISCONNECT_REASON_NULL_BINDING);
+ }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/wmshell/WMShellBaseModule.java b/packages/SystemUI/src/com/android/systemui/wmshell/WMShellBaseModule.java
index fd9783a..0a33930 100644
--- a/packages/SystemUI/src/com/android/systemui/wmshell/WMShellBaseModule.java
+++ b/packages/SystemUI/src/com/android/systemui/wmshell/WMShellBaseModule.java
@@ -463,13 +463,13 @@
@ShellMainThread ShellExecutor mainExecutor,
DisplayImeController displayImeController,
DisplayInsetsController displayInsetsController, Transitions transitions,
- TransactionPool transactionPool,
+ TransactionPool transactionPool, IconProvider iconProvider,
Provider<Optional<StageTaskUnfoldController>> stageTaskUnfoldControllerProvider) {
if (ActivityTaskManager.supportsSplitScreenMultiWindow(context)) {
return Optional.of(new SplitScreenController(shellTaskOrganizer, syncQueue, context,
rootTaskDisplayAreaOrganizer, mainExecutor, displayImeController,
- displayInsetsController, transitions,
- transactionPool, stageTaskUnfoldControllerProvider));
+ displayInsetsController, transitions, transactionPool, iconProvider,
+ stageTaskUnfoldControllerProvider));
} else {
return Optional.empty();
}
diff --git a/packages/SystemUI/tests/src/com/android/keyguard/clock/SmallClockPositionTest.kt b/packages/SystemUI/tests/src/com/android/keyguard/clock/SmallClockPositionTest.kt
index 456f32b..3a27e35 100644
--- a/packages/SystemUI/tests/src/com/android/keyguard/clock/SmallClockPositionTest.kt
+++ b/packages/SystemUI/tests/src/com/android/keyguard/clock/SmallClockPositionTest.kt
@@ -43,7 +43,7 @@
@Test
fun loadResources() {
// Cover constructor taking Resources object.
- position = SmallClockPosition(context.resources)
+ position = SmallClockPosition(context)
position.setDarkAmount(1f)
assertThat(position.preferredY).isGreaterThan(0)
}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/flags/FeatureFlagManagerTest.java b/packages/SystemUI/tests/src/com/android/systemui/flags/FeatureFlagManagerTest.java
index 172dcda..8243be8 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/flags/FeatureFlagManagerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/flags/FeatureFlagManagerTest.java
@@ -18,23 +18,59 @@
import static com.google.common.truth.Truth.assertThat;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.ArgumentMatchers.anyString;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.verifyNoMoreInteractions;
+import static org.mockito.Mockito.verifyZeroInteractions;
+
+import android.content.Context;
+
import androidx.test.filters.SmallTest;
import com.android.systemui.SysuiTestCase;
+import com.android.systemui.dump.DumpManager;
+import org.junit.After;
import org.junit.Before;
import org.junit.Test;
+import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
+import java.io.FileDescriptor;
+import java.io.PrintWriter;
+import java.io.StringWriter;
+
+/**
+ * NOTE: This test is for the version of FeatureFlagManager in src-release, which should not allow
+ * overriding, and should never return any value other than the one provided as the default.
+ */
@SmallTest
public class FeatureFlagManagerTest extends SysuiTestCase {
FeatureFlagManager mFeatureFlagManager;
+ @Mock private SystemPropertiesHelper mProps;
+ @Mock private Context mContext;
+ @Mock private DumpManager mDumpManager;
+
@Before
public void setup() {
MockitoAnnotations.initMocks(this);
- mFeatureFlagManager = new FeatureFlagManager();
+ mFeatureFlagManager = new FeatureFlagManager(mProps, mContext, mDumpManager);
+ }
+
+ @After
+ public void onFinished() {
+ // SystemPropertiesHelper and Context are provided for constructor consistency with the
+ // debug version of the FeatureFlagManager, but should never be used.
+ verifyZeroInteractions(mProps, mContext);
+ // The dump manager should be registered with even for the release version, but that's it.
+ verify(mDumpManager).registerDumpable(anyString(), any());
+ verifyNoMoreInteractions(mDumpManager);
}
@Test
@@ -43,4 +79,31 @@
// Again, nothing changes.
assertThat(mFeatureFlagManager.isEnabled(1, false)).isFalse();
}
+
+ @Test
+ public void testDump() {
+ // Even if a flag is set before
+ mFeatureFlagManager.setEnabled(1, true);
+
+ // WHEN the flags have been accessed
+ assertFalse(mFeatureFlagManager.isEnabled(1, false));
+ assertTrue(mFeatureFlagManager.isEnabled(2, true));
+
+ // Even if a flag is set after
+ mFeatureFlagManager.setEnabled(2, false);
+
+ // THEN the dump contains the flags and the default values
+ String dump = dumpToString();
+ assertThat(dump).contains(" sysui_flag_1: false\n");
+ assertThat(dump).contains(" sysui_flag_2: true\n");
+ }
+
+ private String dumpToString() {
+ StringWriter sw = new StringWriter();
+ PrintWriter pw = new PrintWriter(sw);
+ mFeatureFlagManager.dump(mock(FileDescriptor.class), pw, new String[0]);
+ pw.flush();
+ String dump = sw.toString();
+ return dump;
+ }
}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/keyguard/FaceAuthScreenBrightnessControllerTest.kt b/packages/SystemUI/tests/src/com/android/systemui/keyguard/FaceAuthScreenBrightnessControllerTest.kt
deleted file mode 100644
index cb05a6b..0000000
--- a/packages/SystemUI/tests/src/com/android/systemui/keyguard/FaceAuthScreenBrightnessControllerTest.kt
+++ /dev/null
@@ -1,137 +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.systemui.keyguard
-
-import android.animation.ValueAnimator
-import android.content.res.Resources
-import android.hardware.biometrics.BiometricSourceType
-import android.os.Handler
-import android.provider.Settings.System.SCREEN_BRIGHTNESS_FLOAT
-import android.testing.AndroidTestingRunner
-import android.util.TypedValue
-import android.view.View
-import androidx.test.filters.SmallTest
-import com.android.keyguard.KeyguardUpdateMonitor
-import com.android.keyguard.KeyguardUpdateMonitorCallback
-import com.android.systemui.Dumpable
-import com.android.systemui.SysuiTestCase
-import com.android.systemui.dump.DumpManager
-import com.android.systemui.statusbar.NotificationShadeWindowController
-import com.android.systemui.util.mockito.any
-import com.android.systemui.util.mockito.capture
-import com.android.systemui.util.mockito.eq
-import com.android.systemui.util.settings.GlobalSettings
-import com.android.systemui.util.settings.SystemSettings
-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.Mockito.`when`
-import org.mockito.Mockito.anyInt
-import org.mockito.Mockito.anyString
-import org.mockito.Mockito.clearInvocations
-import org.mockito.Mockito.never
-import org.mockito.Mockito.verify
-import org.mockito.MockitoAnnotations
-
-const val INITIAL_BRIGHTNESS = 0.5f
-
-@RunWith(AndroidTestingRunner::class)
-@SmallTest
-class FaceAuthScreenBrightnessControllerTest : SysuiTestCase() {
-
- @Mock
- lateinit var whiteOverlay: View
- @Mock
- lateinit var dumpManager: DumpManager
- @Mock
- lateinit var resources: Resources
- @Mock
- lateinit var mainHandler: Handler
- @Mock
- lateinit var globalSettings: GlobalSettings
- @Mock
- lateinit var systemSettings: SystemSettings
- @Mock
- lateinit var keyguardUpdateMonitor: KeyguardUpdateMonitor
- @Mock
- lateinit var notificationShadeWindowController: NotificationShadeWindowController
- @Mock
- lateinit var animator: ValueAnimator
- @Captor
- lateinit var keyguardUpdateCallback: ArgumentCaptor<KeyguardUpdateMonitorCallback>
- lateinit var faceAuthScreenBrightnessController: FaceAuthScreenBrightnessController
-
- @Before
- fun setup() {
- MockitoAnnotations.initMocks(this)
- faceAuthScreenBrightnessController = object : FaceAuthScreenBrightnessController(
- notificationShadeWindowController, keyguardUpdateMonitor, resources, globalSettings,
- systemSettings, mainHandler, dumpManager, true) {
- override fun createAnimator(start: Float, end: Float) = animator
- }
- `when`(systemSettings.getFloat(eq(SCREEN_BRIGHTNESS_FLOAT))).thenReturn(INITIAL_BRIGHTNESS)
- `when`(systemSettings.getFloat(eq(SCREEN_BRIGHTNESS_FLOAT), eq(1f)))
- .thenReturn(INITIAL_BRIGHTNESS)
- faceAuthScreenBrightnessController.attach(whiteOverlay)
- verify(keyguardUpdateMonitor).registerCallback(capture(keyguardUpdateCallback))
- }
-
- @Test
- fun init_registersDumpManager() {
- verify(dumpManager).registerDumpable(anyString(), any(Dumpable::class.java))
- }
-
- @Test
- fun init_registersKeyguardCallback() {
- verify(keyguardUpdateMonitor)
- .registerCallback(any(KeyguardUpdateMonitorCallback::class.java))
- }
-
- @Test
- fun onBiometricRunningChanged_animatesBrightness() {
- clearInvocations(whiteOverlay)
- keyguardUpdateCallback.value
- .onBiometricRunningStateChanged(true, BiometricSourceType.FACE)
- verify(whiteOverlay).visibility = eq(View.VISIBLE)
- verify(animator).start()
- }
-
- @Test
- fun faceAuthWallpaper_whenFaceIsDisabledForUser() {
- faceAuthScreenBrightnessController.useFaceAuthWallpaper = true
- faceAuthScreenBrightnessController.faceAuthWallpaper
- verify(resources, never()).openRawResource(anyInt(), any(TypedValue::class.java))
- }
-
- @Test
- fun faceAuthWallpaper_whenFaceFlagIsDisabled() {
- faceAuthScreenBrightnessController.useFaceAuthWallpaper = true
- faceAuthScreenBrightnessController.faceAuthWallpaper
- verify(resources, never()).openRawResource(anyInt(), any(TypedValue::class.java))
- }
-
- @Test
- fun faceAuthWallpaper_whenFaceIsEnabledForUser() {
- faceAuthScreenBrightnessController.useFaceAuthWallpaper = true
- `when`(keyguardUpdateMonitor.isFaceAuthEnabledForUser(anyInt())).thenReturn(true)
- faceAuthScreenBrightnessController.faceAuthWallpaper
- verify(resources).openRawResource(anyInt(), any(TypedValue::class.java))
- }
-}
\ No newline at end of file
diff --git a/packages/SystemUI/tests/src/com/android/systemui/media/dialog/MediaOutputAdapterTest.java b/packages/SystemUI/tests/src/com/android/systemui/media/dialog/MediaOutputAdapterTest.java
index 750600ad..52173c1 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/media/dialog/MediaOutputAdapterTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/media/dialog/MediaOutputAdapterTest.java
@@ -212,12 +212,14 @@
mMediaOutputAdapter.onBindViewHolder(mViewHolder, 1);
assertThat(mViewHolder.mAddIcon.getVisibility()).isEqualTo(View.GONE);
- assertThat(mViewHolder.mTwoLineLayout.getVisibility()).isEqualTo(View.GONE);
assertThat(mViewHolder.mProgressBar.getVisibility()).isEqualTo(View.GONE);
assertThat(mViewHolder.mBottomDivider.getVisibility()).isEqualTo(View.GONE);
- assertThat(mViewHolder.mTitleText.getVisibility()).isEqualTo(View.VISIBLE);
- assertThat(mViewHolder.mTitleText.getText().toString()).isEqualTo(
- mContext.getString(R.string.media_output_dialog_disconnected, TEST_DEVICE_NAME_2));
+ assertThat(mViewHolder.mTitleText.getVisibility()).isEqualTo(View.GONE);
+ assertThat(mViewHolder.mTwoLineLayout.getVisibility()).isEqualTo(View.VISIBLE);
+ assertThat(mViewHolder.mTwoLineTitleText.getText().toString()).isEqualTo(
+ TEST_DEVICE_NAME_2);
+ assertThat(mViewHolder.mSubTitleText.getText().toString()).isEqualTo(
+ mContext.getString(R.string.media_output_dialog_disconnected));
}
@Test
diff --git a/packages/SystemUI/tests/src/com/android/systemui/navigationbar/NavigationBarRotationContextTest.java b/packages/SystemUI/tests/src/com/android/systemui/navigationbar/NavigationBarRotationContextTest.java
index a6ff2e8..85bc634 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/navigationbar/NavigationBarRotationContextTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/navigationbar/NavigationBarRotationContextTest.java
@@ -22,6 +22,7 @@
import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;
+import android.view.Display;
import android.view.View;
import android.view.WindowInsetsController;
@@ -31,6 +32,8 @@
import com.android.systemui.SysuiTestCase;
import com.android.systemui.SysuiTestableContext;
+import com.android.systemui.shared.rotation.RotationButton;
+import com.android.systemui.shared.rotation.RotationButtonController;
import com.android.systemui.statusbar.policy.RotationLockController;
import org.junit.Before;
@@ -39,6 +42,8 @@
import org.junit.runner.RunWith;
import org.mockito.MockitoAnnotations;
+import java.util.function.Supplier;
+
/** atest NavigationBarRotationContextTest */
@SmallTest
@RunWith(AndroidJUnit4.class)
@@ -50,6 +55,8 @@
InstrumentationRegistry.getContext(), getLeakCheck());
private RotationButtonController mRotationButtonController;
private RotationButton mRotationButton;
+ private int mWindowRotation = DEFAULT_ROTATE;
+ private Supplier<Integer> mWindowRotationSupplier = () -> mWindowRotation;
@Before
public void setup() {
@@ -58,7 +65,15 @@
final View view = new View(mContext);
mRotationButton = mock(RotationButton.class);
- mRotationButtonController = new RotationButtonController(mContext, 0, 0);
+ mRotationButtonController = new RotationButtonController(mContext,
+ /* lightIconColor */ 0,
+ /* darkIconColor */ 0,
+ /* iconCcwStart0 */ 0,
+ /* iconCcwStart90 */ 0,
+ /* iconCwStart0 */ 0,
+ /* iconCwStart90 */ 0,
+ mWindowRotationSupplier
+ );
mRotationButtonController.setRotationButton(mRotationButton,
new RotationButton.RotationButtonUpdatesCallback() {
@Override
@@ -77,16 +92,16 @@
@Test
public void testOnInvalidRotationProposal() {
- mRotationButtonController.onRotationProposal(DEFAULT_ROTATE, DEFAULT_ROTATE + 1,
- false /* isValid */);
+ mWindowRotation = DEFAULT_ROTATE + 1;
+ mRotationButtonController.onRotationProposal(DEFAULT_ROTATE, false /* isValid */);
verify(mRotationButtonController, times(1)).setRotateSuggestionButtonState(
false /* visible */);
}
@Test
public void testOnSameRotationProposal() {
- mRotationButtonController.onRotationProposal(DEFAULT_ROTATE, DEFAULT_ROTATE,
- true /* isValid */);
+ mWindowRotation = DEFAULT_ROTATE;
+ mRotationButtonController.onRotationProposal(DEFAULT_ROTATE, true /* isValid */);
verify(mRotationButtonController, times(1)).setRotateSuggestionButtonState(
false /* visible */);
}
@@ -94,17 +109,17 @@
@Test
public void testOnRotationProposalShowButtonShowNav() {
// No navigation bar should not call to set visibility state
- mRotationButtonController.onBehaviorChanged(
+ mRotationButtonController.onBehaviorChanged(Display.DEFAULT_DISPLAY,
WindowInsetsController.BEHAVIOR_SHOW_TRANSIENT_BARS_BY_SWIPE);
mRotationButtonController.onNavigationBarWindowVisibilityChange(false /* showing */);
verify(mRotationButtonController, times(0)).setRotateSuggestionButtonState(
false /* visible */);
verify(mRotationButtonController, times(0)).setRotateSuggestionButtonState(
true /* visible */);
+ mWindowRotation = DEFAULT_ROTATE + 1;
// No navigation bar with rotation change should not call to set visibility state
- mRotationButtonController.onRotationProposal(DEFAULT_ROTATE, DEFAULT_ROTATE + 1,
- true /* isValid */);
+ mRotationButtonController.onRotationProposal(DEFAULT_ROTATE, true /* isValid */);
verify(mRotationButtonController, times(0)).setRotateSuggestionButtonState(
false /* visible */);
verify(mRotationButtonController, times(0)).setRotateSuggestionButtonState(
@@ -124,10 +139,10 @@
false /* visible */);
verify(mRotationButtonController, times(0)).setRotateSuggestionButtonState(
true /* visible */);
+ mWindowRotation = DEFAULT_ROTATE + 1;
// Navigation bar is visible and rotation requested
- mRotationButtonController.onRotationProposal(DEFAULT_ROTATE, DEFAULT_ROTATE + 1,
- true /* isValid */);
+ mRotationButtonController.onRotationProposal(DEFAULT_ROTATE, true /* isValid */);
verify(mRotationButtonController, times(1)).setRotateSuggestionButtonState(
true /* visible */);
}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/navigationbar/gestural/FloatingRotationButtonPositionCalculatorTest.kt b/packages/SystemUI/tests/src/com/android/systemui/navigationbar/gestural/FloatingRotationButtonPositionCalculatorTest.kt
index 0a20001..36e02cb 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/navigationbar/gestural/FloatingRotationButtonPositionCalculatorTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/navigationbar/gestural/FloatingRotationButtonPositionCalculatorTest.kt
@@ -4,7 +4,8 @@
import android.view.Surface
import androidx.test.filters.SmallTest
import com.android.systemui.SysuiTestCase
-import com.android.systemui.navigationbar.gestural.FloatingRotationButtonPositionCalculator.Position
+import com.android.systemui.shared.rotation.FloatingRotationButtonPositionCalculator
+import com.android.systemui.shared.rotation.FloatingRotationButtonPositionCalculator.Position
import com.google.common.truth.Truth.assertThat
import org.junit.Test
import org.junit.runner.RunWith
diff --git a/packages/SystemUI/tests/src/com/android/systemui/qs/FooterActionsControllerTest.kt b/packages/SystemUI/tests/src/com/android/systemui/qs/FooterActionsControllerTest.kt
index e54a6ec..d2bba36 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/qs/FooterActionsControllerTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/qs/FooterActionsControllerTest.kt
@@ -1,7 +1,9 @@
package com.android.systemui.qs
-import com.android.systemui.R
import android.os.UserManager
+import android.testing.AndroidTestingRunner
+import android.testing.TestableLooper
+import android.testing.ViewUtils
import android.view.LayoutInflater
import android.view.View
import androidx.test.filters.SmallTest
@@ -9,6 +11,7 @@
import com.android.internal.logging.UiEventLogger
import com.android.internal.logging.testing.FakeMetricsLogger
import com.android.systemui.Dependency
+import com.android.systemui.R
import com.android.systemui.classifier.FalsingManagerFake
import com.android.systemui.globalactions.GlobalActionsDialogLite
import com.android.systemui.plugins.ActivityStarter
@@ -19,8 +22,11 @@
import com.android.systemui.tuner.TunerService
import com.android.systemui.utils.leaks.FakeTunerService
import com.android.systemui.utils.leaks.LeakCheckedTest
+import com.google.common.truth.Truth.assertThat
+import org.junit.After
import org.junit.Before
import org.junit.Test
+import org.junit.runner.RunWith
import org.mockito.ArgumentMatchers.any
import org.mockito.ArgumentMatchers.anyBoolean
import org.mockito.Mock
@@ -30,6 +36,8 @@
import org.mockito.Mockito.`when` as whenever
@SmallTest
+@TestableLooper.RunWithLooper
+@RunWith(AndroidTestingRunner::class)
class FooterActionsControllerTest : LeakCheckedTest() {
@Mock
private lateinit var userManager: UserManager
@@ -53,10 +61,12 @@
private val metricsLogger: MetricsLogger = FakeMetricsLogger()
private lateinit var view: FooterActionsView
private val falsingManager: FalsingManagerFake = FalsingManagerFake()
+ private lateinit var testableLooper: TestableLooper
@Before
fun setUp() {
MockitoAnnotations.initMocks(this)
+ testableLooper = TestableLooper.get(this)
injectLeakCheckedDependencies(*LeakCheckedTest.ALL_SUPPORTED_CLASSES)
val fakeTunerService = Dependency.get(TunerService::class.java) as FakeTunerService
@@ -69,7 +79,14 @@
globalActionsDialog, uiEventLogger, showPMLiteButton = true,
buttonsVisibleState = ExpansionState.EXPANDED)
controller.init()
- controller.onViewAttached()
+ ViewUtils.attachView(view)
+ // View looper is the testable looper associated with the test
+ testableLooper.processAllMessages()
+ }
+
+ @After
+ fun tearDown() {
+ ViewUtils.detachView(view)
}
@Test
@@ -90,4 +107,19 @@
// Verify Settings wasn't launched.
verify<ActivityStarter>(activityStarter, Mockito.never()).startActivity(any(), anyBoolean())
}
+
+ @Test
+ fun testMultiUserSwitchUpdatedWhenExpansionStarts() {
+ // When expansion starts, listening is set to true
+ val multiUserSwitch = view.requireViewById<View>(R.id.multi_user_switch)
+
+ assertThat(multiUserSwitch.visibility).isNotEqualTo(View.VISIBLE)
+
+ whenever(multiUserSwitchController.isMultiUserEnabled).thenReturn(true)
+
+ controller.setListening(true)
+ testableLooper.processAllMessages()
+
+ assertThat(multiUserSwitch.visibility).isEqualTo(View.VISIBLE)
+ }
}
\ No newline at end of file
diff --git a/packages/SystemUI/tests/src/com/android/systemui/qs/QSPanelControllerTest.java b/packages/SystemUI/tests/src/com/android/systemui/qs/QSPanelControllerTest.java
index 06a4ae0..3242adb 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/qs/QSPanelControllerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/qs/QSPanelControllerTest.java
@@ -42,7 +42,7 @@
import com.android.systemui.qs.logging.QSLogger;
import com.android.systemui.qs.tileimpl.QSTileImpl;
import com.android.systemui.settings.brightness.BrightnessController;
-import com.android.systemui.settings.brightness.BrightnessSlider;
+import com.android.systemui.settings.brightness.BrightnessSliderController;
import com.android.systemui.settings.brightness.ToggleSlider;
import com.android.systemui.statusbar.CommandQueue;
import com.android.systemui.tuner.TunerService;
@@ -88,9 +88,9 @@
@Mock
private BrightnessController mBrightnessController;
@Mock
- private BrightnessSlider.Factory mToggleSliderViewControllerFactory;
+ private BrightnessSliderController.Factory mToggleSliderViewControllerFactory;
@Mock
- private BrightnessSlider mBrightnessSlider;
+ private BrightnessSliderController mBrightnessSliderController;
@Mock
QSTileImpl mQSTile;
@Mock
@@ -120,7 +120,7 @@
when(mQSTileHost.getTiles()).thenReturn(Collections.singleton(mQSTile));
when(mQSTileHost.createTileView(any(), eq(mQSTile), anyBoolean())).thenReturn(mQSTileView);
when(mToggleSliderViewControllerFactory.create(any(), any()))
- .thenReturn(mBrightnessSlider);
+ .thenReturn(mBrightnessSliderController);
when(mBrightnessControllerFactory.create(any(ToggleSlider.class)))
.thenReturn(mBrightnessController);
when(mQSTileRevealControllerFactory.create(any(), any()))
diff --git a/packages/SystemUI/tests/src/com/android/systemui/qs/QSSquishinessControllerTest.kt b/packages/SystemUI/tests/src/com/android/systemui/qs/QSSquishinessControllerTest.kt
new file mode 100644
index 0000000..3059aa1
--- /dev/null
+++ b/packages/SystemUI/tests/src/com/android/systemui/qs/QSSquishinessControllerTest.kt
@@ -0,0 +1,62 @@
+package com.android.systemui.qs
+
+import android.testing.AndroidTestingRunner
+import android.view.ViewGroup
+import androidx.test.filters.SmallTest
+import com.android.systemui.SysuiTestCase
+import com.android.systemui.plugins.qs.QSTile
+import com.android.systemui.qs.tileimpl.QSTileViewImpl
+import org.junit.Before
+import org.junit.Rule
+import org.junit.Test
+import org.junit.runner.RunWith
+import org.mockito.ArgumentMatchers.any
+import org.mockito.Mock
+import org.mockito.Mockito.`when`
+import org.mockito.Mockito.never
+import org.mockito.Mockito.verify
+import org.mockito.junit.MockitoJUnit
+
+@RunWith(AndroidTestingRunner::class)
+@SmallTest
+class QSSquishinessControllerTest : SysuiTestCase() {
+
+ @Mock private lateinit var qsTileHost: QSTileHost
+ @Mock private lateinit var qqsFooterActionsView: FooterActionsView
+ @Mock private lateinit var qqsFooterActionsViewLP: ViewGroup.MarginLayoutParams
+ @Mock private lateinit var qsAnimator: QSAnimator
+ @Mock private lateinit var quickQsPanelController: QuickQSPanelController
+ @Mock private lateinit var qstileView: QSTileViewImpl
+ @Mock private lateinit var qstile: QSTile
+ @Mock private lateinit var tileLayout: TileLayout
+
+ @JvmField @Rule val mockitoRule = MockitoJUnit.rule()
+
+ private lateinit var qsSquishinessController: QSSquishinessController
+
+ @Before
+ fun setup() {
+ qsSquishinessController = QSSquishinessController(qsTileHost, qqsFooterActionsView,
+ qsAnimator, quickQsPanelController)
+ `when`(qsTileHost.tiles).thenReturn(mutableListOf(qstile))
+ `when`(quickQsPanelController.getTileView(any())).thenReturn(qstileView)
+ `when`(quickQsPanelController.tileLayout).thenReturn(tileLayout)
+ `when`(qqsFooterActionsView.layoutParams).thenReturn(qqsFooterActionsViewLP)
+ }
+
+ @Test
+ fun setSquishiness_requestsAnimatorUpdate() {
+ qsSquishinessController.squishiness = 0.5f
+ verify(qsAnimator, never()).requestAnimatorUpdate()
+
+ qsSquishinessController.squishiness = 0f
+ verify(qsAnimator).requestAnimatorUpdate()
+ }
+
+ @Test
+ fun setSquishiness_updatesTiles() {
+ qsSquishinessController.squishiness = 0.5f
+ verify(qstileView).squishinessFraction = 0.5f
+ verify(tileLayout).setSquishinessFraction(0.5f)
+ }
+}
\ No newline at end of file
diff --git a/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/DeviceControlsTileTest.kt b/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/DeviceControlsTileTest.kt
index 94af10a..98c7274 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/DeviceControlsTileTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/DeviceControlsTileTest.kt
@@ -52,13 +52,11 @@
import org.junit.Test
import org.junit.runner.RunWith
import org.mockito.ArgumentCaptor
-import org.mockito.ArgumentMatchers.anyInt
import org.mockito.ArgumentMatchers.anyBoolean
import org.mockito.Captor
import org.mockito.Mock
import org.mockito.Mockito.`when`
import org.mockito.Mockito.doNothing
-import org.mockito.Mockito.never
import org.mockito.Mockito.nullable
import org.mockito.Mockito.spy
import org.mockito.Mockito.verify
@@ -272,28 +270,7 @@
}
@Test
- fun handleClick_availableAndLocked_activityStarted() {
- verify(controlsListingController).observe(
- any(LifecycleOwner::class.java),
- capture(listingCallbackCaptor)
- )
- `when`(controlsComponent.getVisibility()).thenReturn(ControlsComponent.Visibility.AVAILABLE)
- `when`(keyguardStateController.isUnlocked).thenReturn(false)
-
- listingCallbackCaptor.value.onServicesUpdated(listOf(serviceInfo))
- testableLooper.processAllMessages()
-
- tile.click(null /* view */)
- testableLooper.processAllMessages()
-
- // The activity should be started right away and not require a keyguard dismiss.
- verifyZeroInteractions(activityStarter)
- verify(spiedContext).startActivity(intentCaptor.capture())
- assertThat(intentCaptor.value.component?.className).isEqualTo(CONTROLS_ACTIVITY_CLASS_NAME)
- }
-
- @Test
- fun handleClick_availableAndUnlocked_activityStarted() {
+ fun handleClick_available_shownOverLockscreenWhenLocked() {
verify(controlsListingController).observe(
any(LifecycleOwner::class.java),
capture(listingCallbackCaptor)
@@ -307,16 +284,16 @@
tile.click(null /* view */)
testableLooper.processAllMessages()
- verify(activityStarter, never()).postStartActivityDismissingKeyguard(any(), anyInt())
verify(activityStarter).startActivity(
intentCaptor.capture(),
eq(true) /* dismissShade */,
- nullable(ActivityLaunchAnimator.Controller::class.java))
+ nullable(ActivityLaunchAnimator.Controller::class.java),
+ eq(true) /* showOverLockscreenWhenLocked */)
assertThat(intentCaptor.value.component?.className).isEqualTo(CONTROLS_ACTIVITY_CLASS_NAME)
}
@Test
- fun handleClick_availableAfterUnlockAndIsLocked_keyguardDismissRequired() {
+ fun handleClick_availableAfterUnlock_notShownOverLockscreenWhenLocked() {
verify(controlsListingController).observe(
any(LifecycleOwner::class.java),
capture(listingCallbackCaptor)
@@ -331,38 +308,11 @@
tile.click(null /* view */)
testableLooper.processAllMessages()
- verify(activityStarter, never()).startActivity(
- any(),
- anyBoolean() /* dismissShade */,
- nullable(ActivityLaunchAnimator.Controller::class.java))
- verify(activityStarter).postStartActivityDismissingKeyguard(
- intentCaptor.capture(),
- anyInt(),
- nullable(ActivityLaunchAnimator.Controller::class.java))
- assertThat(intentCaptor.value.component?.className).isEqualTo(CONTROLS_ACTIVITY_CLASS_NAME)
- }
-
- @Test
- fun handleClick_availableAfterUnlockAndIsUnlocked_activityStarted() {
- verify(controlsListingController).observe(
- any(LifecycleOwner::class.java),
- capture(listingCallbackCaptor)
- )
- `when`(controlsComponent.getVisibility())
- .thenReturn(ControlsComponent.Visibility.AVAILABLE_AFTER_UNLOCK)
- `when`(keyguardStateController.isUnlocked).thenReturn(true)
-
- listingCallbackCaptor.value.onServicesUpdated(listOf(serviceInfo))
- testableLooper.processAllMessages()
-
- tile.click(null /* view */)
- testableLooper.processAllMessages()
-
- verify(activityStarter, never()).postStartActivityDismissingKeyguard(any(), anyInt())
verify(activityStarter).startActivity(
intentCaptor.capture(),
- eq(true) /* dismissShade */,
- nullable(ActivityLaunchAnimator.Controller::class.java))
+ anyBoolean() /* dismissShade */,
+ nullable(ActivityLaunchAnimator.Controller::class.java),
+ eq(false) /* showOverLockscreenWhenLocked */)
assertThat(intentCaptor.value.component?.className).isEqualTo(CONTROLS_ACTIVITY_CLASS_NAME)
}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/dialog/InternetDialogControllerTest.java b/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/dialog/InternetDialogControllerTest.java
index fe32839..eb03b5f 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/dialog/InternetDialogControllerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/dialog/InternetDialogControllerTest.java
@@ -45,12 +45,14 @@
import com.android.settingslib.wifi.WifiUtils;
import com.android.systemui.R;
import com.android.systemui.SysuiTestCase;
+import com.android.systemui.animation.DialogLaunchAnimator;
import com.android.systemui.broadcast.BroadcastDispatcher;
import com.android.systemui.dagger.qualifiers.Main;
import com.android.systemui.plugins.ActivityStarter;
import com.android.systemui.statusbar.connectivity.NetworkController;
import com.android.systemui.statusbar.connectivity.NetworkController.AccessPointController;
import com.android.systemui.statusbar.policy.KeyguardStateController;
+import com.android.systemui.statusbar.policy.LocationController;
import com.android.systemui.toast.SystemUIToast;
import com.android.systemui.toast.ToastFactory;
import com.android.systemui.util.CarrierConfigTracker;
@@ -135,6 +137,10 @@
private Animator mAnimator;
@Mock
private CarrierConfigTracker mCarrierConfigTracker;
+ @Mock
+ private LocationController mLocationController;
+ @Mock
+ private DialogLaunchAnimator mDialogLaunchAnimator;
private TestableResources mTestableResources;
private MockInternetDialogController mInternetDialogController;
@@ -170,7 +176,8 @@
mSubscriptionManager, mTelephonyManager, mWifiManager,
mock(ConnectivityManager.class), mHandler, mExecutor, mBroadcastDispatcher,
mock(KeyguardUpdateMonitor.class), mGlobalSettings, mKeyguardStateController,
- mWindowManager, mToastFactory, mWorkerHandler, mCarrierConfigTracker);
+ mWindowManager, mToastFactory, mWorkerHandler, mCarrierConfigTracker,
+ mLocationController, mDialogLaunchAnimator);
mSubscriptionManager.addOnSubscriptionsChangedListener(mExecutor,
mInternetDialogController.mOnSubscriptionsChangedListener);
mInternetDialogController.onStart(mInternetDialogCallback, true);
@@ -602,6 +609,30 @@
verify(mMergedCarrierEntry).setEnabled(false);
}
+ @Test
+ public void isWifiScanEnabled_locationOff_returnFalse() {
+ when(mLocationController.isLocationEnabled()).thenReturn(false);
+ when(mWifiManager.isScanAlwaysAvailable()).thenReturn(false);
+
+ assertThat(mInternetDialogController.isWifiScanEnabled()).isFalse();
+
+ when(mWifiManager.isScanAlwaysAvailable()).thenReturn(true);
+
+ assertThat(mInternetDialogController.isWifiScanEnabled()).isFalse();
+ }
+
+ @Test
+ public void isWifiScanEnabled_locationOn_returnIsScanAlwaysAvailable() {
+ when(mLocationController.isLocationEnabled()).thenReturn(true);
+ when(mWifiManager.isScanAlwaysAvailable()).thenReturn(false);
+
+ assertThat(mInternetDialogController.isWifiScanEnabled()).isFalse();
+
+ when(mWifiManager.isScanAlwaysAvailable()).thenReturn(true);
+
+ assertThat(mInternetDialogController.isWifiScanEnabled()).isTrue();
+ }
+
private String getResourcesString(String name) {
return mContext.getResources().getString(getResourcesId(name));
}
@@ -625,12 +656,14 @@
KeyguardUpdateMonitor keyguardUpdateMonitor, GlobalSettings globalSettings,
KeyguardStateController keyguardStateController, WindowManager windowManager,
ToastFactory toastFactory, Handler workerHandler,
- CarrierConfigTracker carrierConfigTracker) {
+ CarrierConfigTracker carrierConfigTracker,
+ LocationController locationController,
+ DialogLaunchAnimator dialogLaunchAnimator) {
super(context, uiEventLogger, starter, accessPointController, subscriptionManager,
telephonyManager, wifiManager, connectivityManager, handler, mainExecutor,
broadcastDispatcher, keyguardUpdateMonitor, globalSettings,
keyguardStateController, windowManager, toastFactory, workerHandler,
- carrierConfigTracker);
+ carrierConfigTracker, locationController, dialogLaunchAnimator);
mGlobalSettings = globalSettings;
}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/dialog/InternetDialogTest.java b/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/dialog/InternetDialogTest.java
index 6688960..5e1fea5 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/dialog/InternetDialogTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/dialog/InternetDialogTest.java
@@ -282,7 +282,7 @@
@Test
public void updateDialog_wifiOffAndWifiScanOff_hideWifiScanNotify() {
when(mWifiManager.isWifiEnabled()).thenReturn(false);
- when(mWifiManager.isScanAlwaysAvailable()).thenReturn(false);
+ when(mInternetDialogController.isWifiScanEnabled()).thenReturn(false);
mInternetDialog.updateDialog(false);
@@ -292,7 +292,7 @@
@Test
public void updateDialog_wifiOffAndWifiScanOnAndDeviceLocked_hideWifiScanNotify() {
when(mWifiManager.isWifiEnabled()).thenReturn(false);
- when(mWifiManager.isScanAlwaysAvailable()).thenReturn(true);
+ when(mInternetDialogController.isWifiScanEnabled()).thenReturn(true);
when(mInternetDialogController.isDeviceLocked()).thenReturn(true);
mInternetDialog.updateDialog(false);
@@ -303,7 +303,7 @@
@Test
public void updateDialog_wifiOffAndWifiScanOnAndDeviceUnlocked_showWifiScanNotify() {
when(mWifiManager.isWifiEnabled()).thenReturn(false);
- when(mWifiManager.isScanAlwaysAvailable()).thenReturn(true);
+ when(mInternetDialogController.isWifiScanEnabled()).thenReturn(true);
when(mInternetDialogController.isDeviceLocked()).thenReturn(false);
mInternetDialog.updateDialog(false);
diff --git a/packages/SystemUI/tests/src/com/android/systemui/settings/brightness/BrightnessSliderTest.kt b/packages/SystemUI/tests/src/com/android/systemui/settings/brightness/BrightnessSliderControllerTest.kt
similarity index 96%
rename from packages/SystemUI/tests/src/com/android/systemui/settings/brightness/BrightnessSliderTest.kt
rename to packages/SystemUI/tests/src/com/android/systemui/settings/brightness/BrightnessSliderControllerTest.kt
index bceb928..2b39354 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/settings/brightness/BrightnessSliderTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/settings/brightness/BrightnessSliderControllerTest.kt
@@ -45,7 +45,7 @@
@SmallTest
@RunWith(AndroidTestingRunner::class)
-class BrightnessSliderTest : SysuiTestCase() {
+class BrightnessSliderControllerTest : SysuiTestCase() {
@Mock
private lateinit var brightnessSliderView: BrightnessSliderView
@@ -66,7 +66,7 @@
private lateinit var seekBar: SeekBar
private var mFalsingManager: FalsingManagerFake = FalsingManagerFake()
- private lateinit var mController: BrightnessSlider
+ private lateinit var mController: BrightnessSliderController
@Before
fun setUp() {
@@ -75,7 +75,7 @@
whenever(mirrorController.toggleSlider).thenReturn(mirror)
whenever(motionEvent.copy()).thenReturn(motionEvent)
- mController = BrightnessSlider(brightnessSliderView, mFalsingManager)
+ mController = BrightnessSliderController(brightnessSliderView, mFalsingManager)
mController.init()
mController.setOnChangedListener(listener)
}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/NotificationRemoteInputManagerTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/NotificationRemoteInputManagerTest.java
index 5944e9c..4ed7224 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/NotificationRemoteInputManagerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/NotificationRemoteInputManagerTest.java
@@ -1,3 +1,18 @@
+/*
+ * Copyright (C) 2021 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;
@@ -10,26 +25,25 @@
import static org.mockito.Mockito.when;
import android.app.Notification;
-import android.app.RemoteInputHistoryItem;
import android.content.Context;
-import android.net.Uri;
import android.os.Handler;
import android.os.Looper;
import android.os.SystemClock;
import android.os.UserHandle;
import android.service.notification.NotificationListenerService;
-import android.service.notification.StatusBarNotification;
import android.testing.AndroidTestingRunner;
import android.testing.TestableLooper;
+import androidx.annotation.NonNull;
import androidx.test.filters.SmallTest;
import com.android.systemui.SysuiTestCase;
import com.android.systemui.dump.DumpManager;
+import com.android.systemui.flags.FeatureFlags;
import com.android.systemui.plugins.statusbar.StatusBarStateController;
-import com.android.systemui.statusbar.NotificationRemoteInputManager.RemoteInputActiveExtender;
-import com.android.systemui.statusbar.NotificationRemoteInputManager.RemoteInputHistoryExtender;
-import com.android.systemui.statusbar.NotificationRemoteInputManager.SmartReplyHistoryExtender;
+import com.android.systemui.statusbar.NotificationRemoteInputManager.LegacyRemoteInputLifetimeExtender.RemoteInputActiveExtender;
+import com.android.systemui.statusbar.NotificationRemoteInputManager.LegacyRemoteInputLifetimeExtender.RemoteInputHistoryExtender;
+import com.android.systemui.statusbar.NotificationRemoteInputManager.LegacyRemoteInputLifetimeExtender.SmartReplyHistoryExtender;
import com.android.systemui.statusbar.notification.NotificationEntryManager;
import com.android.systemui.statusbar.notification.collection.NotificationEntry;
import com.android.systemui.statusbar.notification.collection.NotificationEntryBuilder;
@@ -76,13 +90,19 @@
private RemoteInputHistoryExtender mRemoteInputHistoryExtender;
private SmartReplyHistoryExtender mSmartReplyHistoryExtender;
private RemoteInputActiveExtender mRemoteInputActiveExtender;
+ private TestableNotificationRemoteInputManager.FakeLegacyRemoteInputLifetimeExtender
+ mLegacyRemoteInputLifetimeExtender;
@Before
public void setUp() {
MockitoAnnotations.initMocks(this);
mRemoteInputManager = new TestableNotificationRemoteInputManager(mContext,
- mLockscreenUserManager, mSmartReplyController, mEntryManager,
+ mock(FeatureFlags.class),
+ mLockscreenUserManager,
+ mSmartReplyController,
+ mEntryManager,
+ mock(RemoteInputNotificationRebuilder.class),
() -> Optional.of(mock(StatusBar.class)),
mStateController,
Handler.createAsync(Looper.myLooper()),
@@ -120,6 +140,7 @@
public void testShouldExtendLifetime_remoteInputActive() {
when(mController.isRemoteInputActive(mEntry)).thenReturn(true);
+ assertTrue(mRemoteInputManager.isRemoteInputActive(mEntry));
assertTrue(mRemoteInputActiveExtender.shouldExtendLifetime(mEntry));
}
@@ -128,6 +149,7 @@
NotificationRemoteInputManager.FORCE_REMOTE_INPUT_HISTORY = true;
when(mController.isSpinning(mEntry.getKey())).thenReturn(true);
+ assertTrue(mRemoteInputManager.shouldKeepForRemoteInputHistory(mEntry));
assertTrue(mRemoteInputHistoryExtender.shouldExtendLifetime(mEntry));
}
@@ -136,6 +158,7 @@
NotificationRemoteInputManager.FORCE_REMOTE_INPUT_HISTORY = true;
mEntry.lastRemoteInputSent = SystemClock.elapsedRealtime();
+ assertTrue(mRemoteInputManager.shouldKeepForRemoteInputHistory(mEntry));
assertTrue(mRemoteInputHistoryExtender.shouldExtendLifetime(mEntry));
}
@@ -144,6 +167,7 @@
NotificationRemoteInputManager.FORCE_REMOTE_INPUT_HISTORY = true;
when(mSmartReplyController.isSendingSmartReply(mEntry.getKey())).thenReturn(true);
+ assertTrue(mRemoteInputManager.shouldKeepForSmartReplyHistory(mEntry));
assertTrue(mSmartReplyHistoryExtender.shouldExtendLifetime(mEntry));
}
@@ -151,124 +175,24 @@
public void testNotificationWithRemoteInputActiveIsRemovedOnCollapse() {
mRemoteInputActiveExtender.setShouldManageLifetime(mEntry, true /* shouldManage */);
- assertEquals(mRemoteInputManager.getEntriesKeptForRemoteInputActive(),
+ assertEquals(mLegacyRemoteInputLifetimeExtender.getEntriesKeptForRemoteInputActive(),
Sets.newArraySet(mEntry));
mRemoteInputManager.onPanelCollapsed();
- assertTrue(mRemoteInputManager.getEntriesKeptForRemoteInputActive().isEmpty());
+ assertTrue(
+ mLegacyRemoteInputLifetimeExtender.getEntriesKeptForRemoteInputActive().isEmpty());
}
- @Test
- public void testRebuildWithRemoteInput_noExistingInput_image() {
- Uri uri = mock(Uri.class);
- String mimeType = "image/jpeg";
- String text = "image inserted";
- StatusBarNotification newSbn =
- mRemoteInputManager.rebuildNotificationWithRemoteInputInserted(
- mEntry, text, false, mimeType, uri);
- RemoteInputHistoryItem[] messages = (RemoteInputHistoryItem[]) newSbn.getNotification()
- .extras.getParcelableArray(Notification.EXTRA_REMOTE_INPUT_HISTORY_ITEMS);
- assertEquals(1, messages.length);
- assertEquals(text, messages[0].getText());
- assertEquals(mimeType, messages[0].getMimeType());
- assertEquals(uri, messages[0].getUri());
- }
-
- @Test
- public void testRebuildWithRemoteInput_noExistingInputNoSpinner() {
- StatusBarNotification newSbn =
- mRemoteInputManager.rebuildNotificationWithRemoteInputInserted(
- mEntry, "A Reply", false, null, null);
- RemoteInputHistoryItem[] messages = (RemoteInputHistoryItem[]) newSbn.getNotification()
- .extras.getParcelableArray(Notification.EXTRA_REMOTE_INPUT_HISTORY_ITEMS);
- assertEquals(1, messages.length);
- assertEquals("A Reply", messages[0].getText());
- assertFalse(newSbn.getNotification().extras
- .getBoolean(Notification.EXTRA_SHOW_REMOTE_INPUT_SPINNER, false));
- assertTrue(newSbn.getNotification().extras
- .getBoolean(Notification.EXTRA_HIDE_SMART_REPLIES, false));
- }
-
- @Test
- public void testRebuildWithRemoteInput_noExistingInputWithSpinner() {
- StatusBarNotification newSbn =
- mRemoteInputManager.rebuildNotificationWithRemoteInputInserted(
- mEntry, "A Reply", true, null, null);
- RemoteInputHistoryItem[] messages = (RemoteInputHistoryItem[]) newSbn.getNotification()
- .extras.getParcelableArray(Notification.EXTRA_REMOTE_INPUT_HISTORY_ITEMS);
- assertEquals(1, messages.length);
- assertEquals("A Reply", messages[0].getText());
- assertTrue(newSbn.getNotification().extras
- .getBoolean(Notification.EXTRA_SHOW_REMOTE_INPUT_SPINNER, false));
- assertTrue(newSbn.getNotification().extras
- .getBoolean(Notification.EXTRA_HIDE_SMART_REPLIES, false));
- }
-
- @Test
- public void testRebuildWithRemoteInput_withExistingInput() {
- // Setup a notification entry with 1 remote input.
- StatusBarNotification newSbn =
- mRemoteInputManager.rebuildNotificationWithRemoteInputInserted(
- mEntry, "A Reply", false, null, null);
- NotificationEntry entry = new NotificationEntryBuilder()
- .setSbn(newSbn)
- .build();
-
- // Try rebuilding to add another reply.
- newSbn = mRemoteInputManager.rebuildNotificationWithRemoteInputInserted(
- entry, "Reply 2", true, null, null);
- RemoteInputHistoryItem[] messages = (RemoteInputHistoryItem[]) newSbn.getNotification()
- .extras.getParcelableArray(Notification.EXTRA_REMOTE_INPUT_HISTORY_ITEMS);
- assertEquals(2, messages.length);
- assertEquals("Reply 2", messages[0].getText());
- assertEquals("A Reply", messages[1].getText());
- }
-
- @Test
- public void testRebuildWithRemoteInput_withExistingInput_image() {
- // Setup a notification entry with 1 remote input.
- Uri uri = mock(Uri.class);
- String mimeType = "image/jpeg";
- String text = "image inserted";
- StatusBarNotification newSbn =
- mRemoteInputManager.rebuildNotificationWithRemoteInputInserted(
- mEntry, text, false, mimeType, uri);
- NotificationEntry entry = new NotificationEntryBuilder()
- .setSbn(newSbn)
- .build();
-
- // Try rebuilding to add another reply.
- newSbn = mRemoteInputManager.rebuildNotificationWithRemoteInputInserted(
- entry, "Reply 2", true, null, null);
- RemoteInputHistoryItem[] messages = (RemoteInputHistoryItem[]) newSbn.getNotification()
- .extras.getParcelableArray(Notification.EXTRA_REMOTE_INPUT_HISTORY_ITEMS);
- assertEquals(2, messages.length);
- assertEquals("Reply 2", messages[0].getText());
- assertEquals(text, messages[1].getText());
- assertEquals(mimeType, messages[1].getMimeType());
- assertEquals(uri, messages[1].getUri());
- }
-
- @Test
- public void testRebuildNotificationForCanceledSmartReplies() {
- // Try rebuilding to remove spinner and hide buttons.
- StatusBarNotification newSbn =
- mRemoteInputManager.rebuildNotificationForCanceledSmartReplies(mEntry);
- assertFalse(newSbn.getNotification().extras
- .getBoolean(Notification.EXTRA_SHOW_REMOTE_INPUT_SPINNER, false));
- assertTrue(newSbn.getNotification().extras
- .getBoolean(Notification.EXTRA_HIDE_SMART_REPLIES, false));
- }
-
-
private class TestableNotificationRemoteInputManager extends NotificationRemoteInputManager {
TestableNotificationRemoteInputManager(
Context context,
+ FeatureFlags featureFlags,
NotificationLockscreenUserManager lockscreenUserManager,
SmartReplyController smartReplyController,
NotificationEntryManager notificationEntryManager,
+ RemoteInputNotificationRebuilder rebuilder,
Lazy<Optional<StatusBar>> statusBarOptionalLazy,
StatusBarStateController statusBarStateController,
Handler mainHandler,
@@ -278,9 +202,11 @@
DumpManager dumpManager) {
super(
context,
+ featureFlags,
lockscreenUserManager,
smartReplyController,
notificationEntryManager,
+ rebuilder,
statusBarOptionalLazy,
statusBarStateController,
mainHandler,
@@ -297,14 +223,28 @@
mRemoteInputController = controller;
}
+ @NonNull
@Override
- protected void addLifetimeExtenders() {
- mRemoteInputActiveExtender = new RemoteInputActiveExtender();
- mRemoteInputHistoryExtender = new RemoteInputHistoryExtender();
- mSmartReplyHistoryExtender = new SmartReplyHistoryExtender();
- mLifetimeExtenders.add(mRemoteInputHistoryExtender);
- mLifetimeExtenders.add(mSmartReplyHistoryExtender);
- mLifetimeExtenders.add(mRemoteInputActiveExtender);
+ protected LegacyRemoteInputLifetimeExtender createLegacyRemoteInputLifetimeExtender(
+ Handler mainHandler,
+ NotificationEntryManager notificationEntryManager,
+ SmartReplyController smartReplyController) {
+ mLegacyRemoteInputLifetimeExtender = new FakeLegacyRemoteInputLifetimeExtender();
+ return mLegacyRemoteInputLifetimeExtender;
}
+
+ class FakeLegacyRemoteInputLifetimeExtender extends LegacyRemoteInputLifetimeExtender {
+
+ @Override
+ protected void addLifetimeExtenders() {
+ mRemoteInputActiveExtender = new RemoteInputActiveExtender();
+ mRemoteInputHistoryExtender = new RemoteInputHistoryExtender();
+ mSmartReplyHistoryExtender = new SmartReplyHistoryExtender();
+ mLifetimeExtenders.add(mRemoteInputHistoryExtender);
+ mLifetimeExtenders.add(mSmartReplyHistoryExtender);
+ mLifetimeExtenders.add(mRemoteInputActiveExtender);
+ }
+ }
+
}
}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/NotificationViewHierarchyManagerTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/NotificationViewHierarchyManagerTest.java
index 7fb7b86..cf58c63 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/NotificationViewHierarchyManagerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/NotificationViewHierarchyManagerTest.java
@@ -36,6 +36,7 @@
import androidx.test.filters.SmallTest;
import com.android.systemui.SysuiTestCase;
+import com.android.systemui.flags.FeatureFlags;
import com.android.systemui.plugins.statusbar.NotificationSwipeActionHelper;
import com.android.systemui.statusbar.notification.AssistantFeedbackController;
import com.android.systemui.statusbar.notification.DynamicChildBindController;
@@ -75,6 +76,7 @@
@Spy private FakeListContainer mListContainer = new FakeListContainer();
// Dependency mocks:
+ @Mock private FeatureFlags mFeatureFlags;
@Mock private NotificationEntryManager mEntryManager;
@Mock private NotificationLockscreenUserManager mLockscreenUserManager;
@Mock private NotificationGroupManagerLegacy mGroupManager;
@@ -101,10 +103,14 @@
when(mVisualStabilityManager.areGroupChangesAllowed()).thenReturn(true);
when(mVisualStabilityManager.isReorderingAllowed()).thenReturn(true);
+ when(mFeatureFlags.isNewNotifPipelineEnabled()).thenReturn(false);
+ when(mFeatureFlags.checkLegacyPipelineEnabled()).thenReturn(true);
+
mHelper = new NotificationTestHelper(mContext, mDependency, TestableLooper.get(this));
mViewHierarchyManager = new NotificationViewHierarchyManager(mContext,
- mHandler, mLockscreenUserManager, mGroupManager, mVisualStabilityManager,
+ mHandler, mFeatureFlags, mLockscreenUserManager, mGroupManager,
+ mVisualStabilityManager,
mock(StatusBarStateControllerImpl.class), mEntryManager,
mock(KeyguardBypassController.class),
Optional.of(mock(Bubbles.class)),
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/RemoteInputNotificationRebuilderTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/RemoteInputNotificationRebuilderTest.java
new file mode 100644
index 0000000..ce11d6a
--- /dev/null
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/RemoteInputNotificationRebuilderTest.java
@@ -0,0 +1,174 @@
+/*
+ * Copyright (C) 2021 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;
+
+import static junit.framework.Assert.assertEquals;
+import static junit.framework.Assert.assertFalse;
+import static junit.framework.Assert.assertTrue;
+
+import static org.mockito.Mockito.mock;
+
+import android.app.Notification;
+import android.app.RemoteInputHistoryItem;
+import android.net.Uri;
+import android.os.UserHandle;
+import android.service.notification.StatusBarNotification;
+import android.testing.AndroidTestingRunner;
+import android.testing.TestableLooper;
+
+import androidx.test.filters.SmallTest;
+
+import com.android.systemui.SysuiTestCase;
+import com.android.systemui.statusbar.notification.collection.NotificationEntry;
+import com.android.systemui.statusbar.notification.collection.NotificationEntryBuilder;
+import com.android.systemui.statusbar.notification.row.ExpandableNotificationRow;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
+
+@SmallTest
+@RunWith(AndroidTestingRunner.class)
+@TestableLooper.RunWithLooper
+public class RemoteInputNotificationRebuilderTest extends SysuiTestCase {
+ private static final String TEST_PACKAGE_NAME = "test";
+ private static final int TEST_UID = 0;
+ @Mock
+ private ExpandableNotificationRow mRow;
+
+ private RemoteInputNotificationRebuilder mRebuilder;
+ private NotificationEntry mEntry;
+
+ @Before
+ public void setUp() {
+ MockitoAnnotations.initMocks(this);
+
+ mRebuilder = new RemoteInputNotificationRebuilder(mContext);
+ mEntry = new NotificationEntryBuilder()
+ .setPkg(TEST_PACKAGE_NAME)
+ .setOpPkg(TEST_PACKAGE_NAME)
+ .setUid(TEST_UID)
+ .setNotification(new Notification())
+ .setUser(UserHandle.CURRENT)
+ .build();
+ mEntry.setRow(mRow);
+ }
+
+ @Test
+ public void testRebuildWithRemoteInput_noExistingInput_image() {
+ Uri uri = mock(Uri.class);
+ String mimeType = "image/jpeg";
+ String text = "image inserted";
+ StatusBarNotification newSbn =
+ mRebuilder.rebuildWithRemoteInputInserted(
+ mEntry, text, false, mimeType, uri);
+ RemoteInputHistoryItem[] messages = (RemoteInputHistoryItem[]) newSbn.getNotification()
+ .extras.getParcelableArray(Notification.EXTRA_REMOTE_INPUT_HISTORY_ITEMS);
+ assertEquals(1, messages.length);
+ assertEquals(text, messages[0].getText());
+ assertEquals(mimeType, messages[0].getMimeType());
+ assertEquals(uri, messages[0].getUri());
+ }
+
+ @Test
+ public void testRebuildWithRemoteInput_noExistingInputNoSpinner() {
+ StatusBarNotification newSbn =
+ mRebuilder.rebuildWithRemoteInputInserted(
+ mEntry, "A Reply", false, null, null);
+ RemoteInputHistoryItem[] messages = (RemoteInputHistoryItem[]) newSbn.getNotification()
+ .extras.getParcelableArray(Notification.EXTRA_REMOTE_INPUT_HISTORY_ITEMS);
+ assertEquals(1, messages.length);
+ assertEquals("A Reply", messages[0].getText());
+ assertFalse(newSbn.getNotification().extras
+ .getBoolean(Notification.EXTRA_SHOW_REMOTE_INPUT_SPINNER, false));
+ assertTrue(newSbn.getNotification().extras
+ .getBoolean(Notification.EXTRA_HIDE_SMART_REPLIES, false));
+ }
+
+ @Test
+ public void testRebuildWithRemoteInput_noExistingInputWithSpinner() {
+ StatusBarNotification newSbn =
+ mRebuilder.rebuildWithRemoteInputInserted(
+ mEntry, "A Reply", true, null, null);
+ RemoteInputHistoryItem[] messages = (RemoteInputHistoryItem[]) newSbn.getNotification()
+ .extras.getParcelableArray(Notification.EXTRA_REMOTE_INPUT_HISTORY_ITEMS);
+ assertEquals(1, messages.length);
+ assertEquals("A Reply", messages[0].getText());
+ assertTrue(newSbn.getNotification().extras
+ .getBoolean(Notification.EXTRA_SHOW_REMOTE_INPUT_SPINNER, false));
+ assertTrue(newSbn.getNotification().extras
+ .getBoolean(Notification.EXTRA_HIDE_SMART_REPLIES, false));
+ }
+
+ @Test
+ public void testRebuildWithRemoteInput_withExistingInput() {
+ // Setup a notification entry with 1 remote input.
+ StatusBarNotification newSbn =
+ mRebuilder.rebuildWithRemoteInputInserted(
+ mEntry, "A Reply", false, null, null);
+ NotificationEntry entry = new NotificationEntryBuilder()
+ .setSbn(newSbn)
+ .build();
+
+ // Try rebuilding to add another reply.
+ newSbn = mRebuilder.rebuildWithRemoteInputInserted(
+ entry, "Reply 2", true, null, null);
+ RemoteInputHistoryItem[] messages = (RemoteInputHistoryItem[]) newSbn.getNotification()
+ .extras.getParcelableArray(Notification.EXTRA_REMOTE_INPUT_HISTORY_ITEMS);
+ assertEquals(2, messages.length);
+ assertEquals("Reply 2", messages[0].getText());
+ assertEquals("A Reply", messages[1].getText());
+ }
+
+ @Test
+ public void testRebuildWithRemoteInput_withExistingInput_image() {
+ // Setup a notification entry with 1 remote input.
+ Uri uri = mock(Uri.class);
+ String mimeType = "image/jpeg";
+ String text = "image inserted";
+ StatusBarNotification newSbn =
+ mRebuilder.rebuildWithRemoteInputInserted(
+ mEntry, text, false, mimeType, uri);
+ NotificationEntry entry = new NotificationEntryBuilder()
+ .setSbn(newSbn)
+ .build();
+
+ // Try rebuilding to add another reply.
+ newSbn = mRebuilder.rebuildWithRemoteInputInserted(
+ entry, "Reply 2", true, null, null);
+ RemoteInputHistoryItem[] messages = (RemoteInputHistoryItem[]) newSbn.getNotification()
+ .extras.getParcelableArray(Notification.EXTRA_REMOTE_INPUT_HISTORY_ITEMS);
+ assertEquals(2, messages.length);
+ assertEquals("Reply 2", messages[0].getText());
+ assertEquals(text, messages[1].getText());
+ assertEquals(mimeType, messages[1].getMimeType());
+ assertEquals(uri, messages[1].getUri());
+ }
+
+ @Test
+ public void testRebuildNotificationForCanceledSmartReplies() {
+ // Try rebuilding to remove spinner and hide buttons.
+ StatusBarNotification newSbn =
+ mRebuilder.rebuildForCanceledSmartReplies(mEntry);
+ assertFalse(newSbn.getNotification().extras
+ .getBoolean(Notification.EXTRA_SHOW_REMOTE_INPUT_SPINNER, false));
+ assertTrue(newSbn.getNotification().extras
+ .getBoolean(Notification.EXTRA_HIDE_SMART_REPLIES, false));
+ }
+}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/SmartReplyControllerTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/SmartReplyControllerTest.java
index 837d71f..99c965a 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/SmartReplyControllerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/SmartReplyControllerTest.java
@@ -39,6 +39,7 @@
import com.android.systemui.R;
import com.android.systemui.SysuiTestCase;
import com.android.systemui.dump.DumpManager;
+import com.android.systemui.flags.FeatureFlags;
import com.android.systemui.plugins.statusbar.StatusBarStateController;
import com.android.systemui.statusbar.notification.NotificationEntryManager;
import com.android.systemui.statusbar.notification.collection.NotificationEntry;
@@ -86,14 +87,20 @@
mDependency.injectTestDependency(NotificationEntryManager.class,
mNotificationEntryManager);
- mSmartReplyController = new SmartReplyController(mNotificationEntryManager,
- mIStatusBarService, mClickNotifier);
+ mSmartReplyController = new SmartReplyController(
+ mock(DumpManager.class),
+ mNotificationEntryManager,
+ mIStatusBarService,
+ mClickNotifier);
mDependency.injectTestDependency(SmartReplyController.class,
mSmartReplyController);
mRemoteInputManager = new NotificationRemoteInputManager(mContext,
+ mock(FeatureFlags.class),
mock(NotificationLockscreenUserManager.class), mSmartReplyController,
- mNotificationEntryManager, () -> Optional.of(mock(StatusBar.class)),
+ mNotificationEntryManager,
+ new RemoteInputNotificationRebuilder(mContext),
+ () -> Optional.of(mock(StatusBar.class)),
mStatusBarStateController,
Handler.createAsync(Looper.myLooper()),
mRemoteInputUriController,
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/NotifCollectionTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/NotifCollectionTest.java
index ebeb591..f08a74a 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/NotifCollectionTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/NotifCollectionTest.java
@@ -35,6 +35,7 @@
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertTrue;
import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.ArgumentMatchers.anyBoolean;
import static org.mockito.ArgumentMatchers.anyInt;
import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.Mockito.clearInvocations;
@@ -50,6 +51,7 @@
import android.annotation.Nullable;
import android.app.Notification;
+import android.os.Handler;
import android.os.RemoteException;
import android.service.notification.NotificationListenerService.Ranking;
import android.service.notification.NotificationListenerService.RankingMap;
@@ -77,6 +79,7 @@
import com.android.systemui.statusbar.notification.collection.coalescer.GroupCoalescer.BatchableNotificationHandler;
import com.android.systemui.statusbar.notification.collection.notifcollection.CollectionReadyForBuildListener;
import com.android.systemui.statusbar.notification.collection.notifcollection.DismissedByUserStats;
+import com.android.systemui.statusbar.notification.collection.notifcollection.InternalNotifUpdater;
import com.android.systemui.statusbar.notification.collection.notifcollection.NotifCollectionListener;
import com.android.systemui.statusbar.notification.collection.notifcollection.NotifCollectionLogger;
import com.android.systemui.statusbar.notification.collection.notifcollection.NotifDismissInterceptor;
@@ -107,6 +110,7 @@
@Mock private FeatureFlags mFeatureFlags;
@Mock private NotifCollectionLogger mLogger;
@Mock private LogBufferEulogizer mEulogizer;
+ @Mock private Handler mMainHandler;
@Mock private GroupCoalescer mGroupCoalescer;
@Spy private RecordingCollectionListener mCollectionListener;
@@ -152,6 +156,7 @@
mClock,
mFeatureFlags,
mLogger,
+ mMainHandler,
mEulogizer,
mock(DumpManager.class));
mCollection.attach(mGroupCoalescer);
@@ -1322,6 +1327,78 @@
verify(mCollectionListener, never()).onEntryRemoved(any(NotificationEntry.class), anyInt());
}
+ private Runnable getInternalNotifUpdateRunnable(StatusBarNotification sbn) {
+ InternalNotifUpdater updater = mCollection.getInternalNotifUpdater("Test");
+ updater.onInternalNotificationUpdate(sbn, "reason");
+ ArgumentCaptor<Runnable> runnableCaptor = ArgumentCaptor.forClass(Runnable.class);
+ verify(mMainHandler).post(runnableCaptor.capture());
+ return runnableCaptor.getValue();
+ }
+
+ @Test
+ public void testGetInternalNotifUpdaterPostsToMainHandler() {
+ InternalNotifUpdater updater = mCollection.getInternalNotifUpdater("Test");
+ updater.onInternalNotificationUpdate(mock(StatusBarNotification.class), "reason");
+ verify(mMainHandler).post(any());
+ }
+
+ @Test
+ public void testSecondPostCallsUpdateWithTrue() {
+ // GIVEN a pipeline with one notification
+ NotifEvent notifEvent = mNoMan.postNotif(buildNotif(TEST_PACKAGE, 47, "myTag"));
+ NotificationEntry entry = mCollectionListener.getEntry(notifEvent.key);
+
+ // KNOWING that it already called listener methods once
+ verify(mCollectionListener).onEntryAdded(eq(entry));
+ verify(mCollectionListener).onRankingApplied();
+
+ // WHEN we update the notification via the system
+ mNoMan.postNotif(buildNotif(TEST_PACKAGE, 47, "myTag"));
+
+ // THEN entry updated gets called, added does not, and ranking is called again
+ verify(mCollectionListener).onEntryUpdated(eq(entry));
+ verify(mCollectionListener).onEntryUpdated(eq(entry), eq(true));
+ verify(mCollectionListener).onEntryAdded((entry));
+ verify(mCollectionListener, times(2)).onRankingApplied();
+ }
+
+ @Test
+ public void testInternalNotifUpdaterCallsUpdate() {
+ // GIVEN a pipeline with one notification
+ NotifEvent notifEvent = mNoMan.postNotif(buildNotif(TEST_PACKAGE, 47, "myTag"));
+ NotificationEntry entry = mCollectionListener.getEntry(notifEvent.key);
+
+ // KNOWING that it will call listener methods once
+ verify(mCollectionListener).onEntryAdded(eq(entry));
+ verify(mCollectionListener).onRankingApplied();
+
+ // WHEN we update that notification internally
+ StatusBarNotification sbn = notifEvent.sbn;
+ getInternalNotifUpdateRunnable(sbn).run();
+
+ // THEN only entry updated gets called a second time
+ verify(mCollectionListener).onEntryAdded(eq(entry));
+ verify(mCollectionListener).onRankingApplied();
+ verify(mCollectionListener).onEntryUpdated(eq(entry));
+ verify(mCollectionListener).onEntryUpdated(eq(entry), eq(false));
+ }
+
+ @Test
+ public void testInternalNotifUpdaterIgnoresNew() {
+ // GIVEN a pipeline without any notifications
+ StatusBarNotification sbn = buildNotif(TEST_PACKAGE, 47, "myTag").build().getSbn();
+
+ // WHEN we internally update an unknown notification
+ getInternalNotifUpdateRunnable(sbn).run();
+
+ // THEN only entry updated gets called a second time
+ verify(mCollectionListener, never()).onEntryAdded(any());
+ verify(mCollectionListener, never()).onRankingUpdate(any());
+ verify(mCollectionListener, never()).onRankingApplied();
+ verify(mCollectionListener, never()).onEntryUpdated(any());
+ verify(mCollectionListener, never()).onEntryUpdated(any(), anyBoolean());
+ }
+
private static NotificationEntryBuilder buildNotif(String pkg, int id, String tag) {
return new NotificationEntryBuilder()
.setPkg(pkg)
@@ -1372,6 +1449,11 @@
}
@Override
+ public void onEntryUpdated(NotificationEntry entry, boolean fromSystem) {
+ onEntryUpdated(entry);
+ }
+
+ @Override
public void onEntryRemoved(NotificationEntry entry, int reason) {
}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/ShadeListBuilderTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/ShadeListBuilderTest.java
index e9e6718..190c352 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/ShadeListBuilderTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/ShadeListBuilderTest.java
@@ -56,6 +56,7 @@
import com.android.systemui.statusbar.notification.collection.listbuilder.OnBeforeSortListener;
import com.android.systemui.statusbar.notification.collection.listbuilder.OnBeforeTransformGroupsListener;
import com.android.systemui.statusbar.notification.collection.listbuilder.ShadeListBuilderLogger;
+import com.android.systemui.statusbar.notification.collection.listbuilder.pluggable.Invalidator;
import com.android.systemui.statusbar.notification.collection.listbuilder.pluggable.NotifComparator;
import com.android.systemui.statusbar.notification.collection.listbuilder.pluggable.NotifFilter;
import com.android.systemui.statusbar.notification.collection.listbuilder.pluggable.NotifPromoter;
@@ -847,11 +848,13 @@
NotifPromoter idPromoter = new IdPromoter(4);
NotifSectioner section = new PackageSectioner(PACKAGE_1);
NotifComparator hypeComparator = new HypeComparator(PACKAGE_2);
+ Invalidator preRenderInvalidator = new Invalidator("PreRenderInvalidator") {};
mListBuilder.addPreGroupFilter(packageFilter);
mListBuilder.addPromoter(idPromoter);
mListBuilder.setSectioners(singletonList(section));
mListBuilder.setComparators(singletonList(hypeComparator));
+ mListBuilder.addPreRenderInvalidator(preRenderInvalidator);
// GIVEN a set of random notifs
addNotif(0, PACKAGE_1);
@@ -876,6 +879,10 @@
clearInvocations(mOnRenderListListener);
hypeComparator.invalidateList();
verify(mOnRenderListListener).onRenderList(anyList());
+
+ clearInvocations(mOnRenderListListener);
+ preRenderInvalidator.invalidateList();
+ verify(mOnRenderListListener).onRenderList(anyList());
}
@Test
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/coordinator/RemoteInputCoordinatorTest.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/coordinator/RemoteInputCoordinatorTest.kt
new file mode 100644
index 0000000..0ce6ada
--- /dev/null
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/coordinator/RemoteInputCoordinatorTest.kt
@@ -0,0 +1,145 @@
+/*
+ * Copyright (C) 2021 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.notification.collection.coordinator
+
+import android.os.Handler
+import android.service.notification.StatusBarNotification
+import android.testing.AndroidTestingRunner
+import android.testing.TestableLooper.RunWithLooper
+import androidx.test.filters.SmallTest
+import com.android.systemui.SysuiTestCase
+import com.android.systemui.dump.DumpManager
+import com.android.systemui.statusbar.NotificationRemoteInputManager
+import com.android.systemui.statusbar.NotificationRemoteInputManager.RemoteInputListener
+import com.android.systemui.statusbar.RemoteInputNotificationRebuilder
+import com.android.systemui.statusbar.SmartReplyController
+import com.android.systemui.statusbar.notification.collection.NotifPipeline
+import com.android.systemui.statusbar.notification.collection.NotificationEntry
+import com.android.systemui.statusbar.notification.collection.NotificationEntryBuilder
+import com.android.systemui.statusbar.notification.collection.notifcollection.InternalNotifUpdater
+import com.android.systemui.statusbar.notification.collection.notifcollection.NotifCollectionListener
+import com.android.systemui.statusbar.notification.collection.notifcollection.NotifLifetimeExtender
+import com.android.systemui.statusbar.notification.collection.notifcollection.NotifLifetimeExtender.OnEndLifetimeExtensionCallback
+import com.android.systemui.util.mockito.any
+import com.android.systemui.util.mockito.withArgCaptor
+import com.google.common.truth.Truth.assertThat
+import org.junit.Before
+import org.junit.Test
+import org.junit.runner.RunWith
+import org.mockito.Mock
+import org.mockito.Mockito.`when`
+import org.mockito.Mockito.never
+import org.mockito.Mockito.verify
+import org.mockito.MockitoAnnotations.initMocks
+
+@SmallTest
+@RunWith(AndroidTestingRunner::class)
+@RunWithLooper
+class RemoteInputCoordinatorTest : SysuiTestCase() {
+ private lateinit var coordinator: RemoteInputCoordinator
+ private lateinit var listener: RemoteInputListener
+ private lateinit var collectionListener: NotifCollectionListener
+
+ private lateinit var entry1: NotificationEntry
+ private lateinit var entry2: NotificationEntry
+
+ @Mock private lateinit var lifetimeExtensionCallback: OnEndLifetimeExtensionCallback
+ @Mock private lateinit var rebuilder: RemoteInputNotificationRebuilder
+ @Mock private lateinit var remoteInputManager: NotificationRemoteInputManager
+ @Mock private lateinit var mainHandler: Handler
+ @Mock private lateinit var smartReplyController: SmartReplyController
+ @Mock private lateinit var pipeline: NotifPipeline
+ @Mock private lateinit var notifUpdater: InternalNotifUpdater
+ @Mock private lateinit var dumpManager: DumpManager
+ @Mock private lateinit var sbn: StatusBarNotification
+
+ @Before
+ fun setUp() {
+ initMocks(this)
+ coordinator = RemoteInputCoordinator(
+ dumpManager,
+ rebuilder,
+ remoteInputManager,
+ mainHandler,
+ smartReplyController
+ )
+ `when`(pipeline.addNotificationLifetimeExtender(any())).thenAnswer {
+ (it.arguments[0] as NotifLifetimeExtender).setCallback(lifetimeExtensionCallback)
+ }
+ `when`(pipeline.getInternalNotifUpdater(any())).thenReturn(notifUpdater)
+ coordinator.attach(pipeline)
+ listener = withArgCaptor {
+ verify(remoteInputManager).setRemoteInputListener(capture())
+ }
+ collectionListener = withArgCaptor {
+ verify(pipeline).addCollectionListener(capture())
+ }
+ entry1 = NotificationEntryBuilder().setId(1).build()
+ entry2 = NotificationEntryBuilder().setId(2).build()
+ `when`(rebuilder.rebuildForCanceledSmartReplies(any())).thenReturn(sbn)
+ `when`(rebuilder.rebuildForRemoteInputReply(any())).thenReturn(sbn)
+ `when`(rebuilder.rebuildForSendingSmartReply(any(), any())).thenReturn(sbn)
+ }
+
+ val remoteInputActiveExtender get() = coordinator.mRemoteInputActiveExtender
+ val remoteInputHistoryExtender get() = coordinator.mRemoteInputHistoryExtender
+ val smartReplyHistoryExtender get() = coordinator.mSmartReplyHistoryExtender
+
+ @Test
+ fun testRemoteInputActive() {
+ `when`(remoteInputManager.isRemoteInputActive(entry1)).thenReturn(true)
+ assertThat(remoteInputActiveExtender.shouldExtendLifetime(entry1, 0)).isTrue()
+ assertThat(remoteInputHistoryExtender.shouldExtendLifetime(entry1, 0)).isFalse()
+ assertThat(smartReplyHistoryExtender.shouldExtendLifetime(entry1, 0)).isFalse()
+ assertThat(listener.isNotificationKeptForRemoteInputHistory(entry1.key)).isFalse()
+ }
+
+ @Test
+ fun testRemoteInputHistory() {
+ `when`(remoteInputManager.shouldKeepForRemoteInputHistory(entry1)).thenReturn(true)
+ assertThat(remoteInputActiveExtender.shouldExtendLifetime(entry1, 0)).isFalse()
+ assertThat(remoteInputHistoryExtender.shouldExtendLifetime(entry1, 0)).isTrue()
+ assertThat(smartReplyHistoryExtender.shouldExtendLifetime(entry1, 0)).isFalse()
+ assertThat(listener.isNotificationKeptForRemoteInputHistory(entry1.key)).isTrue()
+ }
+
+ @Test
+ fun testSmartReplyHistory() {
+ `when`(remoteInputManager.shouldKeepForSmartReplyHistory(entry1)).thenReturn(true)
+ assertThat(remoteInputActiveExtender.shouldExtendLifetime(entry1, 0)).isFalse()
+ assertThat(remoteInputHistoryExtender.shouldExtendLifetime(entry1, 0)).isFalse()
+ assertThat(smartReplyHistoryExtender.shouldExtendLifetime(entry1, 0)).isTrue()
+ assertThat(listener.isNotificationKeptForRemoteInputHistory(entry1.key)).isTrue()
+ }
+
+ @Test
+ fun testNotificationWithRemoteInputActiveIsRemovedOnCollapse() {
+ `when`(remoteInputManager.isRemoteInputActive(entry1)).thenReturn(true)
+ assertThat(remoteInputActiveExtender.isExtending(entry1.key)).isFalse()
+
+ // Nothing should happen on panel collapse before we start extending the lifetime
+ listener.onPanelCollapsed()
+ assertThat(remoteInputActiveExtender.isExtending(entry1.key)).isFalse()
+ verify(lifetimeExtensionCallback, never()).onEndLifetimeExtension(any(), any())
+
+ // Start extending lifetime & validate that the extension is ended
+ assertThat(remoteInputActiveExtender.shouldExtendLifetime(entry1, 0)).isTrue()
+ assertThat(remoteInputActiveExtender.isExtending(entry1.key)).isTrue()
+ listener.onPanelCollapsed()
+ verify(lifetimeExtensionCallback).onEndLifetimeExtension(remoteInputActiveExtender, entry1)
+ assertThat(remoteInputActiveExtender.isExtending(entry1.key)).isFalse()
+ }
+}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/coordinator/SensitiveContentCoordinatorTest.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/coordinator/SensitiveContentCoordinatorTest.kt
new file mode 100644
index 0000000..5fd4174
--- /dev/null
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/coordinator/SensitiveContentCoordinatorTest.kt
@@ -0,0 +1,209 @@
+/*
+ * Copyright (C) 2021 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.notification.collection.coordinator
+
+import android.os.UserHandle
+import android.service.notification.StatusBarNotification
+import androidx.test.filters.SmallTest
+import com.android.systemui.SysuiTestCase
+import com.android.systemui.statusbar.NotificationLockscreenUserManager
+import com.android.systemui.statusbar.notification.DynamicPrivacyController
+import com.android.systemui.statusbar.notification.collection.ListEntry
+import com.android.systemui.statusbar.notification.collection.NotifPipeline
+import com.android.systemui.statusbar.notification.collection.NotificationEntry
+import com.android.systemui.statusbar.notification.collection.listbuilder.OnBeforeRenderListListener
+import com.android.systemui.statusbar.notification.collection.listbuilder.pluggable.Invalidator
+import com.android.systemui.statusbar.notification.collection.listbuilder.pluggable.Pluggable
+import com.android.systemui.util.mockito.withArgCaptor
+import com.android.systemui.util.mockito.mock
+import org.junit.Test
+import org.mockito.Mockito.verify
+import org.mockito.Mockito.`when` as whenever
+
+@SmallTest
+class SensitiveContentCoordinatorTest : SysuiTestCase() {
+
+ val dynamicPrivacyController: DynamicPrivacyController = mock()
+ val lockscreenUserManager: NotificationLockscreenUserManager = mock()
+ val pipeline: NotifPipeline = mock()
+
+ val coordinator: SensitiveContentCoordinator = SensitiveContentCoordinatorModule
+ .provideCoordinator(dynamicPrivacyController, lockscreenUserManager)
+
+ @Test
+ fun onDynamicPrivacyChanged_invokeInvalidationListener() {
+ coordinator.attach(pipeline)
+ val invalidator = withArgCaptor<Invalidator> {
+ verify(pipeline).addPreRenderInvalidator(capture())
+ }
+ val dynamicPrivacyListener = withArgCaptor<DynamicPrivacyController.Listener> {
+ verify(dynamicPrivacyController).addListener(capture())
+ }
+
+ val invalidationListener = mock<Pluggable.PluggableListener<Invalidator>>()
+ invalidator.setInvalidationListener(invalidationListener)
+
+ dynamicPrivacyListener.onDynamicPrivacyChanged()
+
+ verify(invalidationListener).onPluggableInvalidated(invalidator)
+ }
+
+ @Test
+ fun onBeforeRenderList_deviceUnlocked_notifDoesNotNeedRedaction() {
+ coordinator.attach(pipeline)
+ val onBeforeRenderListListener = withArgCaptor<OnBeforeRenderListListener> {
+ verify(pipeline).addOnBeforeRenderListListener(capture())
+ }
+
+ whenever(lockscreenUserManager.currentUserId).thenReturn(1)
+ whenever(lockscreenUserManager.isLockscreenPublicMode(1)).thenReturn(false)
+ whenever(lockscreenUserManager.userAllowsPrivateNotificationsInPublic(1)).thenReturn(true)
+ whenever(dynamicPrivacyController.isDynamicallyUnlocked).thenReturn(false)
+ val entry = fakeNotification(1, false)
+
+ onBeforeRenderListListener.onBeforeRenderList(listOf(entry))
+
+ verify(entry.representativeEntry!!).setSensitive(false, false)
+ }
+
+ @Test
+ fun onBeforeRenderList_deviceUnlocked_notifWouldNeedRedaction() {
+ coordinator.attach(pipeline)
+ val onBeforeRenderListListener = withArgCaptor<OnBeforeRenderListListener> {
+ verify(pipeline).addOnBeforeRenderListListener(capture())
+ }
+
+ whenever(lockscreenUserManager.currentUserId).thenReturn(1)
+ whenever(lockscreenUserManager.isLockscreenPublicMode(1)).thenReturn(false)
+ whenever(lockscreenUserManager.userAllowsPrivateNotificationsInPublic(1)).thenReturn(true)
+ whenever(dynamicPrivacyController.isDynamicallyUnlocked).thenReturn(false)
+ val entry = fakeNotification(1, true)
+
+ onBeforeRenderListListener.onBeforeRenderList(listOf(entry))
+
+ verify(entry.representativeEntry!!).setSensitive(false, false)
+ }
+
+ @Test
+ fun onBeforeRenderList_deviceLocked_userAllowsPublicNotifs() {
+ coordinator.attach(pipeline)
+ val onBeforeRenderListListener = withArgCaptor<OnBeforeRenderListListener> {
+ verify(pipeline).addOnBeforeRenderListListener(capture())
+ }
+
+ whenever(lockscreenUserManager.currentUserId).thenReturn(1)
+ whenever(lockscreenUserManager.isLockscreenPublicMode(1)).thenReturn(true)
+ whenever(lockscreenUserManager.userAllowsPrivateNotificationsInPublic(1)).thenReturn(true)
+ whenever(dynamicPrivacyController.isDynamicallyUnlocked).thenReturn(false)
+ val entry = fakeNotification(1, false)
+
+ onBeforeRenderListListener.onBeforeRenderList(listOf(entry))
+
+ verify(entry.representativeEntry!!).setSensitive(false, false)
+ }
+
+ @Test
+ fun onBeforeRenderList_deviceLocked_userDisallowsPublicNotifs_notifDoesNotNeedRedaction() {
+ coordinator.attach(pipeline)
+ val onBeforeRenderListListener = withArgCaptor<OnBeforeRenderListListener> {
+ verify(pipeline).addOnBeforeRenderListListener(capture())
+ }
+
+ whenever(lockscreenUserManager.currentUserId).thenReturn(1)
+ whenever(lockscreenUserManager.isLockscreenPublicMode(1)).thenReturn(true)
+ whenever(lockscreenUserManager.userAllowsPrivateNotificationsInPublic(1)).thenReturn(false)
+ whenever(dynamicPrivacyController.isDynamicallyUnlocked).thenReturn(false)
+ val entry = fakeNotification(1, false)
+
+ onBeforeRenderListListener.onBeforeRenderList(listOf(entry))
+
+ verify(entry.representativeEntry!!).setSensitive(false, true)
+ }
+
+ @Test
+ fun onBeforeRenderList_deviceLocked_notifNeedsRedaction() {
+ coordinator.attach(pipeline)
+ val onBeforeRenderListListener = withArgCaptor<OnBeforeRenderListListener> {
+ verify(pipeline).addOnBeforeRenderListListener(capture())
+ }
+
+ whenever(lockscreenUserManager.currentUserId).thenReturn(1)
+ whenever(lockscreenUserManager.isLockscreenPublicMode(1)).thenReturn(true)
+ whenever(lockscreenUserManager.userAllowsPrivateNotificationsInPublic(1)).thenReturn(false)
+ whenever(dynamicPrivacyController.isDynamicallyUnlocked).thenReturn(false)
+ val entry = fakeNotification(1, true)
+
+ onBeforeRenderListListener.onBeforeRenderList(listOf(entry))
+
+ verify(entry.representativeEntry!!).setSensitive(true, true)
+ }
+
+ @Test
+ fun onBeforeRenderList_deviceDynamicallyUnlocked_notifNeedsRedaction() {
+ coordinator.attach(pipeline)
+ val onBeforeRenderListListener = withArgCaptor<OnBeforeRenderListListener> {
+ verify(pipeline).addOnBeforeRenderListListener(capture())
+ }
+
+ whenever(lockscreenUserManager.currentUserId).thenReturn(1)
+ whenever(lockscreenUserManager.isLockscreenPublicMode(1)).thenReturn(true)
+ whenever(lockscreenUserManager.userAllowsPrivateNotificationsInPublic(1)).thenReturn(false)
+ whenever(dynamicPrivacyController.isDynamicallyUnlocked).thenReturn(true)
+ val entry = fakeNotification(1, true)
+
+ onBeforeRenderListListener.onBeforeRenderList(listOf(entry))
+
+ verify(entry.representativeEntry!!).setSensitive(false, true)
+ }
+
+ @Test
+ fun onBeforeRenderList_deviceDynamicallyUnlocked_notifUserNeedsWorkChallenge() {
+ coordinator.attach(pipeline)
+ val onBeforeRenderListListener = withArgCaptor<OnBeforeRenderListListener> {
+ verify(pipeline).addOnBeforeRenderListListener(capture())
+ }
+
+ whenever(lockscreenUserManager.currentUserId).thenReturn(1)
+ whenever(lockscreenUserManager.isLockscreenPublicMode(1)).thenReturn(true)
+ whenever(lockscreenUserManager.userAllowsPrivateNotificationsInPublic(1)).thenReturn(false)
+ whenever(dynamicPrivacyController.isDynamicallyUnlocked).thenReturn(true)
+ whenever(lockscreenUserManager.needsSeparateWorkChallenge(2)).thenReturn(true)
+
+ val entry = fakeNotification(2, true)
+
+ onBeforeRenderListListener.onBeforeRenderList(listOf(entry))
+
+ verify(entry.representativeEntry!!).setSensitive(true, true)
+ }
+
+ private fun fakeNotification(notifUserId: Int, needsRedaction: Boolean): ListEntry {
+ val mockUserHandle = mock<UserHandle>().apply {
+ whenever(identifier).thenReturn(notifUserId)
+ }
+ val mockSbn: StatusBarNotification = mock<StatusBarNotification>().apply {
+ whenever(user).thenReturn(mockUserHandle)
+ }
+ val mockEntry = mock<NotificationEntry>().apply {
+ whenever(sbn).thenReturn(mockSbn)
+ }
+ whenever(lockscreenUserManager.needsRedaction(mockEntry)).thenReturn(needsRedaction)
+ whenever(mockEntry.rowExists()).thenReturn(true)
+ return object : ListEntry("key", 0) {
+ override fun getRepresentativeEntry(): NotificationEntry = mockEntry
+ }
+ }
+}
\ No newline at end of file
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/coordinator/ShadeEventCoordinatorTest.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/coordinator/ShadeEventCoordinatorTest.kt
new file mode 100644
index 0000000..5915cd7
--- /dev/null
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/coordinator/ShadeEventCoordinatorTest.kt
@@ -0,0 +1,106 @@
+/*
+ * Copyright (C) 2021 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.notification.collection.coordinator
+
+import android.service.notification.NotificationListenerService.REASON_APP_CANCEL
+import android.service.notification.NotificationListenerService.REASON_CANCEL
+import android.testing.AndroidTestingRunner
+import android.testing.TestableLooper.RunWithLooper
+import androidx.test.filters.SmallTest
+import com.android.systemui.SysuiTestCase
+import com.android.systemui.statusbar.notification.collection.NotifPipeline
+import com.android.systemui.statusbar.notification.collection.NotificationEntry
+import com.android.systemui.statusbar.notification.collection.NotificationEntryBuilder
+import com.android.systemui.statusbar.notification.collection.listbuilder.OnBeforeRenderListListener
+import com.android.systemui.statusbar.notification.collection.notifcollection.NotifCollectionListener
+import com.android.systemui.util.mockito.argumentCaptor
+import org.junit.Before
+import org.junit.Test
+import org.junit.runner.RunWith
+import org.mockito.Mock
+import org.mockito.Mockito.never
+import org.mockito.Mockito.verify
+import org.mockito.MockitoAnnotations.initMocks
+
+@SmallTest
+@RunWith(AndroidTestingRunner::class)
+@RunWithLooper
+class ShadeEventCoordinatorTest : SysuiTestCase() {
+ private lateinit var coordinator: ShadeEventCoordinator
+ private lateinit var notifCollectionListener: NotifCollectionListener
+ private lateinit var onBeforeRenderListListener: OnBeforeRenderListListener
+
+ private lateinit var entry1: NotificationEntry
+ private lateinit var entry2: NotificationEntry
+
+ @Mock private lateinit var pipeline: NotifPipeline
+ @Mock private lateinit var logger: ShadeEventCoordinatorLogger
+ @Mock private lateinit var notifRemovedByUserCallback: Runnable
+ @Mock private lateinit var shadeEmptiedCallback: Runnable
+
+ @Before
+ fun setUp() {
+ initMocks(this)
+ coordinator = ShadeEventCoordinator(logger)
+ coordinator.attach(pipeline)
+ notifCollectionListener = argumentCaptor<NotifCollectionListener>().let {
+ verify(pipeline).addCollectionListener(it.capture())
+ it.value!!
+ }
+ onBeforeRenderListListener = argumentCaptor<OnBeforeRenderListListener>().let {
+ verify(pipeline).addOnBeforeRenderListListener(it.capture())
+ it.value!!
+ }
+ coordinator.setNotifRemovedByUserCallback(notifRemovedByUserCallback)
+ coordinator.setShadeEmptiedCallback(shadeEmptiedCallback)
+ entry1 = NotificationEntryBuilder().setId(1).build()
+ entry2 = NotificationEntryBuilder().setId(2).build()
+ }
+
+ @Test
+ fun testUserCancelLastNotification() {
+ notifCollectionListener.onEntryRemoved(entry1, REASON_CANCEL)
+ verify(shadeEmptiedCallback, never()).run()
+ verify(notifRemovedByUserCallback, never()).run()
+ onBeforeRenderListListener.onBeforeRenderList(listOf())
+ verify(shadeEmptiedCallback).run()
+ verify(notifRemovedByUserCallback).run()
+ }
+
+ @Test
+ fun testAppCancelLastNotification() {
+ notifCollectionListener.onEntryRemoved(entry1, REASON_APP_CANCEL)
+ onBeforeRenderListListener.onBeforeRenderList(listOf())
+ verify(shadeEmptiedCallback).run()
+ verify(notifRemovedByUserCallback, never()).run()
+ }
+
+ @Test
+ fun testUserCancelOneOfTwoNotifications() {
+ notifCollectionListener.onEntryRemoved(entry1, REASON_CANCEL)
+ onBeforeRenderListListener.onBeforeRenderList(listOf(entry2))
+ verify(shadeEmptiedCallback, never()).run()
+ verify(notifRemovedByUserCallback).run()
+ }
+
+ @Test
+ fun testAppCancelOneOfTwoNotifications() {
+ notifCollectionListener.onEntryRemoved(entry1, REASON_APP_CANCEL)
+ onBeforeRenderListListener.onBeforeRenderList(listOf(entry2))
+ verify(shadeEmptiedCallback, never()).run()
+ verify(notifRemovedByUserCallback, never()).run()
+ }
+}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/notifcollection/SelfTrackingLifetimeExtenderTest.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/notifcollection/SelfTrackingLifetimeExtenderTest.kt
new file mode 100644
index 0000000..37ad835
--- /dev/null
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/notifcollection/SelfTrackingLifetimeExtenderTest.kt
@@ -0,0 +1,230 @@
+/*
+ * Copyright (C) 2021 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.notification.collection.notifcollection
+
+import android.os.Handler
+import android.testing.AndroidTestingRunner
+import android.testing.TestableLooper.RunWithLooper
+import androidx.test.filters.SmallTest
+import com.android.systemui.SysuiTestCase
+import com.android.systemui.statusbar.notification.collection.NotificationEntry
+import com.android.systemui.statusbar.notification.collection.NotificationEntryBuilder
+import com.android.systemui.statusbar.notification.collection.notifcollection.NotifLifetimeExtender.OnEndLifetimeExtensionCallback
+import com.android.systemui.util.mockito.withArgCaptor
+import com.google.common.truth.Truth.assertThat
+import org.junit.Before
+import org.junit.Test
+import org.junit.runner.RunWith
+import org.mockito.Mock
+import org.mockito.Mockito.`when`
+import org.mockito.Mockito.any
+import org.mockito.Mockito.anyLong
+import org.mockito.Mockito.eq
+import org.mockito.Mockito.never
+import org.mockito.Mockito.times
+import org.mockito.Mockito.verify
+import org.mockito.MockitoAnnotations.initMocks
+import java.util.function.Consumer
+import java.util.function.Predicate
+
+@SmallTest
+@RunWith(AndroidTestingRunner::class)
+@RunWithLooper
+class SelfTrackingLifetimeExtenderTest : SysuiTestCase() {
+ private lateinit var extender: TestableSelfTrackingLifetimeExtender
+
+ private lateinit var entry1: NotificationEntry
+ private lateinit var entry2: NotificationEntry
+
+ @Mock
+ private lateinit var callback: OnEndLifetimeExtensionCallback
+ @Mock
+ private lateinit var mainHandler: Handler
+ @Mock
+ private lateinit var shouldExtend: Predicate<NotificationEntry>
+ @Mock
+ private lateinit var onStarted: Consumer<NotificationEntry>
+ @Mock
+ private lateinit var onCanceled: Consumer<NotificationEntry>
+
+ @Before
+ fun setUp() {
+ initMocks(this)
+ extender = TestableSelfTrackingLifetimeExtender()
+ extender.setCallback(callback)
+ entry1 = NotificationEntryBuilder().setId(1).build()
+ entry2 = NotificationEntryBuilder().setId(2).build()
+ }
+
+ @Test
+ fun testName() {
+ assertThat(extender.name).isEqualTo("Testable")
+ }
+
+ @Test
+ fun testNoExtend() {
+ `when`(shouldExtend.test(entry1)).thenReturn(false)
+ assertThat(extender.shouldExtendLifetime(entry1, 0)).isFalse()
+ assertThat(extender.isExtending(entry1.key)).isFalse()
+ verify(onStarted, never()).accept(entry1)
+ verify(onCanceled, never()).accept(entry1)
+ }
+
+ @Test
+ fun testExtendThenCancelForRepost() {
+ `when`(shouldExtend.test(entry1)).thenReturn(true)
+ assertThat(extender.shouldExtendLifetime(entry1, 0)).isTrue()
+ verify(onStarted).accept(entry1)
+ verify(onCanceled, never()).accept(entry1)
+ assertThat(extender.isExtending(entry1.key)).isTrue()
+ extender.cancelLifetimeExtension(entry1)
+ verify(onCanceled).accept(entry1)
+ }
+
+ @Test
+ fun testExtendThenCancel_thenEndDoesNothing() {
+ testExtendThenCancelForRepost()
+ assertThat(extender.isExtending(entry1.key)).isFalse()
+
+ extender.endLifetimeExtension(entry1.key)
+ extender.endLifetimeExtensionAfterDelay(entry1.key, 1000)
+ verify(callback, never()).onEndLifetimeExtension(any(), any())
+ verify(mainHandler, never()).postDelayed(any(), anyLong())
+ }
+
+ @Test
+ fun testExtendThenEnd() {
+ `when`(shouldExtend.test(entry1)).thenReturn(true)
+ assertThat(extender.shouldExtendLifetime(entry1, 0)).isTrue()
+ verify(onStarted).accept(entry1)
+ assertThat(extender.isExtending(entry1.key)).isTrue()
+ extender.endLifetimeExtension(entry1.key)
+ verify(callback).onEndLifetimeExtension(extender, entry1)
+ verify(onCanceled, never()).accept(entry1)
+ }
+
+ @Test
+ fun testExtendThenEndAfterDelay() {
+ `when`(shouldExtend.test(entry1)).thenReturn(true)
+ assertThat(extender.shouldExtendLifetime(entry1, 0)).isTrue()
+ verify(onStarted).accept(entry1)
+ assertThat(extender.isExtending(entry1.key)).isTrue()
+
+ // Call the method and capture the posted runnable
+ extender.endLifetimeExtensionAfterDelay(entry1.key, 1234)
+ val runnable = withArgCaptor<Runnable> {
+ verify(mainHandler).postDelayed(capture(), eq(1234.toLong()))
+ }
+ assertThat(extender.isExtending(entry1.key)).isTrue()
+ verify(callback, never()).onEndLifetimeExtension(any(), any())
+
+ // now run the posted runnable and ensure it works as expected
+ runnable.run()
+ verify(callback).onEndLifetimeExtension(extender, entry1)
+ assertThat(extender.isExtending(entry1.key)).isFalse()
+ verify(onCanceled, never()).accept(entry1)
+ }
+
+ @Test
+ fun testExtendThenEndAll() {
+ `when`(shouldExtend.test(entry1)).thenReturn(true)
+ `when`(shouldExtend.test(entry2)).thenReturn(true)
+ assertThat(extender.shouldExtendLifetime(entry1, 0)).isTrue()
+ verify(onStarted).accept(entry1)
+ assertThat(extender.isExtending(entry1.key)).isTrue()
+ assertThat(extender.isExtending(entry2.key)).isFalse()
+ assertThat(extender.shouldExtendLifetime(entry2, 0)).isTrue()
+ verify(onStarted).accept(entry2)
+ assertThat(extender.isExtending(entry1.key)).isTrue()
+ assertThat(extender.isExtending(entry2.key)).isTrue()
+ extender.endAllLifetimeExtensions()
+ verify(callback).onEndLifetimeExtension(extender, entry1)
+ verify(callback).onEndLifetimeExtension(extender, entry2)
+ verify(onCanceled, never()).accept(entry1)
+ verify(onCanceled, never()).accept(entry2)
+ }
+
+ @Test
+ fun testExtendWithinEndCanReExtend() {
+ `when`(shouldExtend.test(entry1)).thenReturn(true)
+ assertThat(extender.shouldExtendLifetime(entry1, 0)).isTrue()
+ verify(onStarted, times(1)).accept(entry1)
+
+ `when`(callback.onEndLifetimeExtension(extender, entry1)).thenAnswer {
+ assertThat(extender.shouldExtendLifetime(entry1, 0)).isTrue()
+ }
+ extender.endLifetimeExtension(entry1.key)
+ verify(onStarted, times(2)).accept(entry1)
+ assertThat(extender.isExtending(entry1.key)).isTrue()
+ }
+
+ @Test
+ fun testExtendWithinEndCanNotReExtend() {
+ `when`(shouldExtend.test(entry1)).thenReturn(true, false)
+ assertThat(extender.shouldExtendLifetime(entry1, 0)).isTrue()
+ verify(onStarted, times(1)).accept(entry1)
+
+ `when`(callback.onEndLifetimeExtension(extender, entry1)).thenAnswer {
+ assertThat(extender.shouldExtendLifetime(entry1, 0)).isFalse()
+ }
+ extender.endLifetimeExtension(entry1.key)
+ verify(onStarted, times(1)).accept(entry1)
+ assertThat(extender.isExtending(entry1.key)).isFalse()
+ }
+
+ @Test
+ fun testExtendWithinEndAllCanReExtend() {
+ `when`(shouldExtend.test(entry1)).thenReturn(true)
+ assertThat(extender.shouldExtendLifetime(entry1, 0)).isTrue()
+ verify(onStarted, times(1)).accept(entry1)
+
+ `when`(callback.onEndLifetimeExtension(extender, entry1)).thenAnswer {
+ assertThat(extender.shouldExtendLifetime(entry1, 0)).isTrue()
+ }
+ extender.endAllLifetimeExtensions()
+ verify(onStarted, times(2)).accept(entry1)
+ assertThat(extender.isExtending(entry1.key)).isTrue()
+ }
+
+ @Test
+ fun testExtendWithinEndAllCanNotReExtend() {
+ `when`(shouldExtend.test(entry1)).thenReturn(true, false)
+ assertThat(extender.shouldExtendLifetime(entry1, 0)).isTrue()
+ verify(onStarted, times(1)).accept(entry1)
+
+ `when`(callback.onEndLifetimeExtension(extender, entry1)).thenAnswer {
+ assertThat(extender.shouldExtendLifetime(entry1, 0)).isFalse()
+ }
+ extender.endAllLifetimeExtensions()
+ verify(onStarted, times(1)).accept(entry1)
+ assertThat(extender.isExtending(entry1.key)).isFalse()
+ }
+
+ inner class TestableSelfTrackingLifetimeExtender(debug: Boolean = false) :
+ SelfTrackingLifetimeExtender("Test", "Testable", debug, mainHandler) {
+
+ override fun queryShouldExtendLifetime(entry: NotificationEntry) =
+ shouldExtend.test(entry)
+
+ override fun onStartedLifetimeExtension(entry: NotificationEntry) {
+ onStarted.accept(entry)
+ }
+
+ override fun onCanceledLifetimeExtension(entry: NotificationEntry) {
+ onCanceled.accept(entry)
+ }
+ }
+}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/KeyguardClockPositionAlgorithmTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/KeyguardClockPositionAlgorithmTest.java
index d098e1a..624bedc 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/KeyguardClockPositionAlgorithmTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/KeyguardClockPositionAlgorithmTest.java
@@ -58,7 +58,6 @@
private KeyguardClockPositionAlgorithm.Result mClockPosition;
private MockitoSession mStaticMockSession;
- private int mNotificationStackHeight;
private float mPanelExpansion;
private int mKeyguardStatusBarHeaderHeight;
@@ -264,6 +263,30 @@
}
@Test
+ public void notifPaddingExpandedAlignedWithClockInSplitShadeMode() {
+ givenLockScreen();
+ mIsSplitShade = true;
+ mKeyguardStatusHeight = 200;
+ // WHEN the position algorithm is run
+ positionClock();
+ // THEN the padding DOESN'T adjust for keyguard status height.
+ assertThat(mClockPosition.stackScrollerPaddingExpanded)
+ .isEqualTo(mClockPosition.clockYFullyDozing);
+ }
+
+ @Test
+ public void notifMinPaddingAlignedWithClockInSplitShadeMode() {
+ givenLockScreen();
+ mIsSplitShade = true;
+ mKeyguardStatusHeight = 200;
+ // WHEN the position algorithm is run
+ positionClock();
+ // THEN the padding DOESN'T adjust for keyguard status height.
+ assertThat(mClockPositionAlgorithm.getMinStackScrollerPadding())
+ .isEqualTo(mKeyguardStatusBarHeaderHeight);
+ }
+
+ @Test
public void notifPositionWithLargeClockOnLockScreen() {
// GIVEN on lock screen and clock has a nonzero height
givenLockScreen();
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/SplitShadeHeaderControllerTest.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/SplitShadeHeaderControllerTest.kt
new file mode 100644
index 0000000..a9e8164
--- /dev/null
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/SplitShadeHeaderControllerTest.kt
@@ -0,0 +1,87 @@
+package com.android.systemui.statusbar.phone
+
+import android.content.Context
+import android.content.res.Resources
+import android.test.suitebuilder.annotation.SmallTest
+import android.view.View
+import com.android.systemui.R
+import com.android.systemui.SysuiTestCase
+import com.android.systemui.animation.ShadeInterpolation
+import com.android.systemui.battery.BatteryMeterView
+import com.android.systemui.battery.BatteryMeterViewController
+import com.android.systemui.flags.FeatureFlags
+import com.android.systemui.qs.carrier.QSCarrierGroupController
+import com.google.common.truth.Truth.assertThat
+import org.junit.Before
+import org.junit.Rule
+import org.junit.Test
+import org.mockito.ArgumentMatchers.any
+import org.mockito.ArgumentMatchers.anyInt
+import org.mockito.Mock
+import org.mockito.Mockito.`when` as whenever
+import org.mockito.Mockito.verify
+import org.mockito.junit.MockitoJUnit
+
+@SmallTest
+class SplitShadeHeaderControllerTest : SysuiTestCase() {
+
+ @Mock private lateinit var view: View
+ @Mock private lateinit var statusIcons: StatusIconContainer
+ @Mock private lateinit var statusBarIconController: StatusBarIconController
+ @Mock private lateinit var qsCarrierGroupController: QSCarrierGroupController
+ @Mock private lateinit var qsCarrierGroupControllerBuilder: QSCarrierGroupController.Builder
+ @Mock private lateinit var featureFlags: FeatureFlags
+ @Mock private lateinit var batteryMeterView: BatteryMeterView
+ @Mock private lateinit var batteryMeterViewController: BatteryMeterViewController
+ @Mock private lateinit var resources: Resources
+ @Mock private lateinit var context: Context
+ @JvmField @Rule val mockitoRule = MockitoJUnit.rule()
+ var viewVisibility = View.GONE
+
+ private lateinit var splitShadeHeaderController: SplitShadeHeaderController
+
+ @Before
+ fun setup() {
+ whenever<BatteryMeterView>(view.findViewById(R.id.batteryRemainingIcon))
+ .thenReturn(batteryMeterView)
+ whenever<StatusIconContainer>(view.findViewById(R.id.statusIcons)).thenReturn(statusIcons)
+ whenever(statusIcons.context).thenReturn(context)
+ whenever(context.resources).thenReturn(resources)
+ whenever(qsCarrierGroupControllerBuilder.setQSCarrierGroup(any()))
+ .thenReturn(qsCarrierGroupControllerBuilder)
+ whenever(qsCarrierGroupControllerBuilder.build()).thenReturn(qsCarrierGroupController)
+ whenever(view.setVisibility(anyInt())).then {
+ viewVisibility = it.arguments[0] as Int
+ null
+ }
+ whenever(view.visibility).thenAnswer { _ -> viewVisibility }
+ splitShadeHeaderController = SplitShadeHeaderController(view, statusBarIconController,
+ qsCarrierGroupControllerBuilder, featureFlags, batteryMeterViewController)
+ }
+
+ @Test
+ fun setVisible_onlyInSplitShade() {
+ splitShadeHeaderController.splitShadeMode = true
+ splitShadeHeaderController.shadeExpanded = true
+ assertThat(viewVisibility).isEqualTo(View.VISIBLE)
+
+ splitShadeHeaderController.splitShadeMode = false
+ assertThat(viewVisibility).isEqualTo(View.GONE)
+ }
+
+ @Test
+ fun updateListeners_registersWhenVisible() {
+ splitShadeHeaderController.splitShadeMode = true
+ splitShadeHeaderController.shadeExpanded = true
+ verify(qsCarrierGroupController).setListening(true)
+ verify(statusBarIconController).addIconGroup(any())
+ }
+
+ @Test
+ fun shadeExpandedFraction_updatesAlpha() {
+ splitShadeHeaderController.splitShadeMode = true
+ splitShadeHeaderController.shadeExpanded = true
+ splitShadeHeaderController.shadeExpandedFraction = 0.5f
+ verify(view).setAlpha(ShadeInterpolation.getContentAlpha(0.5f))
+ }
+}
\ No newline at end of file
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarContentInsetsProviderTest.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarContentInsetsProviderTest.kt
index 1503af8..e5158e7 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarContentInsetsProviderTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarContentInsetsProviderTest.kt
@@ -86,7 +86,9 @@
screenBounds,
sbHeightPortrait,
minLeftPadding,
- minRightPadding)
+ minRightPadding,
+ isRtl,
+ dotWidth)
var chipBounds = getPrivacyChipBoundingRectForInsets(bounds, dotWidth, chipWidth, isRtl)
/* 1080 - 20 (rounded corner) - 30 (chip),
@@ -115,7 +117,9 @@
screenBounds,
sbHeightLandscape,
minLeftPadding,
- minRightPadding)
+ minRightPadding,
+ isRtl,
+ dotWidth)
chipBounds = getPrivacyChipBoundingRectForInsets(bounds, dotWidth, chipWidth, isRtl)
/* 2160 - 20 (rounded corner) - 30 (chip),
@@ -146,6 +150,8 @@
val sbHeightPortrait = 100
val sbHeightLandscape = 60
val currentRotation = ROTATION_NONE
+ val isRtl = false
+ val dotWidth = 10
`when`(dc.boundingRects).thenReturn(listOf(dcBounds))
@@ -164,7 +170,9 @@
screenBounds,
sbHeightPortrait,
minLeftPadding,
- minRightPadding)
+ minRightPadding,
+ isRtl,
+ dotWidth)
assertRects(expectedBounds, bounds, currentRotation, targetRotation)
@@ -181,7 +189,9 @@
screenBounds,
sbHeightLandscape,
minLeftPadding,
- minRightPadding)
+ minRightPadding,
+ isRtl,
+ dotWidth)
assertRects(expectedBounds, bounds, currentRotation, targetRotation)
@@ -200,7 +210,9 @@
screenBounds,
sbHeightPortrait,
minLeftPadding,
- minRightPadding)
+ minRightPadding,
+ isRtl,
+ dotWidth)
assertRects(expectedBounds, bounds, currentRotation, targetRotation)
@@ -208,7 +220,7 @@
targetRotation = ROTATION_SEASCAPE
expectedBounds = Rect(minLeftPadding,
0,
- screenBounds.height() - dcBounds.height(),
+ screenBounds.height() - dcBounds.height() - dotWidth,
sbHeightLandscape)
bounds = calculateInsetsForRotationWithRotatedResources(
@@ -218,7 +230,9 @@
screenBounds,
sbHeightLandscape,
minLeftPadding,
- minRightPadding)
+ minRightPadding,
+ isRtl,
+ dotWidth)
assertRects(expectedBounds, bounds, currentRotation, targetRotation)
}
@@ -237,6 +251,8 @@
val sbHeightPortrait = 100
val sbHeightLandscape = 60
val currentRotation = ROTATION_NONE
+ val isRtl = false
+ val dotWidth = 10
`when`(dc.boundingRects).thenReturn(listOf(dcBounds))
@@ -255,7 +271,9 @@
screenBounds,
sbHeightPortrait,
minLeftPadding,
- minRightPadding)
+ minRightPadding,
+ isRtl,
+ dotWidth)
assertRects(expectedBounds, bounds, currentRotation, targetRotation)
@@ -272,7 +290,9 @@
screenBounds,
sbHeightLandscape,
minLeftPadding,
- minRightPadding)
+ minRightPadding,
+ isRtl,
+ dotWidth)
assertRects(expectedBounds, bounds, currentRotation, targetRotation)
@@ -289,14 +309,16 @@
screenBounds,
sbHeightPortrait,
minLeftPadding,
- minRightPadding)
+ minRightPadding,
+ isRtl,
+ dotWidth)
assertRects(expectedBounds, bounds, currentRotation, targetRotation)
targetRotation = ROTATION_SEASCAPE
expectedBounds = Rect(minLeftPadding,
0,
- screenBounds.height() - dcBounds.height(),
+ screenBounds.height() - dcBounds.height() - dotWidth,
sbHeightLandscape)
bounds = calculateInsetsForRotationWithRotatedResources(
@@ -306,7 +328,9 @@
screenBounds,
sbHeightLandscape,
minLeftPadding,
- minRightPadding)
+ minRightPadding,
+ isRtl,
+ dotWidth)
assertRects(expectedBounds, bounds, currentRotation, targetRotation)
}
@@ -320,6 +344,8 @@
val minRightPadding = 20
val sbHeightPortrait = 100
val sbHeightLandscape = 60
+ val isRtl = false
+ val dotWidth = 10
// THEN content insets should only use rounded corner padding
var targetRotation = ROTATION_NONE
@@ -335,7 +361,9 @@
screenBounds,
sbHeightPortrait,
minLeftPadding,
- minRightPadding)
+ minRightPadding,
+ isRtl,
+ dotWidth)
assertRects(expectedBounds, bounds, currentRotation, targetRotation)
targetRotation = ROTATION_LANDSCAPE
@@ -351,7 +379,9 @@
screenBounds,
sbHeightLandscape,
minLeftPadding,
- minRightPadding)
+ minRightPadding,
+ isRtl,
+ dotWidth)
assertRects(expectedBounds, bounds, currentRotation, targetRotation)
targetRotation = ROTATION_UPSIDE_DOWN
@@ -367,7 +397,9 @@
screenBounds,
sbHeightPortrait,
minLeftPadding,
- minRightPadding)
+ minRightPadding,
+ isRtl,
+ dotWidth)
assertRects(expectedBounds, bounds, currentRotation, targetRotation)
targetRotation = ROTATION_LANDSCAPE
@@ -383,7 +415,9 @@
screenBounds,
sbHeightLandscape,
minLeftPadding,
- minRightPadding)
+ minRightPadding,
+ isRtl,
+ dotWidth)
assertRects(expectedBounds, bounds, currentRotation, targetRotation)
}
@@ -397,6 +431,8 @@
val sbHeightPortrait = 100
val sbHeightLandscape = 60
val currentRotation = ROTATION_NONE
+ val isRtl = false
+ val dotWidth = 10
`when`(dc.boundingRects).thenReturn(listOf(dcBounds))
@@ -414,7 +450,9 @@
screenBounds,
sbHeightPortrait,
minLeftPadding,
- minRightPadding)
+ minRightPadding,
+ isRtl,
+ dotWidth)
assertRects(expectedBounds, bounds, currentRotation, targetRotation)
}
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 3fcd071..2d944aa 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
@@ -16,6 +16,7 @@
package com.android.systemui.statusbar.phone;
+import static org.junit.Assert.assertTrue;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.anyBoolean;
import static org.mockito.ArgumentMatchers.anyFloat;
@@ -44,7 +45,6 @@
import com.android.systemui.dock.DockManager;
import com.android.systemui.dump.DumpManager;
import com.android.systemui.keyguard.DismissCallbackRegistry;
-import com.android.systemui.keyguard.FaceAuthScreenBrightnessController;
import com.android.systemui.keyguard.WakefulnessLifecycle;
import com.android.systemui.navigationbar.NavigationModeController;
import com.android.systemui.plugins.ActivityStarter.OnDismissAction;
@@ -60,8 +60,6 @@
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
-import java.util.Optional;
-
import dagger.Lazy;
@SmallTest
@@ -92,8 +90,6 @@
@Mock
private KeyguardBypassController mBypassController;
@Mock
- private FaceAuthScreenBrightnessController mFaceAuthScreenBrightnessController;
- @Mock
private KeyguardBouncer.Factory mKeyguardBouncerFactory;
@Mock
private KeyguardMessageAreaController.Factory mKeyguardMessageAreaFactory;
@@ -102,6 +98,8 @@
@Mock
private UnlockedScreenOffAnimationController mUnlockedScreenOffAnimationController;
@Mock
+ private StatusBarKeyguardViewManager.AlternateAuthInterceptor mAlternateAuthInterceptor;
+ @Mock
private KeyguardMessageArea mKeyguardMessageArea;
@Mock
private Lazy<ShadeController> mShadeController;
@@ -133,7 +131,6 @@
mock(DockManager.class),
mock(NotificationShadeWindowController.class),
mKeyguardStateController,
- Optional.of(mFaceAuthScreenBrightnessController),
mock(NotificationMediaManager.class),
mKeyguardBouncerFactory,
mWakefulnessLifecycle,
@@ -293,6 +290,24 @@
}
@Test
+ public void testShowing_whenAlternateAuthShowing() {
+ mStatusBarKeyguardViewManager.setAlternateAuthInterceptor(mAlternateAuthInterceptor);
+ when(mBouncer.isShowing()).thenReturn(false);
+ when(mAlternateAuthInterceptor.isShowingAlternateAuthBouncer()).thenReturn(true);
+ assertTrue("Is showing not accurate when alternative auth showing",
+ mStatusBarKeyguardViewManager.isShowing());
+ }
+
+ @Test
+ public void testWillBeShowing_whenAlternateAuthShowing() {
+ mStatusBarKeyguardViewManager.setAlternateAuthInterceptor(mAlternateAuthInterceptor);
+ when(mBouncer.isShowing()).thenReturn(false);
+ when(mAlternateAuthInterceptor.isShowingAlternateAuthBouncer()).thenReturn(true);
+ assertTrue("Is or will be showing not accurate when alternative auth showing",
+ mStatusBarKeyguardViewManager.bouncerIsOrWillBeShowing());
+ }
+
+ @Test
public void testUpdateResources_delegatesToBouncer() {
mStatusBarKeyguardViewManager.updateResources();
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarNotificationPresenterTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarNotificationPresenterTest.java
index c80c072..4e6b0a2 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarNotificationPresenterTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarNotificationPresenterTest.java
@@ -37,6 +37,7 @@
import com.android.systemui.ForegroundServiceNotificationListener;
import com.android.systemui.InitController;
import com.android.systemui.SysuiTestCase;
+import com.android.systemui.flags.FeatureFlags;
import com.android.systemui.plugins.statusbar.StatusBarStateController;
import com.android.systemui.statusbar.CommandQueue;
import com.android.systemui.statusbar.KeyguardIndicationController;
@@ -51,6 +52,7 @@
import com.android.systemui.statusbar.notification.NotificationEntryManager;
import com.android.systemui.statusbar.notification.collection.NotificationEntry;
import com.android.systemui.statusbar.notification.collection.NotificationEntryBuilder;
+import com.android.systemui.statusbar.notification.collection.render.NotifShadeEventSource;
import com.android.systemui.statusbar.notification.interruption.NotificationInterruptStateProvider;
import com.android.systemui.statusbar.notification.interruption.NotificationInterruptSuppressor;
import com.android.systemui.statusbar.notification.row.ActivatableNotificationView;
@@ -109,12 +111,15 @@
mock(DozeScrimController.class), mock(ScrimController.class),
mock(NotificationShadeWindowController.class), mock(DynamicPrivacyController.class),
mock(KeyguardStateController.class),
- mock(KeyguardIndicationController.class), mStatusBar,
+ mock(KeyguardIndicationController.class),
+ mock(FeatureFlags.class),
+ mStatusBar,
mock(ShadeControllerImpl.class), mock(LockscreenShadeTransitionController.class),
mCommandQueue,
mock(NotificationViewHierarchyManager.class),
mock(NotificationLockscreenUserManager.class),
mock(SysuiStatusBarStateController.class),
+ mock(NotifShadeEventSource.class),
mock(NotificationEntryManager.class),
mock(NotificationMediaManager.class),
mock(NotificationGutsManager.class),
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarTest.java
index 943d3c7..f14b126 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarTest.java
@@ -96,7 +96,7 @@
import com.android.systemui.plugins.PluginDependencyProvider;
import com.android.systemui.plugins.statusbar.StatusBarStateController;
import com.android.systemui.recents.ScreenPinningRequest;
-import com.android.systemui.settings.brightness.BrightnessSlider;
+import com.android.systemui.settings.brightness.BrightnessSliderController;
import com.android.systemui.shared.plugins.PluginManager;
import com.android.systemui.statusbar.CommandQueue;
import com.android.systemui.statusbar.KeyguardIndicationController;
@@ -121,6 +121,7 @@
import com.android.systemui.statusbar.notification.collection.NotificationEntry;
import com.android.systemui.statusbar.notification.collection.NotificationEntryBuilder;
import com.android.systemui.statusbar.notification.collection.legacy.VisualStabilityManager;
+import com.android.systemui.statusbar.notification.collection.render.NotifShadeEventSource;
import com.android.systemui.statusbar.notification.init.NotificationsController;
import com.android.systemui.statusbar.notification.interruption.BypassHeadsUpNotifier;
import com.android.systemui.statusbar.notification.interruption.NotificationInterruptStateProviderImpl;
@@ -210,6 +211,7 @@
@Mock private NotificationShadeWindowView mNotificationShadeWindowView;
@Mock private BroadcastDispatcher mBroadcastDispatcher;
@Mock private AssistManager mAssistManager;
+ @Mock private NotifShadeEventSource mNotifShadeEventSource;
@Mock private NotificationEntryManager mNotificationEntryManager;
@Mock private NotificationGutsManager mNotificationGutsManager;
@Mock private NotificationMediaManager mNotificationMediaManager;
@@ -257,7 +259,7 @@
@Mock private PhoneStatusBarPolicy mPhoneStatusBarPolicy;
@Mock private DemoModeController mDemoModeController;
@Mock private Lazy<NotificationShadeDepthController> mNotificationShadeDepthControllerLazy;
- @Mock private BrightnessSlider.Factory mBrightnessSliderFactory;
+ @Mock private BrightnessSliderController.Factory mBrightnessSliderFactory;
@Mock private UnfoldTransitionConfig mUnfoldTransitionConfig;
@Mock private Lazy<UnfoldLightRevealOverlayAnimation> mUnfoldLightRevealOverlayAnimationLazy;
@Mock private Lazy<NaturalRotationUnfoldProgressProvider> mNaturalRotationProgressProvider;
@@ -377,6 +379,7 @@
new FalsingManagerFake(),
new FalsingCollectorFake(),
mBroadcastDispatcher,
+ mNotifShadeEventSource,
mNotificationEntryManager,
mNotificationGutsManager,
notificationLogger,
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/UnlockedScreenOffAnimationControllerTest.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/UnlockedScreenOffAnimationControllerTest.kt
new file mode 100644
index 0000000..a8a33da
--- /dev/null
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/UnlockedScreenOffAnimationControllerTest.kt
@@ -0,0 +1,92 @@
+/*
+ * Copyright (C) 2021 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.animation.Animator
+import android.testing.AndroidTestingRunner
+import android.testing.TestableLooper.RunWithLooper
+import android.view.View
+import androidx.test.filters.SmallTest
+import com.android.systemui.SysuiTestCase
+import com.android.systemui.keyguard.KeyguardViewMediator
+import com.android.systemui.keyguard.WakefulnessLifecycle
+import com.android.systemui.statusbar.LightRevealScrim
+import com.android.systemui.statusbar.StatusBarStateControllerImpl
+import com.android.systemui.statusbar.policy.KeyguardStateController
+import com.android.systemui.util.settings.GlobalSettings
+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.Mockito.spy
+import org.mockito.MockitoAnnotations
+
+@SmallTest
+@RunWith(AndroidTestingRunner::class)
+@RunWithLooper(setAsMainLooper = true)
+class UnlockedScreenOffAnimationControllerTest : SysuiTestCase() {
+
+ private lateinit var controller: UnlockedScreenOffAnimationController
+ @Mock
+ private lateinit var keyguardViewMediator: KeyguardViewMediator
+ @Mock
+ private lateinit var dozeParameters: DozeParameters
+ @Mock
+ private lateinit var keyguardStateController: KeyguardStateController
+ @Mock
+ private lateinit var globalSettings: GlobalSettings
+ @Mock
+ private lateinit var statusbar: StatusBar
+ @Mock
+ private lateinit var lightRevealScrim: LightRevealScrim
+ @Mock
+ private lateinit var wakefulnessLifecycle: WakefulnessLifecycle
+ @Mock
+ private lateinit var statusBarStateController: StatusBarStateControllerImpl
+
+ @Before
+ fun setUp() {
+ MockitoAnnotations.initMocks(this)
+
+ controller = UnlockedScreenOffAnimationController(
+ context,
+ wakefulnessLifecycle,
+ statusBarStateController,
+ dagger.Lazy<KeyguardViewMediator> { keyguardViewMediator },
+ keyguardStateController,
+ dagger.Lazy<DozeParameters> { dozeParameters },
+ globalSettings
+ )
+ controller.initialize(statusbar, lightRevealScrim)
+ }
+
+ @Test
+ fun testAnimClearsEndListener() {
+ val keyguardView = View(context)
+ val animator = spy(keyguardView.animate())
+ val keyguardSpy = spy(keyguardView)
+ Mockito.`when`(keyguardSpy.animate()).thenReturn(animator)
+ val listener = ArgumentCaptor.forClass(Animator.AnimatorListener::class.java)
+ controller.animateInKeyguard(keyguardSpy, Runnable {})
+ Mockito.verify(animator).setListener(listener.capture())
+ // Verify that the listener is cleared when it ends
+ listener.value.onAnimationEnd(null)
+ Mockito.verify(animator).setListener(null)
+ }
+}
\ No newline at end of file
diff --git a/packages/SystemUI/tests/src/com/android/systemui/util/mockito/KotlinMockitoHelpers.kt b/packages/SystemUI/tests/src/com/android/systemui/util/mockito/KotlinMockitoHelpers.kt
index bff99bf..483dc9f 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/util/mockito/KotlinMockitoHelpers.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/util/mockito/KotlinMockitoHelpers.kt
@@ -58,3 +58,24 @@
*/
inline fun <reified T : Any> argumentCaptor(): ArgumentCaptor<T> =
ArgumentCaptor.forClass(T::class.java)
+
+/**
+ * Helper function for creating new mocks, without the need to pass in a [Class] instance.
+ *
+ * Generic T is nullable because implicitly bounded by Any?.
+ */
+inline fun <reified T : Any> mock(): T = Mockito.mock(T::class.java)
+
+/**
+ * Helper function for creating and using a single-use ArgumentCaptor in kotlin.
+ *
+ * val captor = argumentCaptor<Foo>()
+ * verify(...).someMethod(captor.capture())
+ * val captured = captor.value
+ *
+ * becomes:
+ *
+ * val captured = withArgCaptor<Foo> { verify(...).someMethod(capture()) }
+ */
+inline fun <reified T : Any> withArgCaptor(block: ArgumentCaptor<T>.() -> Unit): T =
+ argumentCaptor<T>().apply { block() }.value
\ No newline at end of file
diff --git a/packages/SystemUI/tests/src/com/android/systemui/util/service/ObservableServiceConnectionTest.java b/packages/SystemUI/tests/src/com/android/systemui/util/service/ObservableServiceConnectionTest.java
new file mode 100644
index 0000000..7c6d80b
--- /dev/null
+++ b/packages/SystemUI/tests/src/com/android/systemui/util/service/ObservableServiceConnectionTest.java
@@ -0,0 +1,148 @@
+/*
+ * Copyright (C) 2021 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.util.service;
+
+import static org.mockito.ArgumentMatchers.anyInt;
+import static org.mockito.ArgumentMatchers.eq;
+import static org.mockito.Mockito.clearInvocations;
+import static org.mockito.Mockito.never;
+import static org.mockito.Mockito.times;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+
+import android.content.ComponentName;
+import android.content.Context;
+import android.content.Intent;
+import android.os.IBinder;
+import android.testing.AndroidTestingRunner;
+
+import androidx.test.filters.SmallTest;
+
+import com.android.systemui.SysuiTestCase;
+import com.android.systemui.util.concurrency.FakeExecutor;
+import com.android.systemui.util.time.FakeSystemClock;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
+
+import java.util.Objects;
+
+@SmallTest
+@RunWith(AndroidTestingRunner.class)
+public class ObservableServiceConnectionTest extends SysuiTestCase {
+ static class Foo {
+ int mValue;
+
+ Foo(int value) {
+ mValue = value;
+ }
+
+ @Override
+ public boolean equals(Object o) {
+ if (this == o) return true;
+ if (!(o instanceof Foo)) return false;
+ Foo foo = (Foo) o;
+ return mValue == foo.mValue;
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hash(mValue);
+ }
+ }
+
+ @Mock
+ Context mContext;
+
+ @Mock
+ Intent mIntent;
+
+ @Mock
+ Foo mResult;
+
+ @Mock
+ ComponentName mComponentName;
+
+ @Mock
+ IBinder mBinder;
+
+ @Mock
+ ObservableServiceConnection.ServiceTransformer<Foo> mTransformer;
+
+ @Mock
+ ObservableServiceConnection.Callback<Foo> mCallback;
+
+ FakeExecutor mExecutor = new FakeExecutor(new FakeSystemClock());
+
+ @Before
+ public void setUp() throws Exception {
+ MockitoAnnotations.initMocks(this);
+ }
+
+ @Test
+ public void testConnect() {
+ ObservableServiceConnection<Foo> connection = new ObservableServiceConnection<>(mContext,
+ mIntent, 0, mExecutor, mTransformer);
+ // Register twice to ensure only one callback occurs.
+ connection.addCallback(mCallback);
+ connection.addCallback(mCallback);
+ mExecutor.runAllReady();
+ connection.bind();
+
+ when(mTransformer.convert(eq(mBinder))).thenReturn(mResult);
+
+ connection.onServiceConnected(mComponentName, mBinder);
+
+ mExecutor.runAllReady();
+
+ // Ensure callback is informed of the translated result.
+ verify(mCallback, times(1)).onConnected(eq(connection), eq(mResult));
+ }
+
+ @Test
+ public void testDisconnect() {
+ ObservableServiceConnection<Foo> connection = new ObservableServiceConnection<>(mContext,
+ mIntent, 0, mExecutor, mTransformer);
+ connection.addCallback(mCallback);
+ connection.onServiceDisconnected(mComponentName);
+
+ // Disconnects before binds should be ignored.
+ verify(mCallback, never()).onDisconnected(eq(connection), anyInt());
+
+ when(mContext.bindService(eq(mIntent), anyInt(), eq(mExecutor), eq(connection)))
+ .thenReturn(true);
+ connection.bind();
+ connection.onServiceDisconnected(mComponentName);
+
+ mExecutor.runAllReady();
+
+ // Ensure proper disconnect reason reported back
+ verify(mCallback).onDisconnected(eq(connection),
+ eq(ObservableServiceConnection.DISCONNECT_REASON_DISCONNECTED));
+
+ // Verify unbound from service.
+ verify(mContext, times(1)).unbindService(eq(connection));
+
+ clearInvocations(mContext);
+ // Ensure unbind after disconnect has no effect on the connection
+ connection.unbind();
+ verify(mContext, never()).unbindService(eq(connection));
+ }
+}
diff --git a/packages/overlays/DisplayCutoutEmulationCornerOverlay/res/values-land/config.xml b/packages/overlays/DisplayCutoutEmulationCornerOverlay/res/values-land/config.xml
deleted file mode 100644
index bd52901..0000000
--- a/packages/overlays/DisplayCutoutEmulationCornerOverlay/res/values-land/config.xml
+++ /dev/null
@@ -1,22 +0,0 @@
-<!--
- ~ 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>
- <!-- Can't link to other dimensions here, but this should be status_bar_height_landscape -->
- <dimen name="quick_qs_offset_height">28dp</dimen>
- <!-- Total height of QQS in landscape; quick_qs_offset_height + 128 -->
- <dimen name="quick_qs_total_height">156dp</dimen>
-</resources>
\ No newline at end of file
diff --git a/packages/overlays/DisplayCutoutEmulationCornerOverlay/res/values/config.xml b/packages/overlays/DisplayCutoutEmulationCornerOverlay/res/values/config.xml
index 9254b4d..c340432 100644
--- a/packages/overlays/DisplayCutoutEmulationCornerOverlay/res/values/config.xml
+++ b/packages/overlays/DisplayCutoutEmulationCornerOverlay/res/values/config.xml
@@ -44,14 +44,6 @@
-->
<bool name="config_fillMainBuiltInDisplayCutout">true</bool>
- <!-- Height of the status bar -->
- <dimen name="status_bar_height_portrait">48dp</dimen>
- <dimen name="status_bar_height_landscape">28dp</dimen>
- <!-- Height of area above QQS where battery/time go (equal to status bar height if > 48dp) -->
- <dimen name="quick_qs_offset_height">48dp</dimen>
- <!-- Total height of QQS (quick_qs_offset_height + 128) -->
- <dimen name="quick_qs_total_height">176dp</dimen>
-
</resources>
diff --git a/packages/overlays/DisplayCutoutEmulationDoubleOverlay/res/values-land/config.xml b/packages/overlays/DisplayCutoutEmulationDoubleOverlay/res/values-land/config.xml
deleted file mode 100644
index bd52901..0000000
--- a/packages/overlays/DisplayCutoutEmulationDoubleOverlay/res/values-land/config.xml
+++ /dev/null
@@ -1,22 +0,0 @@
-<!--
- ~ 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>
- <!-- Can't link to other dimensions here, but this should be status_bar_height_landscape -->
- <dimen name="quick_qs_offset_height">28dp</dimen>
- <!-- Total height of QQS in landscape; quick_qs_offset_height + 128 -->
- <dimen name="quick_qs_total_height">156dp</dimen>
-</resources>
\ No newline at end of file
diff --git a/packages/overlays/DisplayCutoutEmulationDoubleOverlay/res/values/config.xml b/packages/overlays/DisplayCutoutEmulationDoubleOverlay/res/values/config.xml
index 80c997a..928d9df 100644
--- a/packages/overlays/DisplayCutoutEmulationDoubleOverlay/res/values/config.xml
+++ b/packages/overlays/DisplayCutoutEmulationDoubleOverlay/res/values/config.xml
@@ -56,14 +56,6 @@
-->
<bool name="config_fillMainBuiltInDisplayCutout">true</bool>
- <!-- Height of the status bar -->
- <dimen name="status_bar_height_portrait">48dp</dimen>
- <dimen name="status_bar_height_landscape">28dp</dimen>
- <!-- Height of area above QQS where battery/time go (equal to status bar height if > 48dp) -->
- <dimen name="quick_qs_offset_height">48dp</dimen>
- <!-- Total height of QQS (quick_qs_offset_height + 128) -->
- <dimen name="quick_qs_total_height">176dp</dimen>
-
</resources>
diff --git a/packages/overlays/DisplayCutoutEmulationHoleOverlay/res/values-land/config.xml b/packages/overlays/DisplayCutoutEmulationHoleOverlay/res/values-land/config.xml
deleted file mode 100644
index 2e971de..0000000
--- a/packages/overlays/DisplayCutoutEmulationHoleOverlay/res/values-land/config.xml
+++ /dev/null
@@ -1,22 +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
- -->
-
-<resources>
- <!-- Can't link to other dimensions here, but this should be status_bar_height_landscape -->
- <dimen name="quick_qs_offset_height">28dp</dimen>
- <!-- Total height of QQS in landscape; quick_qs_offset_height + 128 -->
- <dimen name="quick_qs_total_height">156dp</dimen>
-</resources>
diff --git a/packages/overlays/DisplayCutoutEmulationHoleOverlay/res/values/config.xml b/packages/overlays/DisplayCutoutEmulationHoleOverlay/res/values/config.xml
index 9f558d0..62f0535 100644
--- a/packages/overlays/DisplayCutoutEmulationHoleOverlay/res/values/config.xml
+++ b/packages/overlays/DisplayCutoutEmulationHoleOverlay/res/values/config.xml
@@ -48,14 +48,6 @@
-->
<bool name="config_fillMainBuiltInDisplayCutout">true</bool>
- <!-- Height of the status bar -->
- <dimen name="status_bar_height_portrait">136px</dimen>
- <dimen name="status_bar_height_landscape">28dp</dimen>
- <!-- Height of area above QQS where battery/time go (equal to status bar) -->
- <dimen name="quick_qs_offset_height">136px</dimen>
- <!-- Total height of QQS (quick_qs_offset_height + 128) -->
- <dimen name="quick_qs_total_height">488px</dimen>
-
</resources>
diff --git a/packages/overlays/DisplayCutoutEmulationNarrowOverlay/res/values-land/config.xml b/packages/overlays/DisplayCutoutEmulationNarrowOverlay/res/values-land/config.xml
deleted file mode 100644
index bd52901..0000000
--- a/packages/overlays/DisplayCutoutEmulationNarrowOverlay/res/values-land/config.xml
+++ /dev/null
@@ -1,22 +0,0 @@
-<!--
- ~ 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>
- <!-- Can't link to other dimensions here, but this should be status_bar_height_landscape -->
- <dimen name="quick_qs_offset_height">28dp</dimen>
- <!-- Total height of QQS in landscape; quick_qs_offset_height + 128 -->
- <dimen name="quick_qs_total_height">156dp</dimen>
-</resources>
\ No newline at end of file
diff --git a/packages/overlays/DisplayCutoutEmulationNarrowOverlay/res/values/config.xml b/packages/overlays/DisplayCutoutEmulationNarrowOverlay/res/values/config.xml
index 6fb3c7f..a9f8b4b 100644
--- a/packages/overlays/DisplayCutoutEmulationNarrowOverlay/res/values/config.xml
+++ b/packages/overlays/DisplayCutoutEmulationNarrowOverlay/res/values/config.xml
@@ -47,14 +47,6 @@
-->
<bool name="config_fillMainBuiltInDisplayCutout">true</bool>
- <!-- Height of the status bar -->
- <dimen name="status_bar_height_portrait">48dp</dimen>
- <dimen name="status_bar_height_landscape">28dp</dimen>
- <!-- Height of area above QQS where battery/time go (equal to status bar height if > 48dp) -->
- <dimen name="quick_qs_offset_height">48dp</dimen>
- <!-- Total height of QQS (quick_qs_offset_height + 128) -->
- <dimen name="quick_qs_total_height">176dp</dimen>
-
</resources>
diff --git a/packages/overlays/DisplayCutoutEmulationTallOverlay/res/values-land/config.xml b/packages/overlays/DisplayCutoutEmulationTallOverlay/res/values-land/config.xml
deleted file mode 100644
index bd52901..0000000
--- a/packages/overlays/DisplayCutoutEmulationTallOverlay/res/values-land/config.xml
+++ /dev/null
@@ -1,22 +0,0 @@
-<!--
- ~ 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>
- <!-- Can't link to other dimensions here, but this should be status_bar_height_landscape -->
- <dimen name="quick_qs_offset_height">28dp</dimen>
- <!-- Total height of QQS in landscape; quick_qs_offset_height + 128 -->
- <dimen name="quick_qs_total_height">156dp</dimen>
-</resources>
\ No newline at end of file
diff --git a/packages/overlays/DisplayCutoutEmulationTallOverlay/res/values/config.xml b/packages/overlays/DisplayCutoutEmulationTallOverlay/res/values/config.xml
index 7c29ffb..be7d0e4 100644
--- a/packages/overlays/DisplayCutoutEmulationTallOverlay/res/values/config.xml
+++ b/packages/overlays/DisplayCutoutEmulationTallOverlay/res/values/config.xml
@@ -47,14 +47,6 @@
-->
<bool name="config_fillMainBuiltInDisplayCutout">true</bool>
- <!-- Height of the status bar -->
- <dimen name="status_bar_height_portrait">48dp</dimen>
- <dimen name="status_bar_height_landscape">28dp</dimen>
- <!-- Height of area above QQS where battery/time go (equal to status bar height if > 48dp) -->
- <dimen name="quick_qs_offset_height">48dp</dimen>
- <!-- Total height of QQS (quick_qs_offset_height + 128) -->
- <dimen name="quick_qs_total_height">176dp</dimen>
-
</resources>
diff --git a/packages/overlays/DisplayCutoutEmulationWaterfallOverlay/res/values-land/config.xml b/packages/overlays/DisplayCutoutEmulationWaterfallOverlay/res/values-land/config.xml
deleted file mode 100644
index df2f3d1..0000000
--- a/packages/overlays/DisplayCutoutEmulationWaterfallOverlay/res/values-land/config.xml
+++ /dev/null
@@ -1,22 +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.
- -->
-
-<resources>
- <!-- Can't link to other dimensions here, but this should be status_bar_height_landscape -->
- <dimen name="quick_qs_offset_height">48dp</dimen>
- <!-- Total height of QQS in landscape; quick_qs_offset_height + 128 -->
- <dimen name="quick_qs_total_height">176dp</dimen>
-</resources>
\ No newline at end of file
diff --git a/packages/overlays/DisplayCutoutEmulationWaterfallOverlay/res/values/config.xml b/packages/overlays/DisplayCutoutEmulationWaterfallOverlay/res/values/config.xml
index 8d0227e..cc51ebe 100644
--- a/packages/overlays/DisplayCutoutEmulationWaterfallOverlay/res/values/config.xml
+++ b/packages/overlays/DisplayCutoutEmulationWaterfallOverlay/res/values/config.xml
@@ -19,16 +19,6 @@
<string translatable="false" name="config_mainBuiltInDisplayCutout"></string>
<string translatable="false" name="config_mainBuiltInDisplayCutoutRectApproximation"></string>
- <!-- Height of the status bar in portrait. The height should be
- Max((status bar content height + waterfall top size), top cutout size) -->
- <dimen name="status_bar_height_portrait">28dp</dimen>
- <!-- Max((28 + 20), 0) = 48 -->
- <dimen name="status_bar_height_landscape">48dp</dimen>
- <!-- Height of area above QQS where battery/time go (equal to status bar height if > 48dp) -->
- <dimen name="quick_qs_offset_height">48dp</dimen>
- <!-- Total height of QQS (quick_qs_offset_height + 128) -->
- <dimen name="quick_qs_total_height">176dp</dimen>
-
<dimen name="waterfall_display_left_edge_size">20dp</dimen>
<dimen name="waterfall_display_top_edge_size">0dp</dimen>
<dimen name="waterfall_display_right_edge_size">20dp</dimen>
diff --git a/packages/overlays/DisplayCutoutEmulationWideOverlay/res/values-land/config.xml b/packages/overlays/DisplayCutoutEmulationWideOverlay/res/values-land/config.xml
deleted file mode 100644
index bd52901..0000000
--- a/packages/overlays/DisplayCutoutEmulationWideOverlay/res/values-land/config.xml
+++ /dev/null
@@ -1,22 +0,0 @@
-<!--
- ~ 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>
- <!-- Can't link to other dimensions here, but this should be status_bar_height_landscape -->
- <dimen name="quick_qs_offset_height">28dp</dimen>
- <!-- Total height of QQS in landscape; quick_qs_offset_height + 128 -->
- <dimen name="quick_qs_total_height">156dp</dimen>
-</resources>
\ No newline at end of file
diff --git a/packages/overlays/DisplayCutoutEmulationWideOverlay/res/values/config.xml b/packages/overlays/DisplayCutoutEmulationWideOverlay/res/values/config.xml
index 5fb8b9e..78cc7e0 100644
--- a/packages/overlays/DisplayCutoutEmulationWideOverlay/res/values/config.xml
+++ b/packages/overlays/DisplayCutoutEmulationWideOverlay/res/values/config.xml
@@ -47,14 +47,6 @@
-->
<bool name="config_fillMainBuiltInDisplayCutout">true</bool>
- <!-- Height of the status bar -->
- <dimen name="status_bar_height_portrait">48dp</dimen>
- <dimen name="status_bar_height_landscape">28dp</dimen>
- <!-- Height of area above QQS where battery/time go (equal to status bar height if > 48dp) -->
- <dimen name="quick_qs_offset_height">48dp</dimen>
- <!-- Total height of QQS (quick_qs_offset_height + 128) -->
- <dimen name="quick_qs_total_height">176dp</dimen>
-
</resources>
diff --git a/packages/overlays/NoCutoutOverlay/res/values/config.xml b/packages/overlays/NoCutoutOverlay/res/values/config.xml
index 9157699..84b91b8 100644
--- a/packages/overlays/NoCutoutOverlay/res/values/config.xml
+++ b/packages/overlays/NoCutoutOverlay/res/values/config.xml
@@ -25,12 +25,4 @@
by shrinking the display such that it does not overlap the cutout area. -->
<bool name="config_maskMainBuiltInDisplayCutout">true</bool>
- <!-- Height of the status bar -->
- <dimen name="status_bar_height_portrait">28dp</dimen>
- <dimen name="status_bar_height_landscape">28dp</dimen>
-
- <!-- Height of area above QQS where battery/time go (equal to status bar height if > 48dp) -->
- <dimen name="quick_qs_offset_height">48dp</dimen>
- <!-- Total height of QQS (quick_qs_offset_height + 128) -->
- <dimen name="quick_qs_total_height">176dp</dimen>
</resources>
diff --git a/services/accessibility/java/com/android/server/accessibility/AccessibilityManagerService.java b/services/accessibility/java/com/android/server/accessibility/AccessibilityManagerService.java
index 8205d35..e6f91a25f 100644
--- a/services/accessibility/java/com/android/server/accessibility/AccessibilityManagerService.java
+++ b/services/accessibility/java/com/android/server/accessibility/AccessibilityManagerService.java
@@ -128,6 +128,7 @@
import com.android.server.SystemService;
import com.android.server.accessibility.magnification.MagnificationController;
import com.android.server.accessibility.magnification.MagnificationProcessor;
+import com.android.server.accessibility.magnification.MagnificationScaleProvider;
import com.android.server.accessibility.magnification.WindowMagnificationManager;
import com.android.server.pm.UserManagerInternal;
import com.android.server.wm.ActivityTaskManagerInternal;
@@ -338,7 +339,8 @@
mA11yWindowManager = new AccessibilityWindowManager(mLock, mMainHandler,
mWindowManagerService, this, mSecurityPolicy, this, mTraceManager);
mA11yDisplayListener = new AccessibilityDisplayListener(mContext, mMainHandler);
- mMagnificationController = new MagnificationController(this, mLock, mContext);
+ mMagnificationController = new MagnificationController(this, mLock, mContext,
+ new MagnificationScaleProvider(mContext));
mMagnificationProcessor = new MagnificationProcessor(mMagnificationController);
init();
}
@@ -1364,6 +1366,7 @@
}
private void switchUser(int userId) {
+ mMagnificationController.updateUserIdIfNeeded(userId);
synchronized (mLock) {
if (mCurrentUserId == userId && mInitialized) {
return;
@@ -1386,8 +1389,6 @@
// The user changed.
mCurrentUserId = userId;
-
- mMagnificationController.updateUserIdIfNeeded(mCurrentUserId);
AccessibilityUserState userState = getCurrentUserStateLocked();
readConfigurationForUserStateLocked(userState);
@@ -1444,6 +1445,7 @@
synchronized (mLock) {
mUserStates.remove(userId);
}
+ getMagnificationController().onUserRemoved(userId);
}
// Called only during settings restore; currently supports only the owner user
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 8f30aa9a..c62473d 100644
--- a/services/accessibility/java/com/android/server/accessibility/magnification/FullScreenMagnificationController.java
+++ b/services/accessibility/java/com/android/server/accessibility/magnification/FullScreenMagnificationController.java
@@ -28,10 +28,8 @@
import android.content.IntentFilter;
import android.graphics.Rect;
import android.graphics.Region;
-import android.os.AsyncTask;
import android.os.Handler;
import android.os.Message;
-import android.provider.Settings;
import android.text.TextUtils;
import android.util.MathUtils;
import android.util.Slog;
@@ -59,7 +57,8 @@
* holding the current state of magnification and animation, and it handles
* communication between the accessibility manager and window manager.
*
- * Magnification is limited to the range [MIN_SCALE, MAX_SCALE], and can only occur inside the
+ * Magnification is limited to the range controlled by
+ * {@link MagnificationScaleProvider#constrainScale(float)}, and can only occur inside the
* magnification region. If a value is out of bounds, it will be adjusted to guarantee these
* constraints.
*/
@@ -69,13 +68,9 @@
private static final MagnificationAnimationCallback STUB_ANIMATION_CALLBACK = success -> {
};
- public static final float MIN_SCALE = 1.0f;
- public static final float MAX_SCALE = 8.0f;
private static final boolean DEBUG_SET_MAGNIFICATION_SPEC = false;
- private static final float DEFAULT_MAGNIFICATION_SCALE = 2.0f;
-
private final Object mLock;
private final ControllerContext mControllerCtx;
@@ -84,7 +79,7 @@
private final MagnificationInfoChangedCallback mMagnificationInfoChangedCallback;
- private int mUserId;
+ private final MagnificationScaleProvider mScaleProvider;
private final long mMainThreadId;
@@ -489,7 +484,7 @@
return false;
}
// Constrain scale immediately for use in the pivot calculations.
- scale = MathUtils.constrain(scale, MIN_SCALE, MAX_SCALE);
+ scale = MagnificationScaleProvider.constrainScale(scale);
final Rect viewport = mTempRect;
mMagnificationRegion.getBounds(viewport);
@@ -557,7 +552,7 @@
// Compute changes.
boolean changed = false;
- final float normScale = MathUtils.constrain(scale, MIN_SCALE, MAX_SCALE);
+ final float normScale = MagnificationScaleProvider.constrainScale(scale);
if (Float.compare(mCurrentMagnificationSpec.scale, normScale) != 0) {
mCurrentMagnificationSpec.scale = normScale;
changed = true;
@@ -658,12 +653,13 @@
*/
public FullScreenMagnificationController(@NonNull Context context,
@NonNull AccessibilityManagerService ams, @NonNull Object lock,
- @NonNull MagnificationInfoChangedCallback magnificationInfoChangedCallback) {
+ @NonNull MagnificationInfoChangedCallback magnificationInfoChangedCallback,
+ @NonNull MagnificationScaleProvider scaleProvider) {
this(new ControllerContext(context, ams,
LocalServices.getService(WindowManagerInternal.class),
new Handler(context.getMainLooper()),
context.getResources().getInteger(R.integer.config_longAnimTime)), lock,
- magnificationInfoChangedCallback);
+ magnificationInfoChangedCallback, scaleProvider);
}
/**
@@ -672,12 +668,14 @@
@VisibleForTesting
public FullScreenMagnificationController(@NonNull ControllerContext ctx,
@NonNull Object lock,
- @NonNull MagnificationInfoChangedCallback magnificationInfoChangedCallback) {
+ @NonNull MagnificationInfoChangedCallback magnificationInfoChangedCallback,
+ @NonNull MagnificationScaleProvider scaleProvider) {
mControllerCtx = ctx;
mLock = lock;
mMainThreadId = mControllerCtx.getContext().getMainLooper().getThread().getId();
mScreenStateObserver = new ScreenStateObserver(mControllerCtx.getContext(), this);
mMagnificationInfoChangedCallback = magnificationInfoChangedCallback;
+ mScaleProvider = scaleProvider;
}
/**
@@ -1096,18 +1094,9 @@
/**
* Persists the default display magnification scale to the current user's settings.
*/
- public void persistScale() {
- // TODO: b/123047354, Need support multi-display?
+ public void persistScale(int displayId) {
final float scale = getScale(Display.DEFAULT_DISPLAY);
- final int userId = mUserId;
-
- new AsyncTask<Void, Void, Void>() {
- @Override
- protected Void doInBackground(Void... params) {
- mControllerCtx.putMagnificationScale(scale, userId);
- return null;
- }
- }.execute();
+ mScaleProvider.putScale(scale, displayId);
}
/**
@@ -1117,21 +1106,8 @@
* @return the previously persisted magnification scale, or the default
* scale if none is available
*/
- public float getPersistedScale() {
- return mControllerCtx.getMagnificationScale(mUserId);
- }
-
- /**
- * Sets the currently active user ID.
- *
- * @param userId the currently active user ID
- */
- public void setUserId(int userId) {
- if (mUserId == userId) {
- return;
- }
- mUserId = userId;
- resetAllIfNeeded(false);
+ public float getPersistedScale(int displayId) {
+ return mScaleProvider.getScale(displayId);
}
/**
@@ -1225,7 +1201,11 @@
mControllerCtx.getHandler().sendMessage(m);
}
- private void resetAllIfNeeded(boolean animate) {
+ /**
+ * Resets magnification on all displays.
+ * @param animate reset the magnification with animation
+ */
+ void resetAllIfNeeded(boolean animate) {
synchronized (mLock) {
for (int i = 0; i < mDisplays.size(); i++) {
resetIfNeeded(mDisplays.keyAt(i), animate);
@@ -1288,8 +1268,8 @@
public String toString() {
StringBuilder builder = new StringBuilder();
builder.append("MagnificationController[");
- builder.append("mUserId=").append(mUserId);
builder.append(", mDisplays=").append(mDisplays);
+ builder.append(", mScaleProvider=").append(mScaleProvider);
builder.append("]");
return builder.toString();
}
@@ -1570,23 +1550,6 @@
}
/**
- * Write Settings of magnification scale.
- */
- public void putMagnificationScale(float value, int userId) {
- Settings.Secure.putFloatForUser(mContext.getContentResolver(),
- Settings.Secure.ACCESSIBILITY_DISPLAY_MAGNIFICATION_SCALE, value, userId);
- }
-
- /**
- * Get Settings of magnification scale.
- */
- public float getMagnificationScale(int userId) {
- return Settings.Secure.getFloatForUser(mContext.getContentResolver(),
- Settings.Secure.ACCESSIBILITY_DISPLAY_MAGNIFICATION_SCALE,
- DEFAULT_MAGNIFICATION_SCALE, userId);
- }
-
- /**
* @return Configuration of animation duration.
*/
public long getAnimationDuration() {
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 8f4a5cb..935df99 100644
--- a/services/accessibility/java/com/android/server/accessibility/magnification/FullScreenMagnificationGestureHandler.java
+++ b/services/accessibility/java/com/android/server/accessibility/magnification/FullScreenMagnificationGestureHandler.java
@@ -119,11 +119,11 @@
private static final boolean DEBUG_DETECTING = false | DEBUG_ALL;
private static final boolean DEBUG_PANNING_SCALING = false | DEBUG_ALL;
- // The MIN_SCALE is different from MagnificationController.MIN_SCALE due
+ // 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 MAX_SCALE = FullScreenMagnificationController.MAX_SCALE;
+ private static final float MAX_SCALE = MagnificationScaleProvider.MAX_SCALE;
@VisibleForTesting final FullScreenMagnificationController mFullScreenMagnificationController;
@@ -341,7 +341,7 @@
}
public void persistScaleAndTransitionTo(State state) {
- mFullScreenMagnificationController.persistScale();
+ mFullScreenMagnificationController.persistScale(mDisplayId);
clear();
transitionTo(state);
}
@@ -945,7 +945,7 @@
if (DEBUG_DETECTING) Slog.i(mLogTag, "zoomOn(" + centerX + ", " + centerY + ")");
final float scale = MathUtils.constrain(
- mFullScreenMagnificationController.getPersistedScale(),
+ mFullScreenMagnificationController.getPersistedScale(mDisplayId),
MIN_SCALE, MAX_SCALE);
mFullScreenMagnificationController.setScaleAndCenter(mDisplayId,
scale, centerX, centerY,
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 5a6836c..3708c7a 100644
--- a/services/accessibility/java/com/android/server/accessibility/magnification/MagnificationController.java
+++ b/services/accessibility/java/com/android/server/accessibility/magnification/MagnificationController.java
@@ -23,11 +23,13 @@
import android.annotation.NonNull;
import android.annotation.Nullable;
+import android.annotation.UserIdInt;
import android.content.Context;
import android.graphics.PointF;
import android.graphics.Rect;
import android.graphics.Region;
import android.os.SystemClock;
+import android.os.UserHandle;
import android.provider.Settings;
import android.util.Slog;
import android.util.SparseArray;
@@ -75,12 +77,15 @@
private final SparseArray<DisableMagnificationCallback>
mMagnificationEndRunnableSparseArray = new SparseArray();
+ private final MagnificationScaleProvider mScaleProvider;
private FullScreenMagnificationController mFullScreenMagnificationController;
private WindowMagnificationManager mWindowMagnificationMgr;
private int mMagnificationCapabilities = ACCESSIBILITY_MAGNIFICATION_MODE_FULLSCREEN;
@GuardedBy("mLock")
private int mActivatedMode = ACCESSIBILITY_MAGNIFICATION_MODE_NONE;
+ // Track the active user to reset the magnification and get the associated user settings.
+ private @UserIdInt int mUserId = UserHandle.USER_SYSTEM;
@GuardedBy("mLock")
private boolean mImeWindowVisible = false;
private long mWindowModeEnabledTime = 0;
@@ -98,17 +103,19 @@
}
public MagnificationController(AccessibilityManagerService ams, Object lock,
- Context context) {
+ Context context, MagnificationScaleProvider scaleProvider) {
mAms = ams;
mLock = lock;
mContext = context;
+ mScaleProvider = scaleProvider;
}
@VisibleForTesting
public MagnificationController(AccessibilityManagerService ams, Object lock,
Context context, FullScreenMagnificationController fullScreenMagnificationController,
- WindowMagnificationManager windowMagnificationManager) {
- this(ams, lock, context);
+ WindowMagnificationManager windowMagnificationManager,
+ MagnificationScaleProvider scaleProvider) {
+ this(ams, lock, context, scaleProvider);
mFullScreenMagnificationController = fullScreenMagnificationController;
mWindowMagnificationMgr = windowMagnificationManager;
}
@@ -194,7 +201,7 @@
final FullScreenMagnificationController screenMagnificationController =
getFullScreenMagnificationController();
final WindowMagnificationManager windowMagnificationMgr = getWindowMagnificationMgr();
- final float scale = windowMagnificationMgr.getPersistedScale();
+ final float scale = mScaleProvider.getScale(displayId);
final DisableMagnificationCallback animationEndCallback =
new DisableMagnificationCallback(transitionCallBack, displayId, targetMode,
scale, magnificationCenter);
@@ -313,13 +320,23 @@
* @param userId the currently active user ID
*/
public void updateUserIdIfNeeded(int userId) {
+ if (mUserId == userId) {
+ return;
+ }
+ mUserId = userId;
+ final FullScreenMagnificationController fullMagnificationController;
+ final WindowMagnificationManager windowMagnificationManager;
synchronized (mLock) {
- if (mFullScreenMagnificationController != null) {
- mFullScreenMagnificationController.setUserId(userId);
- }
- if (mWindowMagnificationMgr != null) {
- mWindowMagnificationMgr.setUserId(userId);
- }
+ fullMagnificationController = mFullScreenMagnificationController;
+ windowMagnificationManager = mWindowMagnificationMgr;
+ }
+
+ mScaleProvider.onUserChanged(userId);
+ if (fullMagnificationController != null) {
+ fullMagnificationController.resetAllIfNeeded(false);
+ }
+ if (windowMagnificationManager != null) {
+ windowMagnificationManager.disableAllWindowMagnifiers();
}
}
@@ -337,6 +354,14 @@
mWindowMagnificationMgr.onDisplayRemoved(displayId);
}
}
+ mScaleProvider.onDisplayRemoved(displayId);
+ }
+
+ /**
+ * Called when the given user is removed.
+ */
+ public void onUserRemoved(int userId) {
+ mScaleProvider.onUserRemoved(userId);
}
public void setMagnificationCapabilities(int capabilities) {
@@ -378,8 +403,7 @@
synchronized (mLock) {
if (mFullScreenMagnificationController == null) {
mFullScreenMagnificationController = new FullScreenMagnificationController(mContext,
- mAms, mLock, this);
- mFullScreenMagnificationController.setUserId(mAms.getCurrentUserIdLocked());
+ mAms, mLock, this, mScaleProvider);
}
}
return mFullScreenMagnificationController;
@@ -404,7 +428,8 @@
synchronized (mLock) {
if (mWindowMagnificationMgr == null) {
mWindowMagnificationMgr = new WindowMagnificationManager(mContext,
- mAms.getCurrentUserIdLocked(), this, mAms.getTraceManager());
+ mUserId, this, mAms.getTraceManager(),
+ mScaleProvider);
}
return mWindowMagnificationMgr;
}
diff --git a/services/accessibility/java/com/android/server/accessibility/magnification/MagnificationScaleProvider.java b/services/accessibility/java/com/android/server/accessibility/magnification/MagnificationScaleProvider.java
new file mode 100644
index 0000000..8e1aa38
--- /dev/null
+++ b/services/accessibility/java/com/android/server/accessibility/magnification/MagnificationScaleProvider.java
@@ -0,0 +1,139 @@
+/*
+ * Copyright (C) 2021 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.accessibility.magnification;
+
+import android.content.Context;
+import android.os.UserHandle;
+import android.provider.Settings;
+import android.util.MathUtils;
+import android.util.SparseArray;
+import android.view.Display;
+
+import com.android.internal.annotations.GuardedBy;
+import com.android.internal.annotations.VisibleForTesting;
+import com.android.internal.os.BackgroundThread;
+
+/**
+ * Supplies setter/getter of the magnification scale for the given display. Only the value of the
+ * default play is persisted. It also constraints the range of applied magnification scale between
+ * [MIN_SCALE, MAX_SCALE] which is consistent with the range provided by
+ * {@code AccessibilityService.MagnificationController#setScale()}.
+ */
+public class MagnificationScaleProvider {
+
+ @VisibleForTesting
+ protected static final float DEFAULT_MAGNIFICATION_SCALE = 2.0f;
+ public static final float MIN_SCALE = 1.0f;
+ public static final float MAX_SCALE = 8.0f;
+
+ private final Context mContext;
+ // Stores the scale for non-default displays.
+ @GuardedBy("mLock")
+ private final SparseArray<SparseArray<Float>> mUsersScales = new SparseArray();
+ private int mCurrentUserId = UserHandle.USER_SYSTEM;
+ private final Object mLock = new Object();
+
+ public MagnificationScaleProvider(Context context) {
+ mContext = context;
+ }
+
+ /**
+ * Stores the user settings scale associated to the given display. Only the scale of the
+ * default display is persistent.
+ *
+ * @param scale the magnification scale
+ * @param displayId the id of the display
+ */
+ void putScale(float scale, int displayId) {
+ if (displayId == Display.DEFAULT_DISPLAY) {
+ BackgroundThread.getHandler().post(
+ () -> Settings.Secure.putFloatForUser(mContext.getContentResolver(),
+ Settings.Secure.ACCESSIBILITY_DISPLAY_MAGNIFICATION_SCALE, scale,
+ mCurrentUserId));
+ } else {
+ synchronized (mLock) {
+ getScalesWithCurrentUser().put(displayId, scale);
+ }
+ }
+ }
+
+ /**
+ * Gets the user settings scale with the given display.
+ *
+ * @param displayId the id of the display
+ * @return the magnification scale.
+ */
+ float getScale(int displayId) {
+ if (displayId == Display.DEFAULT_DISPLAY) {
+ return Settings.Secure.getFloatForUser(mContext.getContentResolver(),
+ Settings.Secure.ACCESSIBILITY_DISPLAY_MAGNIFICATION_SCALE,
+ DEFAULT_MAGNIFICATION_SCALE, mCurrentUserId);
+ } else {
+ synchronized (mLock) {
+ return getScalesWithCurrentUser().get(displayId, DEFAULT_MAGNIFICATION_SCALE);
+ }
+ }
+ }
+
+
+ @GuardedBy("mLock")
+ private SparseArray<Float> getScalesWithCurrentUser() {
+ SparseArray<Float> scales = mUsersScales.get(mCurrentUserId);
+ if (scales == null) {
+ scales = new SparseArray<>();
+ mUsersScales.put(mCurrentUserId, scales);
+ }
+
+ return scales;
+ }
+
+ void onUserChanged(int userId) {
+ synchronized (mLock) {
+ mCurrentUserId = userId;
+ }
+ }
+
+ void onUserRemoved(int userId) {
+ synchronized (mLock) {
+ mUsersScales.remove(userId);
+ }
+ }
+
+ void onDisplayRemoved(int displayId) {
+ synchronized (mLock) {
+ final int userCounts = mUsersScales.size();
+ for (int i = userCounts - 1; i >= 0; i--) {
+ mUsersScales.get(i).remove(displayId);
+ }
+ }
+ }
+
+ @Override
+ public String toString() {
+ synchronized (mLock) {
+ return "MagnificationScaleProvider{"
+ + "mCurrentUserId=" + mCurrentUserId
+ + "Scale on the default display=" + getScale(Display.DEFAULT_DISPLAY)
+ + "Scales on non-default displays=" + getScalesWithCurrentUser()
+ + '}';
+ }
+ }
+
+ static float constrainScale(float scale) {
+ return MathUtils.constrain(scale, MIN_SCALE, MAX_SCALE);
+ }
+}
diff --git a/services/accessibility/java/com/android/server/accessibility/magnification/WindowMagnificationGestureHandler.java b/services/accessibility/java/com/android/server/accessibility/magnification/WindowMagnificationGestureHandler.java
index bc61284..7d8f545 100644
--- a/services/accessibility/java/com/android/server/accessibility/magnification/WindowMagnificationGestureHandler.java
+++ b/services/accessibility/java/com/android/server/accessibility/magnification/WindowMagnificationGestureHandler.java
@@ -69,7 +69,7 @@
//Ensure the range has consistency with FullScreenMagnificationGestureHandler.
private static final float MIN_SCALE = 2.0f;
- private static final float MAX_SCALE = WindowMagnificationManager.MAX_SCALE;
+ private static final float MAX_SCALE = MagnificationScaleProvider.MAX_SCALE;
private final WindowMagnificationManager mWindowMagnificationMgr;
@VisibleForTesting
@@ -177,8 +177,7 @@
}
final float scale = MathUtils.constrain(
- mWindowMagnificationMgr.getPersistedScale(),
- MIN_SCALE, MAX_SCALE);
+ mWindowMagnificationMgr.getPersistedScale(mDisplayId), MIN_SCALE, MAX_SCALE);
mWindowMagnificationMgr.enableWindowMagnification(mDisplayId, scale, centerX, centerY);
}
diff --git a/services/accessibility/java/com/android/server/accessibility/magnification/WindowMagnificationManager.java b/services/accessibility/java/com/android/server/accessibility/magnification/WindowMagnificationManager.java
index 7a111d8..ce7ba75 100644
--- a/services/accessibility/java/com/android/server/accessibility/magnification/WindowMagnificationManager.java
+++ b/services/accessibility/java/com/android/server/accessibility/magnification/WindowMagnificationManager.java
@@ -29,8 +29,6 @@
import android.os.Binder;
import android.os.IBinder;
import android.os.RemoteException;
-import android.provider.Settings;
-import android.util.MathUtils;
import android.util.Slog;
import android.util.SparseArray;
import android.view.MotionEvent;
@@ -40,7 +38,6 @@
import com.android.internal.annotations.GuardedBy;
import com.android.internal.annotations.VisibleForTesting;
-import com.android.internal.os.BackgroundThread;
import com.android.server.LocalServices;
import com.android.server.accessibility.AccessibilityTraceManager;
import com.android.server.statusbar.StatusBarManagerInternal;
@@ -49,6 +46,8 @@
* A class to manipulate window magnification through {@link WindowMagnificationConnectionWrapper}
* create by {@link #setConnection(IWindowMagnificationConnection)}. To set the connection with
* SysUI, call {@code StatusBarManagerInternal#requestWindowMagnificationConnection(boolean)}.
+ * The applied magnification scale is constrained by
+ * {@link MagnificationScaleProvider#constrainScale(float)}
*/
public class WindowMagnificationManager implements
PanningScalingHandler.MagnificationDelegate {
@@ -57,10 +56,6 @@
private static final String TAG = "WindowMagnificationMgr";
- //Ensure the range has consistency with full screen.
- static final float MAX_SCALE = FullScreenMagnificationController.MAX_SCALE;
- static final float MIN_SCALE = FullScreenMagnificationController.MIN_SCALE;
-
private final Object mLock = new Object();
private final Context mContext;
@VisibleForTesting
@@ -71,7 +66,6 @@
private ConnectionCallback mConnectionCallback;
@GuardedBy("mLock")
private SparseArray<WindowMagnifier> mWindowMagnifiers = new SparseArray<>();
- private int mUserId;
private boolean mReceiverRegistered = false;
@VisibleForTesting
@@ -116,13 +110,14 @@
private final Callback mCallback;
private final AccessibilityTraceManager mTrace;
+ private final MagnificationScaleProvider mScaleProvider;
public WindowMagnificationManager(Context context, int userId, @NonNull Callback callback,
- AccessibilityTraceManager trace) {
+ AccessibilityTraceManager trace, MagnificationScaleProvider scaleProvider) {
mContext = context;
- mUserId = userId;
mCallback = callback;
mTrace = trace;
+ mScaleProvider = scaleProvider;
}
/**
@@ -159,15 +154,6 @@
}
/**
- * Sets the currently active user ID.
- *
- * @param userId the currently active user ID
- */
- public void setUserId(int userId) {
- mUserId = userId;
- }
-
- /**
* @return {@code true} if {@link IWindowMagnificationConnection} is available
*/
public boolean isConnected() {
@@ -219,13 +205,18 @@
return true;
}
- @GuardedBy("mLock")
- private void disableAllWindowMagnifiers() {
- for (int i = 0; i < mWindowMagnifiers.size(); i++) {
- final WindowMagnifier magnifier = mWindowMagnifiers.valueAt(i);
- magnifier.disableWindowMagnificationInternal(null);
+ /**
+ * Disables window magnifier on all displays without animation.
+ */
+ void disableAllWindowMagnifiers() {
+ synchronized (mLock) {
+ for (int i = 0; i < mWindowMagnifiers.size(); i++) {
+ final WindowMagnifier magnifier = mWindowMagnifiers.valueAt(i);
+ magnifier.disableWindowMagnificationInternal(null);
+ }
+ mWindowMagnifiers.clear();
}
- mWindowMagnifiers.clear();
+
}
private void resetWindowMagnifiers() {
@@ -378,29 +369,24 @@
}
/**
- * Retrieves a previously persisted magnification scale from the current
- * user's settings.
+ * Retrieves a previously magnification scale from the current
+ * user's settings. Only the value of the default display is persisted.
*
- * @return the previously persisted magnification scale, or the default
+ * @return the previously magnification scale, or the default
* scale if none is available
*/
- float getPersistedScale() {
- return Settings.Secure.getFloatForUser(mContext.getContentResolver(),
- Settings.Secure.ACCESSIBILITY_DISPLAY_MAGNIFICATION_SCALE,
- MIN_SCALE, mUserId);
+ float getPersistedScale(int displayId) {
+ return mScaleProvider.getScale(displayId);
}
/**
- * Persists the default display magnification scale to the current user's settings.
+ * Persists the default display magnification scale to the current user's settings. Only the
+ * value of the default display is persisted in user's settings.
*/
void persistScale(int displayId) {
-
float scale = getScale(displayId);
if (scale != 1.0f) {
- BackgroundThread.getHandler().post(() -> {
- Settings.Secure.putFloatForUser(mContext.getContentResolver(),
- Settings.Secure.ACCESSIBILITY_DISPLAY_MAGNIFICATION_SCALE, scale, mUserId);
- });
+ mScaleProvider.putScale(scale, displayId);
}
}
@@ -511,7 +497,7 @@
*
* @param displayId The logical display id.
*/
- void onDisplayRemoved(int displayId) {
+ public void onDisplayRemoved(int displayId) {
disableWindowMagnification(displayId, true);
}
@@ -613,7 +599,7 @@
private static class WindowMagnifier {
private final int mDisplayId;
- private float mScale = MIN_SCALE;
+ private float mScale = MagnificationScaleProvider.MIN_SCALE;
private boolean mEnabled;
private final WindowMagnificationManager mWindowMagnificationManager;
@@ -633,7 +619,7 @@
if (mEnabled) {
return false;
}
- final float normScale = MathUtils.constrain(scale, MIN_SCALE, MAX_SCALE);
+ final float normScale = MagnificationScaleProvider.constrainScale(scale);
if (mWindowMagnificationManager.enableWindowMagnificationInternal(mDisplayId, normScale,
centerX, centerY, animationCallback)) {
mScale = normScale;
@@ -664,7 +650,7 @@
if (!mEnabled) {
return;
}
- final float normScale = MathUtils.constrain(scale, MIN_SCALE, MAX_SCALE);
+ final float normScale = MagnificationScaleProvider.constrainScale(scale);
if (Float.compare(mScale, normScale) != 0
&& mWindowMagnificationManager.setScaleInternal(mDisplayId, scale)) {
mScale = normScale;
diff --git a/services/accessibility/java/com/android/server/accessibility/magnification/WindowMagnificationPromptController.java b/services/accessibility/java/com/android/server/accessibility/magnification/WindowMagnificationPromptController.java
index 1fdd908..ecf999e 100644
--- a/services/accessibility/java/com/android/server/accessibility/magnification/WindowMagnificationPromptController.java
+++ b/services/accessibility/java/com/android/server/accessibility/magnification/WindowMagnificationPromptController.java
@@ -160,7 +160,7 @@
intentFilter.addAction(ACTION_DISMISS);
intentFilter.addAction(ACTION_TURN_ON_IN_SETTINGS);
mContext.registerReceiver(mNotificationActionReceiver, intentFilter,
- Manifest.permission.MANAGE_ACCESSIBILITY, null);
+ Manifest.permission.MANAGE_ACCESSIBILITY, null, Context.RECEIVER_EXPORTED);
}
private void launchMagnificationSettings() {
diff --git a/services/appprediction/java/com/android/server/appprediction/AppPredictionPerUserService.java b/services/appprediction/java/com/android/server/appprediction/AppPredictionPerUserService.java
index 4946ad4..1af8ad3 100644
--- a/services/appprediction/java/com/android/server/appprediction/AppPredictionPerUserService.java
+++ b/services/appprediction/java/com/android/server/appprediction/AppPredictionPerUserService.java
@@ -187,7 +187,7 @@
@NonNull IPredictionCallback callback) {
final AppPredictionSessionInfo sessionInfo = mSessionInfos.get(sessionId);
if (sessionInfo == null) return;
- final boolean serviceExists = resolveService(sessionId, false,
+ final boolean serviceExists = resolveService(sessionId, true,
sessionInfo.mUsesPeopleService,
s -> s.registerPredictionUpdates(sessionId, callback));
if (serviceExists) {
diff --git a/services/appwidget/java/com/android/server/appwidget/AppWidgetServiceImpl.java b/services/appwidget/java/com/android/server/appwidget/AppWidgetServiceImpl.java
index c32543a..78d9095 100644
--- a/services/appwidget/java/com/android/server/appwidget/AppWidgetServiceImpl.java
+++ b/services/appwidget/java/com/android/server/appwidget/AppWidgetServiceImpl.java
@@ -147,7 +147,7 @@
OnCrossProfileWidgetProvidersChangeListener {
private static final String TAG = "AppWidgetServiceImpl";
- private static boolean DEBUG = false;
+ private static final boolean DEBUG = false;
private static final String OLD_KEYGUARD_HOST_PACKAGE = "android";
private static final String NEW_KEYGUARD_HOST_PACKAGE = "com.android.keyguard";
diff --git a/services/companion/Android.bp b/services/companion/Android.bp
index 4ae9365..e3926b4 100644
--- a/services/companion/Android.bp
+++ b/services/companion/Android.bp
@@ -9,7 +9,10 @@
filegroup {
name: "services.companion-sources",
- srcs: ["java/**/*.java"],
+ srcs: [
+ "java/**/*.java",
+ "java/**/*.proto",
+ ],
path: "java",
visibility: ["//frameworks/base/services"],
}
@@ -17,6 +20,9 @@
java_library_static {
name: "services.companion",
defaults: ["platform_service_defaults"],
+ proto: {
+ type: "stream",
+ },
srcs: [":services.companion-sources"],
libs: ["services.core"],
}
diff --git a/services/companion/java/com/android/server/companion/AssociationRequestsProcessor.java b/services/companion/java/com/android/server/companion/AssociationRequestsProcessor.java
new file mode 100644
index 0000000..1fd7951
--- /dev/null
+++ b/services/companion/java/com/android/server/companion/AssociationRequestsProcessor.java
@@ -0,0 +1,323 @@
+/*
+ * Copyright (C) 2021 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.companion;
+
+import static android.companion.AssociationRequest.DEVICE_PROFILE_APP_STREAMING;
+import static android.companion.AssociationRequest.DEVICE_PROFILE_WATCH;
+import static android.content.pm.PackageManager.PERMISSION_GRANTED;
+
+import static com.android.internal.util.CollectionUtils.filter;
+import static com.android.internal.util.FunctionalUtils.uncheckExceptions;
+import static com.android.internal.util.Preconditions.checkNotNull;
+import static com.android.server.companion.CompanionDeviceManagerService.DEBUG;
+import static com.android.server.companion.CompanionDeviceManagerService.LOG_TAG;
+import static com.android.server.companion.CompanionDeviceManagerService.getCallingUserId;
+
+import static java.util.Collections.unmodifiableMap;
+
+import android.Manifest;
+import android.annotation.NonNull;
+import android.annotation.Nullable;
+import android.companion.AssociationInfo;
+import android.companion.AssociationRequest;
+import android.companion.CompanionDeviceManager;
+import android.companion.ICompanionDeviceDiscoveryService;
+import android.companion.IFindDeviceCallback;
+import android.content.ComponentName;
+import android.content.Context;
+import android.content.Intent;
+import android.content.pm.Signature;
+import android.os.IBinder;
+import android.os.RemoteException;
+import android.util.ArrayMap;
+import android.util.PackageUtils;
+import android.util.Slog;
+
+import com.android.internal.infra.AndroidFuture;
+import com.android.internal.infra.PerUser;
+import com.android.internal.infra.ServiceConnector;
+import com.android.internal.util.ArrayUtils;
+import com.android.server.FgThread;
+
+import java.io.PrintWriter;
+import java.util.Arrays;
+import java.util.HashSet;
+import java.util.Map;
+import java.util.Objects;
+import java.util.Set;
+
+class AssociationRequestsProcessor {
+ private static final String TAG = LOG_TAG + ".AssociationRequestsProcessor";
+
+ private static final Map<String, String> DEVICE_PROFILE_TO_PERMISSION;
+ static {
+ final Map<String, String> map = new ArrayMap<>();
+ map.put(DEVICE_PROFILE_WATCH, Manifest.permission.REQUEST_COMPANION_PROFILE_WATCH);
+ map.put(DEVICE_PROFILE_APP_STREAMING,
+ Manifest.permission.REQUEST_COMPANION_PROFILE_APP_STREAMING);
+
+ DEVICE_PROFILE_TO_PERMISSION = unmodifiableMap(map);
+ }
+
+ private static final ComponentName SERVICE_TO_BIND_TO = ComponentName.createRelative(
+ CompanionDeviceManager.COMPANION_DEVICE_DISCOVERY_PACKAGE_NAME,
+ ".CompanionDeviceDiscoveryService");
+
+ private static final int ASSOCIATE_WITHOUT_PROMPT_MAX_PER_TIME_WINDOW = 5;
+ private static final long ASSOCIATE_WITHOUT_PROMPT_WINDOW_MS = 60 * 60 * 1000; // 60 min;
+
+ private final Context mContext;
+ private final CompanionDeviceManagerService mService;
+
+ private AssociationRequest mRequest;
+ private IFindDeviceCallback mFindDeviceCallback;
+ private String mCallingPackage;
+ private AndroidFuture<?> mOngoingDeviceDiscovery;
+
+ private PerUser<ServiceConnector<ICompanionDeviceDiscoveryService>> mServiceConnectors;
+
+ AssociationRequestsProcessor(CompanionDeviceManagerService service) {
+ mContext = service.getContext();
+ mService = service;
+
+ final Intent serviceIntent = new Intent().setComponent(SERVICE_TO_BIND_TO);
+ mServiceConnectors = new PerUser<ServiceConnector<ICompanionDeviceDiscoveryService>>() {
+ @Override
+ protected ServiceConnector<ICompanionDeviceDiscoveryService> create(int userId) {
+ return new ServiceConnector.Impl<>(
+ mContext,
+ serviceIntent, 0/* bindingFlags */, userId,
+ ICompanionDeviceDiscoveryService.Stub::asInterface);
+ }
+ };
+ }
+
+ void process(AssociationRequest request, IFindDeviceCallback callback, String callingPackage)
+ throws RemoteException {
+ if (DEBUG) {
+ Slog.d(TAG, "process(request=" + request + ", from=" + callingPackage + ")");
+ }
+
+ checkNotNull(request, "Request cannot be null");
+ checkNotNull(callback, "Callback cannot be null");
+ mService.checkCallerIsSystemOr(callingPackage);
+ int userId = getCallingUserId();
+ mService.checkUsesFeature(callingPackage, userId);
+ final String deviceProfile = request.getDeviceProfile();
+ validateDeviceProfileAndCheckPermission(deviceProfile);
+
+ mFindDeviceCallback = callback;
+ mRequest = request;
+ mCallingPackage = callingPackage;
+ request.setCallingPackage(callingPackage);
+
+ if (mayAssociateWithoutPrompt(callingPackage, userId)) {
+ Slog.i(TAG, "setSkipPrompt(true)");
+ request.setSkipPrompt(true);
+ }
+ callback.asBinder().linkToDeath(mBinderDeathRecipient /* recipient */, 0);
+
+ mOngoingDeviceDiscovery = getDeviceProfilePermissionDescription(deviceProfile)
+ .thenComposeAsync(description -> {
+ if (DEBUG) {
+ Slog.d(TAG, "fetchProfileDescription done: " + description);
+ }
+
+ request.setDeviceProfilePrivilegesDescription(description);
+
+ return mServiceConnectors.forUser(userId).postAsync(service -> {
+ if (DEBUG) {
+ Slog.d(TAG, "Connected to CDM service -> "
+ + "Starting discovery for " + request);
+ }
+
+ AndroidFuture<String> future = new AndroidFuture<>();
+ service.startDiscovery(request, callingPackage, callback, future);
+ return future;
+ }).cancelTimeout();
+
+ }, FgThread.getExecutor()).whenComplete(uncheckExceptions((deviceAddress, err) -> {
+ if (err == null) {
+ mService.createAssociationInternal(
+ userId, deviceAddress, callingPackage, deviceProfile);
+ mServiceConnectors.forUser(userId).post(service -> {
+ service.onAssociationCreated();
+ });
+ } else {
+ Slog.e(TAG, "Failed to discover device(s)", err);
+ callback.onFailure("No devices found: " + err.getMessage());
+ }
+ cleanup();
+ }));
+ }
+
+ void stopScan(AssociationRequest request, IFindDeviceCallback callback, String callingPackage) {
+ if (DEBUG) {
+ Slog.d(TAG, "stopScan(request = " + request + ")");
+ }
+ if (Objects.equals(request, mRequest)
+ && Objects.equals(callback, mFindDeviceCallback)
+ && Objects.equals(callingPackage, mCallingPackage)) {
+ cleanup();
+ }
+ }
+
+ private void validateDeviceProfileAndCheckPermission(@Nullable String deviceProfile) {
+ // Device profile can be null.
+ if (deviceProfile == null) return;
+
+ if (DEVICE_PROFILE_APP_STREAMING.equals(deviceProfile)) {
+ // TODO: remove, when properly supporting this profile.
+ throw new UnsupportedOperationException(
+ "DEVICE_PROFILE_APP_STREAMING is not fully supported yet.");
+ }
+
+ if (!DEVICE_PROFILE_TO_PERMISSION.containsKey(deviceProfile)) {
+ throw new IllegalArgumentException("Unsupported device profile: " + deviceProfile);
+ }
+
+ final String permission = DEVICE_PROFILE_TO_PERMISSION.get(deviceProfile);
+ if (mContext.checkCallingOrSelfPermission(permission) != PERMISSION_GRANTED) {
+ throw new SecurityException("Application must hold " + permission + " to associate "
+ + "with a device with " + deviceProfile + " profile.");
+ }
+ }
+
+ private void cleanup() {
+ if (DEBUG) {
+ Slog.d(TAG, "cleanup(); discovery = "
+ + mOngoingDeviceDiscovery + ", request = " + mRequest);
+ }
+ synchronized (mService.mLock) {
+ AndroidFuture<?> ongoingDeviceDiscovery = mOngoingDeviceDiscovery;
+ if (ongoingDeviceDiscovery != null && !ongoingDeviceDiscovery.isDone()) {
+ ongoingDeviceDiscovery.cancel(true);
+ }
+ if (mFindDeviceCallback != null) {
+ mFindDeviceCallback.asBinder().unlinkToDeath(mBinderDeathRecipient, 0);
+ mFindDeviceCallback = null;
+ }
+ mRequest = null;
+ mCallingPackage = null;
+ }
+ }
+
+ private boolean mayAssociateWithoutPrompt(String packageName, int userId) {
+ String[] sameOemPackages = mContext.getResources()
+ .getStringArray(com.android.internal.R.array.config_companionDevicePackages);
+ if (!ArrayUtils.contains(sameOemPackages, packageName)) {
+ Slog.w(TAG, packageName
+ + " can not silently create associations due to no package found."
+ + " Packages from OEM: " + Arrays.toString(sameOemPackages)
+ );
+ return false;
+ }
+
+ // Throttle frequent associations
+ long now = System.currentTimeMillis();
+ Set<AssociationInfo> recentAssociations = filter(
+ mService.getAllAssociations(userId, packageName),
+ a -> now - a.getTimeApprovedMs() < ASSOCIATE_WITHOUT_PROMPT_WINDOW_MS);
+
+ if (recentAssociations.size() >= ASSOCIATE_WITHOUT_PROMPT_MAX_PER_TIME_WINDOW) {
+ Slog.w(TAG, "Too many associations. " + packageName
+ + " already associated " + recentAssociations.size()
+ + " devices within the last " + ASSOCIATE_WITHOUT_PROMPT_WINDOW_MS
+ + "ms: " + recentAssociations);
+ return false;
+ }
+ String[] sameOemCerts = mContext.getResources()
+ .getStringArray(com.android.internal.R.array.config_companionDeviceCerts);
+
+ Signature[] signatures = mService.mPackageManagerInternal
+ .getPackage(packageName).getSigningDetails().getSignatures();
+ String[] apkCerts = PackageUtils.computeSignaturesSha256Digests(signatures);
+
+ Set<String> sameOemPackageCerts =
+ getSameOemPackageCerts(packageName, sameOemPackages, sameOemCerts);
+
+ for (String cert : apkCerts) {
+ if (sameOemPackageCerts.contains(cert)) {
+ return true;
+ }
+ }
+
+ Slog.w(TAG, packageName
+ + " can not silently create associations. " + packageName
+ + " has SHA256 certs from APK: " + Arrays.toString(apkCerts)
+ + " and from OEM: " + Arrays.toString(sameOemCerts)
+ );
+
+ return false;
+ }
+
+ @NonNull
+ private AndroidFuture<String> getDeviceProfilePermissionDescription(
+ @Nullable String deviceProfile) {
+ if (deviceProfile == null) {
+ return AndroidFuture.completedFuture(null);
+ }
+
+ final AndroidFuture<String> result = new AndroidFuture<>();
+ mService.mPermissionControllerManager.getPrivilegesDescriptionStringForProfile(
+ deviceProfile, FgThread.getExecutor(), desc -> {
+ try {
+ result.complete(String.valueOf(desc));
+ } catch (Exception e) {
+ result.completeExceptionally(e);
+ }
+ });
+ return result;
+ }
+
+
+ void dump(@NonNull PrintWriter pw) {
+ pw.append("Discovery Service State:").append('\n');
+ for (int i = 0, size = mServiceConnectors.size(); i < size; i++) {
+ int userId = mServiceConnectors.keyAt(i);
+ pw.append(" ")
+ .append("u").append(Integer.toString(userId)).append(": ")
+ .append(Objects.toString(mServiceConnectors.valueAt(i)))
+ .append('\n');
+ }
+ }
+
+ private final IBinder.DeathRecipient mBinderDeathRecipient = new IBinder.DeathRecipient() {
+ @Override
+ public void binderDied() {
+ if (DEBUG) {
+ Slog.d(TAG, "binderDied()");
+ }
+ mService.mMainHandler.post(AssociationRequestsProcessor.this::cleanup);
+ }
+ };
+
+ private static Set<String> getSameOemPackageCerts(
+ String packageName, String[] oemPackages, String[] sameOemCerts) {
+ Set<String> sameOemPackageCerts = new HashSet<>();
+
+ // Assume OEM may enter same package name in the parallel string array with
+ // multiple APK certs corresponding to it
+ for (int i = 0; i < oemPackages.length; i++) {
+ if (oemPackages[i].equals(packageName)) {
+ sameOemPackageCerts.add(sameOemCerts[i].replaceAll(":", ""));
+ }
+ }
+
+ return sameOemPackageCerts;
+ }
+}
diff --git a/services/companion/java/com/android/server/companion/CompanionDeviceManagerService.java b/services/companion/java/com/android/server/companion/CompanionDeviceManagerService.java
index a48172b..cdce3e6 100644
--- a/services/companion/java/com/android/server/companion/CompanionDeviceManagerService.java
+++ b/services/companion/java/com/android/server/companion/CompanionDeviceManagerService.java
@@ -19,8 +19,6 @@
import static android.bluetooth.le.ScanSettings.CALLBACK_TYPE_ALL_MATCHES;
import static android.bluetooth.le.ScanSettings.SCAN_MODE_BALANCED;
-import static android.companion.AssociationRequest.DEVICE_PROFILE_APP_STREAMING;
-import static android.companion.AssociationRequest.DEVICE_PROFILE_WATCH;
import static android.companion.DeviceId.TYPE_MAC_ADDRESS;
import static android.content.pm.PackageManager.CERT_INPUT_SHA256;
import static android.content.pm.PackageManager.PERMISSION_GRANTED;
@@ -31,7 +29,6 @@
import static com.android.internal.util.CollectionUtils.find;
import static com.android.internal.util.CollectionUtils.forEach;
import static com.android.internal.util.CollectionUtils.map;
-import static com.android.internal.util.FunctionalUtils.uncheckExceptions;
import static com.android.internal.util.Preconditions.checkArgument;
import static com.android.internal.util.Preconditions.checkNotNull;
import static com.android.internal.util.Preconditions.checkState;
@@ -39,13 +36,10 @@
import static com.android.internal.util.function.pooled.PooledLambda.obtainRunnable;
import static java.util.Collections.emptySet;
-import static java.util.Collections.unmodifiableMap;
import static java.util.Collections.unmodifiableSet;
import static java.util.Objects.requireNonNull;
import static java.util.concurrent.TimeUnit.MINUTES;
-import android.Manifest;
-import android.annotation.CheckResult;
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.annotation.SuppressLint;
@@ -62,12 +56,10 @@
import android.bluetooth.le.ScanFilter;
import android.bluetooth.le.ScanResult;
import android.bluetooth.le.ScanSettings;
-import android.companion.Association;
+import android.companion.AssociationInfo;
import android.companion.AssociationRequest;
-import android.companion.CompanionDeviceManager;
import android.companion.DeviceId;
import android.companion.DeviceNotAssociatedException;
-import android.companion.ICompanionDeviceDiscoveryService;
import android.companion.ICompanionDeviceManager;
import android.companion.IFindDeviceCallback;
import android.content.BroadcastReceiver;
@@ -81,14 +73,11 @@
import android.content.pm.PackageItemInfo;
import android.content.pm.PackageManager;
import android.content.pm.PackageManagerInternal;
-import android.content.pm.Signature;
import android.content.pm.UserInfo;
import android.net.NetworkPolicyManager;
import android.os.Binder;
import android.os.Environment;
import android.os.Handler;
-import android.os.IBinder;
-import android.os.IInterface;
import android.os.Parcel;
import android.os.PowerWhitelistManager;
import android.os.Process;
@@ -103,7 +92,6 @@
import android.util.ArrayMap;
import android.util.ArraySet;
import android.util.ExceptionUtils;
-import android.util.PackageUtils;
import android.util.Slog;
import android.util.SparseArray;
import android.util.SparseBooleanArray;
@@ -111,9 +99,6 @@
import com.android.internal.annotations.GuardedBy;
import com.android.internal.app.IAppOpsService;
import com.android.internal.content.PackageMonitor;
-import com.android.internal.infra.AndroidFuture;
-import com.android.internal.infra.PerUser;
-import com.android.internal.infra.ServiceConnector;
import com.android.internal.notification.NotificationAccessConfirmationActivityContract;
import com.android.internal.os.BackgroundThread;
import com.android.internal.util.ArrayUtils;
@@ -146,27 +131,13 @@
/** @hide */
@SuppressLint("LongLogTag")
-public class CompanionDeviceManagerService extends SystemService implements Binder.DeathRecipient {
+public class CompanionDeviceManagerService extends SystemService {
static final String LOG_TAG = "CompanionDeviceManagerService";
static final boolean DEBUG = false;
- private static final Map<String, String> DEVICE_PROFILE_TO_PERMISSION;
- static {
- final Map<String, String> map = new ArrayMap<>();
- map.put(DEVICE_PROFILE_WATCH, Manifest.permission.REQUEST_COMPANION_PROFILE_WATCH);
- map.put(DEVICE_PROFILE_APP_STREAMING,
- Manifest.permission.REQUEST_COMPANION_PROFILE_APP_STREAMING);
-
- DEVICE_PROFILE_TO_PERMISSION = unmodifiableMap(map);
- }
-
/** Range of Association IDs allocated for a user.*/
static final int ASSOCIATIONS_IDS_PER_USER_RANGE = 100000;
- private static final ComponentName SERVICE_TO_BIND_TO = ComponentName.createRelative(
- CompanionDeviceManager.COMPANION_DEVICE_DISCOVERY_PACKAGE_NAME,
- ".CompanionDeviceDiscoveryService");
-
private static final long DEVICE_DISAPPEARED_TIMEOUT_MS = 10 * 1000;
private static final long DEVICE_DISAPPEARED_UNBIND_TIMEOUT_MS = 10 * 60 * 1000;
@@ -177,9 +148,6 @@
private static final String PREF_FILE_NAME = "companion_device_preferences.xml";
private static final String PREF_KEY_AUTO_REVOKE_GRANTS_DONE = "auto_revoke_grants_done";
- private static final int ASSOCIATE_WITHOUT_PROMPT_MAX_PER_TIME_WINDOW = 5;
- private static final long ASSOCIATE_WITHOUT_PROMPT_WINDOW_MS = 60 * 60 * 1000; // 60 min;
-
private static DateFormat sDateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
static {
sDateFormat.setTimeZone(TimeZone.getDefault());
@@ -188,19 +156,15 @@
private final CompanionDeviceManagerImpl mImpl;
// Persistent data store for all Associations.
private final PersistentDataStore mPersistentDataStore;
+ private final AssociationRequestsProcessor mAssociationRequestsProcessor;
private PowerWhitelistManager mPowerWhitelistManager;
- private PerUser<ServiceConnector<ICompanionDeviceDiscoveryService>> mServiceConnectors;
private IAppOpsService mAppOpsManager;
private RoleManager mRoleManager;
private BluetoothAdapter mBluetoothAdapter;
private UserManager mUserManager;
- private IFindDeviceCallback mFindDeviceCallback;
private ScanCallback mBleScanCallback = new BleScanCallback();
- private AssociationRequest mRequest;
- private String mCallingPackage;
- private AndroidFuture<?> mOngoingDeviceDiscovery;
- private PermissionControllerManager mPermissionControllerManager;
+ PermissionControllerManager mPermissionControllerManager;
private BluetoothDeviceConnectedListener mBluetoothDeviceConnectedListener =
new BluetoothDeviceConnectedListener();
@@ -212,13 +176,13 @@
private ArrayMap<String, TriggerDeviceDisappearedRunnable> mTriggerDeviceDisappearedRunnables =
new ArrayMap<>();
- private final Object mLock = new Object();
- private final Handler mMainHandler = Handler.getMain();
+ final Object mLock = new Object();
+ final Handler mMainHandler = Handler.getMain();
private CompanionDevicePresenceController mCompanionDevicePresenceController;
/** Maps a {@link UserIdInt} to a set of associations for the user. */
@GuardedBy("mLock")
- private final SparseArray<Set<Association>> mCachedAssociations = new SparseArray<>();
+ private final SparseArray<Set<AssociationInfo>> mCachedAssociations = new SparseArray<>();
/**
* A structure that consist of two nested maps, and effectively maps (userId + packageName) to
* a list of IDs that have been previously assigned to associations for that package.
@@ -236,6 +200,7 @@
super(context);
mImpl = new CompanionDeviceManagerImpl();
mPersistentDataStore = new PersistentDataStore();
+ mAssociationRequestsProcessor = new AssociationRequestsProcessor(this);
mPowerWhitelistManager = context.getSystemService(PowerWhitelistManager.class);
mRoleManager = context.getSystemService(RoleManager.class);
@@ -249,17 +214,6 @@
mUserManager = context.getSystemService(UserManager.class);
mCompanionDevicePresenceController = new CompanionDevicePresenceController();
- Intent serviceIntent = new Intent().setComponent(SERVICE_TO_BIND_TO);
- mServiceConnectors = new PerUser<ServiceConnector<ICompanionDeviceDiscoveryService>>() {
- @Override
- protected ServiceConnector<ICompanionDeviceDiscoveryService> create(int userId) {
- return new ServiceConnector.Impl<>(
- getContext(),
- serviceIntent, 0/* bindingFlags */, userId,
- ICompanionDeviceDiscoveryService.Stub::asInterface);
- }
- };
-
registerPackageMonitor();
}
@@ -316,7 +270,7 @@
@Override
public void onUserUnlocking(@NonNull TargetUser user) {
int userHandle = user.getUserIdentifier();
- Set<Association> associations = getAllAssociations(userHandle);
+ Set<AssociationInfo> associations = getAllAssociations(userHandle);
if (associations == null || associations.isEmpty()) {
return;
}
@@ -339,11 +293,11 @@
}
try {
- Set<Association> associations = getAllAssociations(userId);
+ Set<AssociationInfo> associations = getAllAssociations(userId);
if (associations == null) {
continue;
}
- for (Association a : associations) {
+ for (AssociationInfo a : associations) {
try {
int uid = pm.getPackageUidAsUser(a.getPackageName(), userId);
exemptFromAutoRevoke(a.getPackageName(), uid);
@@ -357,39 +311,6 @@
}
}
- @Override
- public void binderDied() {
- Slog.w(LOG_TAG, "binderDied()");
- mMainHandler.post(this::cleanup);
- }
-
- private void cleanup() {
- Slog.d(LOG_TAG, "cleanup(); discovery = "
- + mOngoingDeviceDiscovery + ", request = " + mRequest);
- synchronized (mLock) {
- AndroidFuture<?> ongoingDeviceDiscovery = mOngoingDeviceDiscovery;
- if (ongoingDeviceDiscovery != null && !ongoingDeviceDiscovery.isDone()) {
- ongoingDeviceDiscovery.cancel(true);
- }
- mFindDeviceCallback = unlinkToDeath(mFindDeviceCallback, this, 0);
- mRequest = null;
- mCallingPackage = null;
- }
- }
-
- /**
- * Usage: {@code a = unlinkToDeath(a, deathRecipient, flags); }
- */
- @Nullable
- @CheckResult
- private static <T extends IInterface> T unlinkToDeath(T iinterface,
- IBinder.DeathRecipient deathRecipient, int flags) {
- if (iinterface != null) {
- iinterface.asBinder().unlinkToDeath(deathRecipient, flags);
- }
- return null;
- }
-
class CompanionDeviceManagerImpl extends ICompanionDeviceManager.Stub {
@Override
@@ -410,61 +331,15 @@
String callingPackage) throws RemoteException {
Slog.i(LOG_TAG, "associate(request = " + request + ", callback = " + callback
+ ", callingPackage = " + callingPackage + ")");
- checkNotNull(request, "Request cannot be null");
- checkNotNull(callback, "Callback cannot be null");
- checkCallerIsSystemOr(callingPackage);
- int userId = getCallingUserId();
- checkUsesFeature(callingPackage, userId);
- final String deviceProfile = request.getDeviceProfile();
- validateDeviceProfileAndCheckPermission(deviceProfile);
-
- mFindDeviceCallback = callback;
- mRequest = request;
- mCallingPackage = callingPackage;
- request.setCallingPackage(callingPackage);
-
- if (mayAssociateWithoutPrompt(callingPackage, userId)) {
- Slog.i(LOG_TAG, "setSkipPrompt(true)");
- request.setSkipPrompt(true);
- }
- callback.asBinder().linkToDeath(CompanionDeviceManagerService.this /* recipient */, 0);
-
- mOngoingDeviceDiscovery = getDeviceProfilePermissionDescription(deviceProfile)
- .thenComposeAsync(description -> {
- Slog.d(LOG_TAG, "fetchProfileDescription done: " + description);
-
- request.setDeviceProfilePrivilegesDescription(description);
-
- return mServiceConnectors.forUser(userId).postAsync(service -> {
- Slog.d(LOG_TAG, "Connected to CDM service; starting discovery for " + request);
-
- AndroidFuture<String> future = new AndroidFuture<>();
- service.startDiscovery(request, callingPackage, callback, future);
- return future;
- }).cancelTimeout();
-
- }, FgThread.getExecutor()).whenComplete(uncheckExceptions((deviceAddress, err) -> {
- if (err == null) {
- createAssociationInternal(
- userId, deviceAddress, callingPackage, deviceProfile);
- } else {
- Slog.e(LOG_TAG, "Failed to discover device(s)", err);
- callback.onFailure("No devices found: " + err.getMessage());
- }
- cleanup();
- }));
+ mAssociationRequestsProcessor.process(request, callback, callingPackage);
}
@Override
public void stopScan(AssociationRequest request,
IFindDeviceCallback callback,
String callingPackage) {
- Slog.d(LOG_TAG, "stopScan(request = " + request + ")");
- if (Objects.equals(request, mRequest)
- && Objects.equals(callback, mFindDeviceCallback)
- && Objects.equals(callingPackage, mCallingPackage)) {
- cleanup();
- }
+ Slog.i(LOG_TAG, "stopScan(request = " + request + ")");
+ mAssociationRequestsProcessor.stopScan(request, callback, callingPackage);
}
@Override
@@ -480,7 +355,7 @@
}
@Override
- public List<Association> getAssociationsForUser(int userId) {
+ public List<AssociationInfo> getAssociationsForUser(int userId) {
if (!callerCanManageCompanionDevices()) {
throw new SecurityException("Caller must hold "
+ android.Manifest.permission.MANAGE_COMPANION_DEVICES);
@@ -505,44 +380,6 @@
== PERMISSION_GRANTED;
}
- private void checkCallerIsSystemOr(String pkg) throws RemoteException {
- checkCallerIsSystemOr(pkg, getCallingUserId());
- }
-
- private void checkCallerIsSystemOr(String pkg, int userId) throws RemoteException {
- if (isCallerSystem()) {
- return;
- }
-
- checkArgument(getCallingUserId() == userId,
- "Must be called by either same user or system");
- int callingUid = Binder.getCallingUid();
- if (mAppOpsManager.checkPackage(callingUid, pkg) != AppOpsManager.MODE_ALLOWED) {
- throw new SecurityException(pkg + " doesn't belong to uid " + callingUid);
- }
- }
-
- private void validateDeviceProfileAndCheckPermission(@Nullable String deviceProfile) {
- // Device profile can be null.
- if (deviceProfile == null) return;
-
- if (DEVICE_PROFILE_APP_STREAMING.equals(deviceProfile)) {
- // TODO: remove, when properly supporting this profile.
- throw new UnsupportedOperationException(
- "DEVICE_PROFILE_APP_STREAMING is not fully supported yet.");
- }
-
- if (!DEVICE_PROFILE_TO_PERMISSION.containsKey(deviceProfile)) {
- throw new IllegalArgumentException("Unsupported device profile: " + deviceProfile);
- }
-
- final String permission = DEVICE_PROFILE_TO_PERMISSION.get(deviceProfile);
- if (getContext().checkCallingOrSelfPermission(permission) != PERMISSION_GRANTED) {
- throw new SecurityException("Application must hold " + permission + " to associate "
- + "with a device with " + deviceProfile + " profile.");
- }
- }
-
@Override
public PendingIntent requestNotificationAccess(ComponentName component)
throws RemoteException {
@@ -630,7 +467,7 @@
checkCallerIsSystemOr(packageName);
int userId = getCallingUserId();
- Set<Association> deviceAssociations = filter(
+ Set<AssociationInfo> deviceAssociations = filter(
getAllAssociations(userId, packageName),
association -> deviceAddress.equals(association.getDeviceMacAddress()));
@@ -674,23 +511,6 @@
checkUsesFeature(callingPackage, userId);
}
- private void checkUsesFeature(String pkg, int userId) {
- if (isCallerSystem()) {
- // Drop the requirement for calls from system process
- return;
- }
-
- FeatureInfo[] reqFeatures = getPackageInfo(pkg, userId).reqFeatures;
- String requiredFeature = PackageManager.FEATURE_COMPANION_DEVICE_SETUP;
- int numFeatures = ArrayUtils.size(reqFeatures);
- for (int i = 0; i < numFeatures; i++) {
- if (requiredFeature.equals(reqFeatures[i].name)) return;
- }
- throw new IllegalStateException("Must declare uses-feature "
- + requiredFeature
- + " in manifest to use this API");
- }
-
@Override
public boolean canPairWithoutPrompt(
String packageName, String deviceMacAddress, int userId) {
@@ -740,14 +560,7 @@
.append(sDateFormat.format(time)).append('\n');
}
- fout.append("Discovery Service State:").append('\n');
- for (int i = 0, size = mServiceConnectors.size(); i < size; i++) {
- int userId = mServiceConnectors.keyAt(i);
- fout.append(" ")
- .append("u").append(Integer.toString(userId)).append(": ")
- .append(Objects.toString(mServiceConnectors.valueAt(i)))
- .append('\n');
- }
+ mAssociationRequestsProcessor.dump(fout);
fout.append("Device Listener Services State:").append('\n');
for (int i = 0, size = mCompanionDevicePresenceController.mBoundServices.size();
@@ -762,7 +575,24 @@
}
}
- private static int getCallingUserId() {
+ void checkCallerIsSystemOr(String pkg) throws RemoteException {
+ checkCallerIsSystemOr(pkg, getCallingUserId());
+ }
+
+ private void checkCallerIsSystemOr(String pkg, int userId) throws RemoteException {
+ if (isCallerSystem()) {
+ return;
+ }
+
+ checkArgument(getCallingUserId() == userId,
+ "Must be called by either same user or system");
+ int callingUid = Binder.getCallingUid();
+ if (mAppOpsManager.checkPackage(callingUid, pkg) != AppOpsManager.MODE_ALLOWED) {
+ throw new SecurityException(pkg + " doesn't belong to uid " + callingUid);
+ }
+ }
+
+ static int getCallingUserId() {
return UserHandle.getUserId(Binder.getCallingUid());
}
@@ -770,9 +600,26 @@
return Binder.getCallingUid() == Process.SYSTEM_UID;
}
+ void checkUsesFeature(String pkg, int userId) {
+ if (isCallerSystem()) {
+ // Drop the requirement for calls from system process
+ return;
+ }
+
+ FeatureInfo[] reqFeatures = getPackageInfo(pkg, userId).reqFeatures;
+ String requiredFeature = PackageManager.FEATURE_COMPANION_DEVICE_SETUP;
+ int numFeatures = ArrayUtils.size(reqFeatures);
+ for (int i = 0; i < numFeatures; i++) {
+ if (requiredFeature.equals(reqFeatures[i].name)) return;
+ }
+ throw new IllegalStateException("Must declare uses-feature "
+ + requiredFeature
+ + " in manifest to use this API");
+ }
+
void createAssociationInternal(
int userId, String deviceMacAddress, String packageName, String deviceProfile) {
- final Association association = new Association(
+ final AssociationInfo association = new AssociationInfo(
getNewAssociationIdForPackage(userId, packageName),
userId,
packageName,
@@ -801,7 +648,7 @@
// First: collect all IDs currently in use for this user's Associations.
final SparseBooleanArray usedIds = new SparseBooleanArray();
- for (Association it : getAllAssociations(userId)) {
+ for (AssociationInfo it : getAllAssociations(userId)) {
usedIds.put(it.getAssociationId(), true);
}
@@ -851,7 +698,7 @@
}
}
- void onAssociationPreRemove(Association association) {
+ void onAssociationPreRemove(AssociationInfo association) {
if (association.isNotifyOnDeviceNearby()) {
mCompanionDevicePresenceController.unbindDevicePresenceListener(
association.getPackageName(), association.getUserId());
@@ -859,7 +706,7 @@
String deviceProfile = association.getDeviceProfile();
if (deviceProfile != null) {
- Association otherAssociationWithDeviceProfile = find(
+ AssociationInfo otherAssociationWithDeviceProfile = find(
getAllAssociations(association.getUserId()),
a -> !a.equals(association) && deviceProfile.equals(a.getDeviceProfile()));
if (otherAssociationWithDeviceProfile != null) {
@@ -890,7 +737,7 @@
}
}
- private void updateSpecialAccessPermissionForAssociatedPackage(Association association) {
+ private void updateSpecialAccessPermissionForAssociatedPackage(AssociationInfo association) {
PackageInfo packageInfo = getPackageInfo(
association.getPackageName(),
association.getUserId());
@@ -904,7 +751,7 @@
}
private void updateSpecialAccessPermissionAsSystem(
- Association association, PackageInfo packageInfo) {
+ AssociationInfo association, PackageInfo packageInfo) {
if (containsEither(packageInfo.requestedPermissions,
android.Manifest.permission.RUN_IN_BACKGROUND,
android.Manifest.permission.REQUEST_COMPANION_RUN_IN_BACKGROUND)) {
@@ -950,72 +797,6 @@
}
}
- private Set<String> getSameOemPackageCerts(
- String packageName, String[] oemPackages, String[] sameOemCerts) {
- Set<String> sameOemPackageCerts = new HashSet<>();
-
- // Assume OEM may enter same package name in the parallel string array with
- // multiple APK certs corresponding to it
- for (int i = 0; i < oemPackages.length; i++) {
- if (oemPackages[i].equals(packageName)) {
- sameOemPackageCerts.add(sameOemCerts[i].replaceAll(":", ""));
- }
- }
-
- return sameOemPackageCerts;
- }
-
- boolean mayAssociateWithoutPrompt(String packageName, int userId) {
- String[] sameOemPackages = getContext()
- .getResources()
- .getStringArray(com.android.internal.R.array.config_companionDevicePackages);
- if (!ArrayUtils.contains(sameOemPackages, packageName)) {
- Slog.w(LOG_TAG, packageName
- + " can not silently create associations due to no package found."
- + " Packages from OEM: " + Arrays.toString(sameOemPackages)
- );
- return false;
- }
-
- // Throttle frequent associations
- long now = System.currentTimeMillis();
- Set<Association> recentAssociations = filter(
- getAllAssociations(userId, packageName),
- a -> now - a.getTimeApprovedMs() < ASSOCIATE_WITHOUT_PROMPT_WINDOW_MS);
-
- if (recentAssociations.size() >= ASSOCIATE_WITHOUT_PROMPT_MAX_PER_TIME_WINDOW) {
- Slog.w(LOG_TAG, "Too many associations. " + packageName
- + " already associated " + recentAssociations.size()
- + " devices within the last " + ASSOCIATE_WITHOUT_PROMPT_WINDOW_MS
- + "ms: " + recentAssociations);
- return false;
- }
- String[] sameOemCerts = getContext()
- .getResources()
- .getStringArray(com.android.internal.R.array.config_companionDeviceCerts);
-
- Signature[] signatures = mPackageManagerInternal
- .getPackage(packageName).getSigningDetails().getSignatures();
- String[] apkCerts = PackageUtils.computeSignaturesSha256Digests(signatures);
-
- Set<String> sameOemPackageCerts =
- getSameOemPackageCerts(packageName, sameOemPackages, sameOemCerts);
-
- for (String cert : apkCerts) {
- if (sameOemPackageCerts.contains(cert)) {
- return true;
- }
- }
-
- Slog.w(LOG_TAG, packageName
- + " can not silently create associations. " + packageName
- + " has SHA256 certs from APK: " + Arrays.toString(apkCerts)
- + " and from OEM: " + Arrays.toString(sameOemCerts)
- );
-
- return false;
- }
-
private static <T> boolean containsEither(T[] array, T a, T b) {
return ArrayUtils.contains(array, a) || ArrayUtils.contains(array, b);
}
@@ -1035,20 +816,20 @@
}, getContext(), packageName, userId).recycleOnUse());
}
- private void recordAssociation(Association association, int userId) {
+ private void recordAssociation(AssociationInfo association, int userId) {
Slog.i(LOG_TAG, "recordAssociation(" + association + ")");
updateAssociations(associations -> add(associations, association), userId);
}
- private void updateAssociations(Function<Set<Association>, Set<Association>> update,
+ private void updateAssociations(Function<Set<AssociationInfo>, Set<AssociationInfo>> update,
int userId) {
synchronized (mLock) {
if (DEBUG) Slog.d(LOG_TAG, "Updating Associations set...");
- final Set<Association> prevAssociations = getAllAssociations(userId);
+ final Set<AssociationInfo> prevAssociations = getAllAssociations(userId);
if (DEBUG) Slog.d(LOG_TAG, " > Before : " + prevAssociations + "...");
- final Set<Association> updatedAssociations = update.apply(
+ final Set<AssociationInfo> updatedAssociations = update.apply(
new ArraySet<>(prevAssociations));
if (DEBUG) Slog.d(LOG_TAG, " > After: " + updatedAssociations);
@@ -1065,9 +846,9 @@
}
}
- private void updateAtm(int userId, Set<Association> associations) {
+ private void updateAtm(int userId, Set<AssociationInfo> associations) {
final Set<Integer> companionAppUids = new ArraySet<>();
- for (Association association : associations) {
+ for (AssociationInfo association : associations) {
final int uid = mPackageManagerInternal.getPackageUid(association.getPackageName(),
0, userId);
if (uid >= 0) {
@@ -1083,7 +864,7 @@
}
}
- @NonNull Set<Association> getAllAssociations(int userId) {
+ @NonNull Set<AssociationInfo> getAllAssociations(int userId) {
synchronized (mLock) {
readPersistedStateForUserIfNeededLocked(userId);
// This returns non-null, because the readAssociationsInfoForUserIfNeededLocked() method
@@ -1098,7 +879,7 @@
Slog.i(LOG_TAG, "Reading state for user " + userId + " from the disk");
- final Set<Association> associations = new ArraySet<>();
+ final Set<AssociationInfo> associations = new ArraySet<>();
final Map<String, Set<Integer>> previouslyUsedIds = new ArrayMap<>();
mPersistentDataStore.readStateForUser(userId, associations, previouslyUsedIds);
@@ -1120,17 +901,17 @@
}
}
- private Set<Association> getAllAssociations(int userId, @Nullable String packageFilter) {
+ Set<AssociationInfo> getAllAssociations(int userId, @Nullable String packageFilter) {
return filter(
getAllAssociations(userId),
// Null filter == get all associations
a -> packageFilter == null || Objects.equals(packageFilter, a.getPackageName()));
}
- private Set<Association> getAllAssociations() {
+ private Set<AssociationInfo> getAllAssociations() {
final long identity = Binder.clearCallingIdentity();
try {
- ArraySet<Association> result = new ArraySet<>();
+ ArraySet<AssociationInfo> result = new ArraySet<>();
for (UserInfo user : mUserManager.getAliveUsers()) {
result.addAll(getAllAssociations(user.id));
}
@@ -1140,7 +921,7 @@
}
}
- private Set<Association> getAllAssociations(
+ private Set<AssociationInfo> getAllAssociations(
int userId, @Nullable String packageFilter, @Nullable String addressFilter) {
return filter(
getAllAssociations(userId),
@@ -1156,7 +937,7 @@
mCurrentlyConnectedDevices.add(address);
for (UserInfo user : getAllUsers()) {
- for (Association association : getAllAssociations(user.id)) {
+ for (AssociationInfo association : getAllAssociations(user.id)) {
if (Objects.equals(address, association.getDeviceMacAddress())) {
if (association.getDeviceProfile() != null) {
Slog.i(LOG_TAG, "Granting role " + association.getDeviceProfile()
@@ -1171,7 +952,7 @@
onDeviceNearby(address);
}
- private void grantDeviceProfile(Association association) {
+ private void grantDeviceProfile(AssociationInfo association) {
Slog.i(LOG_TAG, "grantDeviceProfile(association = " + association + ")");
if (association.getDeviceProfile() != null) {
@@ -1278,7 +1059,7 @@
Date lastNearby = mDevicesLastNearby.valueAt(i);
if (isDeviceDisappeared(lastNearby)) {
- for (Association association : getAllAssociations(address)) {
+ for (AssociationInfo association : getAllAssociations(address)) {
if (association.isNotifyOnDeviceNearby()) {
mCompanionDevicePresenceController.unbindDevicePresenceListener(
association.getPackageName(), association.getUserId());
@@ -1320,12 +1101,12 @@
}
}
- private Set<Association> getAllAssociations(String deviceAddress) {
+ private Set<AssociationInfo> getAllAssociations(String deviceAddress) {
List<UserInfo> aliveUsers = mUserManager.getAliveUsers();
- Set<Association> result = new ArraySet<>();
+ Set<AssociationInfo> result = new ArraySet<>();
for (int i = 0, size = aliveUsers.size(); i < size; i++) {
UserInfo user = aliveUsers.get(i);
- for (Association association : getAllAssociations(user.id)) {
+ for (AssociationInfo association : getAllAssociations(user.id)) {
if (Objects.equals(association.getDeviceMacAddress(), deviceAddress)) {
result.add(association);
}
@@ -1349,7 +1130,7 @@
|| timestamp.getTime() - oldTimestamp.getTime() >= DEVICE_DISAPPEARED_TIMEOUT_MS;
if (justAppeared) {
Slog.i(LOG_TAG, "onDeviceNearby(justAppeared, address = " + address + ")");
- for (Association association : getAllAssociations(address)) {
+ for (AssociationInfo association : getAllAssociations(address)) {
if (association.isNotifyOnDeviceNearby()) {
mCompanionDevicePresenceController.onDeviceNotifyAppeared(association,
getContext(), mMainHandler);
@@ -1362,7 +1143,7 @@
Slog.i(LOG_TAG, "onDeviceDisappeared(address = " + address + ")");
boolean hasDeviceListeners = false;
- for (Association association : getAllAssociations(address)) {
+ for (AssociationInfo association : getAllAssociations(address)) {
if (association.isNotifyOnDeviceNearby()) {
mCompanionDevicePresenceController.onDeviceNotifyDisappeared(
association, getContext(), mMainHandler);
@@ -1431,7 +1212,7 @@
private List<ScanFilter> getBleScanFilters() {
ArrayList<ScanFilter> result = new ArrayList<>();
ArraySet<String> addressesSeen = new ArraySet<>();
- for (Association association : getAllAssociations()) {
+ for (AssociationInfo association : getAllAssociations()) {
String address = association.getDeviceMacAddress();
if (addressesSeen.contains(address)) {
continue;
@@ -1444,25 +1225,6 @@
return result;
}
- @NonNull
- private AndroidFuture<String> getDeviceProfilePermissionDescription(
- @Nullable String deviceProfile) {
- if (deviceProfile == null) {
- return AndroidFuture.completedFuture(null);
- }
-
- final AndroidFuture<String> result = new AndroidFuture<>();
- mPermissionControllerManager.getPrivilegesDescriptionStringForProfile(
- deviceProfile, FgThread.getExecutor(), desc -> {
- try {
- result.complete(String.valueOf(desc));
- } catch (Exception e) {
- result.completeExceptionally(e);
- }
- });
- return result;
- }
-
static int getFirstAssociationIdForUser(@UserIdInt int userId) {
// We want the IDs to start from 1, not 0.
return userId * ASSOCIATIONS_IDS_PER_USER_RANGE + 1;
diff --git a/services/companion/java/com/android/server/companion/CompanionDevicePresenceController.java b/services/companion/java/com/android/server/companion/CompanionDevicePresenceController.java
index 328a8b3..a79db2c 100644
--- a/services/companion/java/com/android/server/companion/CompanionDevicePresenceController.java
+++ b/services/companion/java/com/android/server/companion/CompanionDevicePresenceController.java
@@ -22,7 +22,7 @@
import static com.android.internal.util.CollectionUtils.filter;
import android.annotation.NonNull;
-import android.companion.Association;
+import android.companion.AssociationInfo;
import android.companion.CompanionDeviceService;
import android.companion.ICompanionDeviceService;
import android.content.ComponentName;
@@ -60,7 +60,7 @@
};
}
- void onDeviceNotifyAppeared(Association association, Context context, Handler handler) {
+ void onDeviceNotifyAppeared(AssociationInfo association, Context context, Handler handler) {
ServiceConnector<ICompanionDeviceService> primaryConnector =
getPrimaryServiceConnector(association, context, handler);
if (primaryConnector != null) {
@@ -71,7 +71,7 @@
}
}
- void onDeviceNotifyDisappeared(Association association, Context context, Handler handler) {
+ void onDeviceNotifyDisappeared(AssociationInfo association, Context context, Handler handler) {
ServiceConnector<ICompanionDeviceService> primaryConnector =
getPrimaryServiceConnector(association, context, handler);
if (primaryConnector != null) {
@@ -94,7 +94,7 @@
}
private ServiceConnector<ICompanionDeviceService> getPrimaryServiceConnector(
- Association association, Context context, Handler handler) {
+ AssociationInfo association, Context context, Handler handler) {
for (BoundService boundService: getDeviceListenerServiceConnector(association, context,
handler)) {
if (boundService.mIsPrimary) {
@@ -104,15 +104,15 @@
return null;
}
- private List<BoundService> getDeviceListenerServiceConnector(Association a, Context context,
+ private List<BoundService> getDeviceListenerServiceConnector(AssociationInfo a, Context context,
Handler handler) {
return mBoundServices.forUser(a.getUserId()).computeIfAbsent(
a.getPackageName(),
pkg -> createDeviceListenerServiceConnector(a, context, handler));
}
- private List<BoundService> createDeviceListenerServiceConnector(Association a, Context context,
- Handler handler) {
+ private List<BoundService> createDeviceListenerServiceConnector(AssociationInfo a,
+ Context context, Handler handler) {
List<ResolveInfo> resolveInfos = context
.getPackageManager()
.queryIntentServicesAsUser(new Intent(CompanionDeviceService.SERVICE_INTERFACE),
@@ -161,7 +161,7 @@
}
private boolean validatePackageInfo(List<ResolveInfo> packageResolveInfos,
- Association association) {
+ AssociationInfo association) {
if (packageResolveInfos.size() == 0 || packageResolveInfos.size() > 5) {
Slog.e(LOG_TAG, "Device presence listener package must have at least one and not "
+ "more than five CompanionDeviceService(s) declared. But "
diff --git a/services/companion/java/com/android/server/companion/PersistentDataStore.java b/services/companion/java/com/android/server/companion/PersistentDataStore.java
index 73d45ad..5b8d7e5 100644
--- a/services/companion/java/com/android/server/companion/PersistentDataStore.java
+++ b/services/companion/java/com/android/server/companion/PersistentDataStore.java
@@ -34,7 +34,7 @@
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.annotation.UserIdInt;
-import android.companion.Association;
+import android.companion.AssociationInfo;
import android.companion.DeviceId;
import android.os.Environment;
import android.util.AtomicFile;
@@ -179,11 +179,11 @@
* Reads previously persisted data for the given user "into" the provided containers.
*
* @param userId Android UserID
- * @param associationsOut a container to read the {@link Association}s "into".
+ * @param associationsOut a container to read the {@link AssociationInfo}s "into".
* @param previouslyUsedIdsPerPackageOut a container to read the used IDs "into".
*/
void readStateForUser(@UserIdInt int userId,
- @NonNull Set<Association> associationsOut,
+ @NonNull Set<AssociationInfo> associationsOut,
@NonNull Map<String, Set<Integer>> previouslyUsedIdsPerPackageOut) {
Slog.i(LOG_TAG, "Reading associations for user " + userId + " from disk");
final AtomicFile file = getStorageFileForUser(userId);
@@ -244,7 +244,7 @@
* @param associations a set of user's associations.
* @param previouslyUsedIdsPerPackage a set previously used Association IDs for the user.
*/
- void persistStateForUser(@UserIdInt int userId, @NonNull Set<Association> associations,
+ void persistStateForUser(@UserIdInt int userId, @NonNull Set<AssociationInfo> associations,
@NonNull Map<String, Set<Integer>> previouslyUsedIdsPerPackage) {
Slog.i(LOG_TAG, "Writing associations for user " + userId + " to disk");
if (DEBUG) Slog.d(LOG_TAG, " > " + associations);
@@ -257,7 +257,7 @@
}
private int readStateFromFileLocked(@UserIdInt int userId, @NonNull AtomicFile file,
- @NonNull String rootTag, @Nullable Set<Association> associationsOut,
+ @NonNull String rootTag, @Nullable Set<AssociationInfo> associationsOut,
@NonNull Map<String, Set<Integer>> previouslyUsedIdsPerPackageOut) {
try (FileInputStream in = file.openRead()) {
final TypedXmlPullParser parser = Xml.resolvePullParser(in);
@@ -289,7 +289,7 @@
}
private void persistStateToFileLocked(@NonNull AtomicFile file,
- @Nullable Set<Association> associations,
+ @Nullable Set<AssociationInfo> associations,
@NonNull Map<String, Set<Integer>> previouslyUsedIdsPerPackage) {
file.write(out -> {
try {
@@ -328,7 +328,7 @@
}
private static void readAssociationsV0(@NonNull TypedXmlPullParser parser,
- @UserIdInt int userId, @NonNull Set<Association> out)
+ @UserIdInt int userId, @NonNull Set<AssociationInfo> out)
throws XmlPullParserException, IOException {
requireStartOfTag(parser, XML_TAG_ASSOCIATIONS);
@@ -349,7 +349,7 @@
}
private static void readAssociationV0(@NonNull TypedXmlPullParser parser, @UserIdInt int userId,
- int associationId, @NonNull Set<Association> out) throws XmlPullParserException {
+ int associationId, @NonNull Set<AssociationInfo> out) throws XmlPullParserException {
requireStartOfTag(parser, XML_TAG_ASSOCIATION);
final String appPackage = readStringAttribute(parser, XML_ATTR_PACKAGE);
@@ -366,12 +366,12 @@
// "Convert" MAC address into a DeviceId.
final List<DeviceId> deviceIds = Arrays.asList(
new DeviceId(TYPE_MAC_ADDRESS, deviceAddress));
- out.add(new Association(associationId, userId, appPackage, deviceIds, profile,
+ out.add(new AssociationInfo(associationId, userId, appPackage, deviceIds, profile,
/* managedByCompanionApp */false, notify, timeApproved));
}
private static void readAssociationsV1(@NonNull TypedXmlPullParser parser,
- @UserIdInt int userId, @NonNull Set<Association> out)
+ @UserIdInt int userId, @NonNull Set<AssociationInfo> out)
throws XmlPullParserException, IOException {
requireStartOfTag(parser, XML_TAG_ASSOCIATIONS);
@@ -385,7 +385,7 @@
}
private static void readAssociationV1(@NonNull TypedXmlPullParser parser, @UserIdInt int userId,
- @NonNull Set<Association> out) throws XmlPullParserException, IOException {
+ @NonNull Set<AssociationInfo> out) throws XmlPullParserException, IOException {
requireStartOfTag(parser, XML_TAG_ASSOCIATION);
final int associationId = readIntAttribute(parser, XML_ATTR_ID);
@@ -406,8 +406,8 @@
deviceIds.add(new DeviceId(type, value));
}
- out.add(new Association(associationId, userId, appPackage, deviceIds, profile, managedByApp,
- notify, timeApproved));
+ out.add(new AssociationInfo(associationId, userId, appPackage, deviceIds, profile,
+ managedByApp, notify, timeApproved));
}
private static void readPreviouslyUsedIdsV1(@NonNull TypedXmlPullParser parser,
@@ -437,13 +437,13 @@
}
private static void writeAssociations(@NonNull XmlSerializer parent,
- @Nullable Set<Association> associations) throws IOException {
+ @Nullable Set<AssociationInfo> associations) throws IOException {
final XmlSerializer serializer = parent.startTag(null, XML_TAG_ASSOCIATIONS);
forEach(associations, it -> writeAssociation(serializer, it));
serializer.endTag(null, XML_TAG_ASSOCIATIONS);
}
- private static void writeAssociation(@NonNull XmlSerializer parent, @NonNull Association a)
+ private static void writeAssociation(@NonNull XmlSerializer parent, @NonNull AssociationInfo a)
throws IOException {
final XmlSerializer serializer = parent.startTag(null, XML_TAG_ASSOCIATION);
diff --git a/services/companion/java/com/android/server/companion/proto/companion_apps_permissions.proto b/services/companion/java/com/android/server/companion/proto/companion_apps_permissions.proto
new file mode 100644
index 0000000..b786bcc
--- /dev/null
+++ b/services/companion/java/com/android/server/companion/proto/companion_apps_permissions.proto
@@ -0,0 +1,37 @@
+/*
+ * Copyright (C) 2021 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.
+ */
+
+syntax = "proto3";
+
+option java_multiple_files = true;
+
+/* Represents granted permissions of a list of apps */
+message CompanionAppsPermissions {
+ // granted permissions of apps
+ repeated AppPermissions appPermissions = 1;
+
+ /* Represents the granted permissions of an app */
+ message AppPermissions {
+ // package name of the app
+ string packageName = 1;
+
+ // signing certificates used to sign the APK contents of this app
+ bytes certificates = 2;
+
+ // granted permissions
+ repeated string permission = 3;
+ }
+}
diff --git a/services/companion/java/com/android/server/companion/proto/companion_message.proto b/services/companion/java/com/android/server/companion/proto/companion_message.proto
new file mode 100644
index 0000000..2309be3
--- /dev/null
+++ b/services/companion/java/com/android/server/companion/proto/companion_message.proto
@@ -0,0 +1,43 @@
+/*
+ * Copyright (C) 2021 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.
+ */
+
+syntax = "proto3";
+
+option java_multiple_files = true;
+
+/* Represents a message between companion devices */
+message CompanionMessage {
+ // id of the message
+ int32 messageId = 1;
+
+ // type of the message
+ CompanionMessageType type = 2;
+
+ // data contained in the message
+ bytes data = 3;
+
+ // types of CompanionMessage
+ enum CompanionMessageType {
+ // default value for proto3
+ UNKNOWN = 0;
+
+ // handshake message to establish secure channel
+ SECURE_CHANNEL_HANDSHAKE = 1;
+
+ // permission sync
+ PERMISSION_SYNC = 2;
+ }
+}
diff --git a/services/companion/java/com/android/server/companion/virtual/VirtualDeviceManagerService.java b/services/companion/java/com/android/server/companion/virtual/VirtualDeviceManagerService.java
new file mode 100644
index 0000000..18cf6f8
--- /dev/null
+++ b/services/companion/java/com/android/server/companion/virtual/VirtualDeviceManagerService.java
@@ -0,0 +1,111 @@
+/*
+ * Copyright (C) 2021 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.companion.virtual;
+
+import android.annotation.NonNull;
+import android.annotation.Nullable;
+import android.annotation.SuppressLint;
+import android.companion.virtual.IVirtualDevice;
+import android.companion.virtual.IVirtualDeviceManager;
+import android.content.Context;
+import android.os.Parcel;
+import android.os.RemoteException;
+import android.util.ExceptionUtils;
+import android.util.Slog;
+
+import com.android.internal.annotations.GuardedBy;
+import com.android.internal.util.DumpUtils;
+import com.android.server.SystemService;
+
+import java.io.FileDescriptor;
+import java.io.PrintWriter;
+import java.util.ArrayList;
+
+
+/** @hide */
+@SuppressLint("LongLogTag")
+public class VirtualDeviceManagerService extends SystemService {
+
+ private static final boolean DEBUG = false;
+ private static final String LOG_TAG = "VirtualDeviceManagerService";
+ private final VirtualDeviceManagerImpl mImpl;
+ @GuardedBy("mVirtualDevices")
+ private final ArrayList<VirtualDeviceImpl> mVirtualDevices = new ArrayList<>();
+
+ public VirtualDeviceManagerService(Context context) {
+ super(context);
+ mImpl = new VirtualDeviceManagerImpl();
+ }
+
+ @Override
+ public void onStart() {
+ publishBinderService(Context.VIRTUAL_DEVICE_SERVICE, mImpl);
+ }
+
+ private class VirtualDeviceImpl extends IVirtualDevice.Stub {
+
+ private VirtualDeviceImpl() {}
+
+ @Override
+ public void close() {
+ synchronized (mVirtualDevices) {
+ mVirtualDevices.remove(this);
+ }
+ }
+ }
+
+ class VirtualDeviceManagerImpl extends IVirtualDeviceManager.Stub {
+
+ @Override
+ public IVirtualDevice createVirtualDevice() {
+ getContext().enforceCallingOrSelfPermission(
+ android.Manifest.permission.CREATE_VIRTUAL_DEVICE,
+ "createVirtualDevice");
+ VirtualDeviceImpl virtualDevice = new VirtualDeviceImpl();
+ synchronized (mVirtualDevices) {
+ mVirtualDevices.add(virtualDevice);
+ }
+ return virtualDevice;
+ }
+
+ @Override
+ public boolean onTransact(int code, Parcel data, Parcel reply, int flags)
+ throws RemoteException {
+ try {
+ return super.onTransact(code, data, reply, flags);
+ } catch (Throwable e) {
+ Slog.e(LOG_TAG, "Error during IPC", e);
+ throw ExceptionUtils.propagate(e, RemoteException.class);
+ }
+ }
+
+ @Override
+ public void dump(@NonNull FileDescriptor fd,
+ @NonNull PrintWriter fout,
+ @Nullable String[] args) {
+ if (!DumpUtils.checkDumpAndUsageStatsPermission(getContext(), LOG_TAG, fout)) {
+ return;
+ }
+ fout.println("Created virtual devices: ");
+ synchronized (mVirtualDevices) {
+ for (VirtualDeviceImpl virtualDevice : mVirtualDevices) {
+ fout.println(virtualDevice.toString());
+ }
+ }
+ }
+ }
+}
diff --git a/services/core/Android.bp b/services/core/Android.bp
index 216224c..f135fbf 100644
--- a/services/core/Android.bp
+++ b/services/core/Android.bp
@@ -88,12 +88,21 @@
out: ["com/android/internal/art/ArtStatsLog.java"],
}
+genrule {
+ name: "statslog-contexthub-java-gen",
+ tools: ["stats-log-api-gen"],
+ cmd: "$(location stats-log-api-gen) --java $(out) --module contexthub" +
+ " --javaPackage com.android.server.location.contexthub --javaClass ContextHubStatsLog",
+ out: ["com/android/server/location/contexthub/ContextHubStatsLog.java"],
+}
+
java_library_static {
name: "services.core.unboosted",
defaults: ["platform_service_defaults"],
srcs: [
":android.hardware.biometrics.face-V1-java-source",
":statslog-art-java-gen",
+ ":statslog-contexthub-java-gen",
":services.core-sources",
":services.core.protologsrc",
":dumpstate_aidl",
diff --git a/services/core/java/android/content/pm/OWNERS b/services/core/java/android/content/pm/OWNERS
index 5eed0b5..3993140 100644
--- a/services/core/java/android/content/pm/OWNERS
+++ b/services/core/java/android/content/pm/OWNERS
@@ -1 +1 @@
-include /core/java/android/content/pm/OWNERS
\ No newline at end of file
+include /PACKAGE_MANAGER_OWNERS
\ No newline at end of file
diff --git a/services/core/java/com/android/server/BatteryService.java b/services/core/java/com/android/server/BatteryService.java
index 1e608f5..0146aa8 100644
--- a/services/core/java/com/android/server/BatteryService.java
+++ b/services/core/java/com/android/server/BatteryService.java
@@ -81,8 +81,6 @@
import java.io.PrintWriter;
import java.util.ArrayDeque;
import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.List;
import java.util.NoSuchElementException;
import java.util.Objects;
import java.util.concurrent.atomic.AtomicReference;
@@ -1435,11 +1433,7 @@
*/
public static final class HealthServiceWrapper {
private static final String TAG = "HealthServiceWrapper";
- public static final String INSTANCE_HEALTHD = "backup";
public static final String INSTANCE_VENDOR = "default";
- // All interesting instances, sorted by priority high -> low.
- private static final List<String> sAllInstances =
- Arrays.asList(INSTANCE_VENDOR, INSTANCE_HEALTHD);
private final IServiceNotification mNotification = new Notification();
private final HandlerThread mHandlerThread = new HandlerThread("HealthServiceHwbinder");
@@ -1471,8 +1465,8 @@
}
/**
- * Start monitoring registration of new IHealth services. Only instances that are in
- * {@code sAllInstances} and in device / framework manifest are used. This function should
+ * Start monitoring registration of new IHealth services. Only instance
+ * {@link #INSTANCE_VENDOR} and in device / framework manifest are used. This function should
* only be called once.
*
* mCallback.onRegistration() is called synchronously (aka in init thread) before
@@ -1481,7 +1475,7 @@
* @throws RemoteException transaction error when talking to IServiceManager
* @throws NoSuchElementException if one of the following cases:
* - No service manager;
- * - none of {@code sAllInstances} are in manifests (i.e. not
+ * - {@link #INSTANCE_VENDOR} is not in manifests (i.e. not
* available on this device), or none of these instances are available to current
* process.
* @throws NullPointerException when supplier is null
@@ -1499,26 +1493,23 @@
// Initialize mLastService and call callback for the first time (in init thread)
IHealth newService = null;
- for (String name : sAllInstances) {
- traceBegin("HealthInitGetService_" + name);
- try {
- newService = healthSupplier.get(name);
- } catch (NoSuchElementException ex) {
- /* ignored, handled below */
- } finally {
- traceEnd();
- }
- if (newService != null) {
- mInstanceName = name;
- mLastService.set(newService);
- break;
- }
+ traceBegin("HealthInitGetService_" + INSTANCE_VENDOR);
+ try {
+ newService = healthSupplier.get(INSTANCE_VENDOR);
+ } catch (NoSuchElementException ex) {
+ /* ignored, handled below */
+ } finally {
+ traceEnd();
+ }
+ if (newService != null) {
+ mInstanceName = INSTANCE_VENDOR;
+ mLastService.set(newService);
}
if (mInstanceName == null || newService == null) {
throw new NoSuchElementException(String.format(
- "No IHealth service instance among %s is available. Perhaps no permission?",
- sAllInstances.toString()));
+ "IHealth service instance %s isn't available. Perhaps no permission?",
+ INSTANCE_VENDOR));
}
if (callback != null) {
diff --git a/services/core/java/com/android/server/IpSecService.java b/services/core/java/com/android/server/IpSecService.java
index d6ee951..aeb8143 100644
--- a/services/core/java/com/android/server/IpSecService.java
+++ b/services/core/java/com/android/server/IpSecService.java
@@ -58,13 +58,13 @@
import android.text.TextUtils;
import android.util.Log;
import android.util.Range;
-import android.util.Slog;
import android.util.SparseArray;
import android.util.SparseBooleanArray;
import com.android.internal.annotations.GuardedBy;
import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.util.Preconditions;
+import com.android.net.module.util.BinderUtils;
import com.android.net.module.util.NetdUtils;
import com.android.net.module.util.PermissionUtils;
@@ -1056,9 +1056,9 @@
public void systemReady() {
if (isNetdAlive()) {
- Slog.d(TAG, "IpSecService is ready");
+ Log.d(TAG, "IpSecService is ready");
} else {
- Slog.wtf(TAG, "IpSecService not ready: failed to connect to NetD Native Service!");
+ Log.wtf(TAG, "IpSecService not ready: failed to connect to NetD Native Service!");
}
}
@@ -1332,7 +1332,7 @@
final INetd netd = mSrvConfig.getNetdInstance();
netd.ipSecAddTunnelInterface(intfName, localAddr, remoteAddr, ikey, okey, resourceId);
- Binder.withCleanCallingIdentity(() -> {
+ BinderUtils.withCleanCallingIdentity(() -> {
NetdUtils.setInterfaceUp(netd, intfName);
});
diff --git a/services/core/java/com/android/server/SystemService.java b/services/core/java/com/android/server/SystemService.java
index 39321bf..9923274 100644
--- a/services/core/java/com/android/server/SystemService.java
+++ b/services/core/java/com/android/server/SystemService.java
@@ -301,17 +301,20 @@
protected void dumpSupportedUsers(@NonNull PrintWriter pw, @NonNull String prefix) {
final List<UserInfo> allUsers = UserManager.get(mContext).getUsers();
final List<Integer> supportedUsers = new ArrayList<>(allUsers.size());
- for (UserInfo user : allUsers) {
- supportedUsers.add(user.id);
+ for (int i = 0; i < allUsers.size(); i++) {
+ final UserInfo user = allUsers.get(i);
+ if (isUserSupported(new TargetUser(user))) {
+ supportedUsers.add(user.id);
+ }
}
- if (allUsers.isEmpty()) {
+ if (supportedUsers.isEmpty()) {
pw.print(prefix); pw.println("No supported users");
- } else {
- final int size = supportedUsers.size();
- pw.print(prefix); pw.print(size); pw.print(" supported user");
- if (size > 1) pw.print("s");
- pw.print(": "); pw.println(supportedUsers);
+ return;
}
+ final int size = supportedUsers.size();
+ pw.print(prefix); pw.print(size); pw.print(" supported user");
+ if (size > 1) pw.print("s");
+ pw.print(": "); pw.println(supportedUsers);
}
/**
diff --git a/services/core/java/com/android/server/am/ActiveServices.java b/services/core/java/com/android/server/am/ActiveServices.java
index 1997897..b5623be 100644
--- a/services/core/java/com/android/server/am/ActiveServices.java
+++ b/services/core/java/com/android/server/am/ActiveServices.java
@@ -5110,6 +5110,29 @@
return didSomething;
}
+ void makeServicesNonForegroundLocked(final String pkg, final @UserIdInt int userId) {
+ final ServiceMap smap = mServiceMap.get(userId);
+ if (smap != null) {
+ ArrayList<ServiceRecord> fgsList = new ArrayList<>();
+ for (int i = 0; i < smap.mServicesByInstanceName.size(); i++) {
+ final ServiceRecord sr = smap.mServicesByInstanceName.valueAt(i);
+ if (sr.appInfo.packageName.equals(pkg) && sr.isForeground) {
+ fgsList.add(sr);
+ }
+ }
+
+ final int numServices = fgsList.size();
+ if (DEBUG_FOREGROUND_SERVICE) {
+ Slog.i(TAG_SERVICE, "Forcing " + numServices + " services out of foreground in u"
+ + userId + "/" + pkg);
+ }
+ for (int i = 0; i < numServices; i++) {
+ final ServiceRecord sr = fgsList.get(i);
+ setServiceForegroundInnerLocked(sr, 0, null, Service.STOP_FOREGROUND_REMOVE, 0);
+ }
+ }
+ }
+
void forceStopPackageLocked(String packageName, int userId) {
ServiceMap smap = mServiceMap.get(userId);
if (smap != null && smap.mActiveForegroundApps.size() > 0) {
diff --git a/services/core/java/com/android/server/am/ActivityManagerService.java b/services/core/java/com/android/server/am/ActivityManagerService.java
index f6c1106..53f7575 100644
--- a/services/core/java/com/android/server/am/ActivityManagerService.java
+++ b/services/core/java/com/android/server/am/ActivityManagerService.java
@@ -2397,6 +2397,7 @@
mBatteryStatsService.publish();
mAppOpsService.publish();
+ mProcessStats.publish();
Slog.d("AppOps", "AppOpsService published");
LocalServices.addService(ActivityManagerInternal.class, mInternal);
LocalManagerRegistry.addManager(ActivityManagerLocal.class,
@@ -3751,6 +3752,29 @@
}
@Override
+ public void makeServicesNonForeground(final String packageName, int userId) {
+ if (checkCallingPermission(android.Manifest.permission.MANAGE_ACTIVITY_TASKS)
+ != PackageManager.PERMISSION_GRANTED) {
+ String msg = "Permission Denial: makeServicesNonForeground() from pid="
+ + Binder.getCallingPid()
+ + ", uid=" + Binder.getCallingUid()
+ + " requires " + android.Manifest.permission.MANAGE_ACTIVITY_TASKS;
+ Slog.w(TAG, msg);
+ throw new SecurityException(msg);
+ }
+
+ final int callingPid = Binder.getCallingPid();
+ userId = mUserController.handleIncomingUser(callingPid, Binder.getCallingUid(),
+ userId, true, ALLOW_FULL_ONLY, "makeServicesNonForeground", null);
+ final long callingId = Binder.clearCallingIdentity();
+ try {
+ makeServicesNonForegroundUnchecked(packageName, userId);
+ } finally {
+ Binder.restoreCallingIdentity(callingId);
+ }
+ }
+
+ @Override
public void forceStopPackage(final String packageName, int userId) {
if (checkCallingPermission(android.Manifest.permission.FORCE_STOP_PACKAGES)
!= PackageManager.PERMISSION_GRANTED) {
@@ -4058,6 +4082,13 @@
}
}
+ private void makeServicesNonForegroundUnchecked(final String packageName,
+ final @UserIdInt int userId) {
+ synchronized (this) {
+ mServices.makeServicesNonForegroundLocked(packageName, userId);
+ }
+ }
+
@GuardedBy("this")
private void forceStopPackageLocked(final String packageName, int uid, String reason) {
forceStopPackageLocked(packageName, UserHandle.getAppId(uid), false,
@@ -16399,6 +16430,11 @@
}
@Override
+ public void makeServicesNonForeground(String pkg, int userId) {
+ ActivityManagerService.this.makeServicesNonForegroundUnchecked(pkg, userId);
+ }
+
+ @Override
public void stopForegroundServicesForChannel(String pkg, int userId,
String channelId) {
synchronized (ActivityManagerService.this) {
diff --git a/services/core/java/com/android/server/am/ActivityManagerShellCommand.java b/services/core/java/com/android/server/am/ActivityManagerShellCommand.java
index 685d606..0f71639 100644
--- a/services/core/java/com/android/server/am/ActivityManagerShellCommand.java
+++ b/services/core/java/com/android/server/am/ActivityManagerShellCommand.java
@@ -229,6 +229,8 @@
return runBugReport(pw);
case "force-stop":
return runForceStop(pw);
+ case "stop-fgs":
+ return runStopForegroundServices(pw);
case "fgs-notification-rate-limit":
return runFgsNotificationRateLimit(pw);
case "crash":
@@ -1105,6 +1107,22 @@
return 0;
}
+ int runStopForegroundServices(PrintWriter pw) throws RemoteException {
+ int userId = UserHandle.USER_SYSTEM;
+
+ String opt;
+ while ((opt = getNextOption()) != null) {
+ if (opt.equals("--user")) {
+ userId = UserHandle.parseUserArg(getNextArgRequired());
+ } else {
+ getErrPrintWriter().println("Error: Unknown option: " + opt);
+ return -1;
+ }
+ }
+ mInterface.makeServicesNonForeground(getNextArgRequired(), userId);
+ return 0;
+ }
+
int runFgsNotificationRateLimit(PrintWriter pw) throws RemoteException {
final String toggleValue = getNextArgRequired();
final boolean enable;
diff --git a/services/core/java/com/android/server/am/OomAdjuster.java b/services/core/java/com/android/server/am/OomAdjuster.java
index a6b265b..dc9ecfe 100644
--- a/services/core/java/com/android/server/am/OomAdjuster.java
+++ b/services/core/java/com/android/server/am/OomAdjuster.java
@@ -1079,6 +1079,7 @@
}
if ((numCached - numCachedExtraGroup) > cachedProcessLimit) {
app.killLocked("cached #" + numCached,
+ "too many cached",
ApplicationExitInfo.REASON_OTHER,
ApplicationExitInfo.SUBREASON_TOO_MANY_CACHED,
true);
@@ -1089,6 +1090,7 @@
&& app.getLastActivityTime() < oldTime) {
app.killLocked("empty for " + ((oldTime + ProcessList.MAX_EMPTY_TIME
- app.getLastActivityTime()) / 1000) + "s",
+ "empty for too long",
ApplicationExitInfo.REASON_OTHER,
ApplicationExitInfo.SUBREASON_TRIM_EMPTY,
true);
@@ -1096,6 +1098,7 @@
numEmpty++;
if (numEmpty > emptyProcessLimit) {
app.killLocked("empty #" + numEmpty,
+ "too many empty",
ApplicationExitInfo.REASON_OTHER,
ApplicationExitInfo.SUBREASON_TOO_MANY_EMPTY,
true);
diff --git a/services/core/java/com/android/server/am/ProcessRecord.java b/services/core/java/com/android/server/am/ProcessRecord.java
index c573615..8ae1259 100644
--- a/services/core/java/com/android/server/am/ProcessRecord.java
+++ b/services/core/java/com/android/server/am/ProcessRecord.java
@@ -1003,6 +1003,12 @@
@GuardedBy("mService")
void killLocked(String reason, @Reason int reasonCode, @SubReason int subReason,
boolean noisy) {
+ killLocked(reason, reason, reasonCode, subReason, noisy);
+ }
+
+ @GuardedBy("mService")
+ void killLocked(String reason, String description, @Reason int reasonCode,
+ @SubReason int subReason, boolean noisy) {
if (!mKilledByAm) {
Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "kill");
if (mService != null && (noisy || info.uid == mService.mCurOomAdjUid)) {
@@ -1011,7 +1017,7 @@
+ "): " + reason, info.uid);
}
if (mPid > 0) {
- mService.mProcessList.noteAppKill(this, reasonCode, subReason, reason);
+ mService.mProcessList.noteAppKill(this, reasonCode, subReason, description);
EventLog.writeEvent(EventLogTags.AM_KILL,
userId, mPid, processName, mState.getSetAdj(), reason);
Process.killProcessQuiet(mPid);
diff --git a/services/core/java/com/android/server/am/ProcessStatsService.java b/services/core/java/com/android/server/am/ProcessStatsService.java
index 34a0c1b..256cffd 100644
--- a/services/core/java/com/android/server/am/ProcessStatsService.java
+++ b/services/core/java/com/android/server/am/ProcessStatsService.java
@@ -38,8 +38,11 @@
import com.android.internal.app.procstats.IProcessStats;
import com.android.internal.app.procstats.ProcessState;
import com.android.internal.app.procstats.ProcessStats;
+import com.android.internal.app.procstats.ProcessStatsInternal;
import com.android.internal.app.procstats.ServiceState;
+import com.android.internal.app.procstats.UidState;
import com.android.internal.os.BackgroundThread;
+import com.android.server.LocalServices;
import java.io.File;
import java.io.FileDescriptor;
@@ -783,6 +786,64 @@
}
}
+ private SparseArray<long[]> getUidProcStateStatsOverTime(long minTime) {
+ final Parcel current = Parcel.obtain();
+ final ProcessStats stats = new ProcessStats();
+ long curTime;
+ synchronized (mLock) {
+ final long now = SystemClock.uptimeMillis();
+ mProcessStats.mTimePeriodEndRealtime = SystemClock.elapsedRealtime();
+ mProcessStats.mTimePeriodEndUptime = now;
+ stats.add(mProcessStats);
+ curTime = mProcessStats.mTimePeriodEndRealtime - mProcessStats.mTimePeriodStartRealtime;
+ }
+ if (curTime < minTime) {
+ try {
+ mFileLock.lock();
+ // Need to add in older stats to reach desired time.
+ ArrayList<String> files = getCommittedFilesLF(0, false, true);
+ if (files != null && files.size() > 0) {
+ int i = files.size() - 1;
+ while (i >= 0 && (stats.mTimePeriodEndRealtime
+ - stats.mTimePeriodStartRealtime) < minTime) {
+ AtomicFile file = new AtomicFile(new File(files.get(i)));
+ i--;
+ ProcessStats moreStats = new ProcessStats(false);
+ readLF(moreStats, file);
+ if (moreStats.mReadError == null) {
+ stats.add(moreStats);
+ } else {
+ Slog.w(TAG, "Failure reading " + files.get(i + 1) + "; "
+ + moreStats.mReadError);
+ continue;
+ }
+ }
+ }
+ } finally {
+ mFileLock.unlock();
+ }
+ }
+ final SparseArray<UidState> uidStates = stats.mUidStates;
+ final SparseArray<long[]> results = new SparseArray<>();
+ for (int i = 0, size = uidStates.size(); i < size; i++) {
+ final int uid = uidStates.keyAt(i);
+ final UidState uidState = uidStates.valueAt(i);
+ results.put(uid, uidState.getAggregatedDurationsInStates());
+ }
+ return results;
+ }
+
+ void publish() {
+ LocalServices.addService(ProcessStatsInternal.class, new LocalService());
+ }
+
+ private final class LocalService extends ProcessStatsInternal {
+ @Override
+ public SparseArray<long[]> getUidProcStateStatsOverTime(long minTime) {
+ return ProcessStatsService.this.getUidProcStateStatsOverTime(minTime);
+ }
+ }
+
private void dumpAggregatedStats(PrintWriter pw, long aggregateHours, long now,
String reqPackage, boolean isCompact, boolean dumpDetails, boolean dumpFullDetails,
boolean dumpAll, boolean activeOnly, int section) {
diff --git a/services/core/java/com/android/server/apphibernation/AppHibernationManagerInternal.java b/services/core/java/com/android/server/apphibernation/AppHibernationManagerInternal.java
index b0335fe..a3c9612 100644
--- a/services/core/java/com/android/server/apphibernation/AppHibernationManagerInternal.java
+++ b/services/core/java/com/android/server/apphibernation/AppHibernationManagerInternal.java
@@ -43,4 +43,9 @@
* @see AppHibernationService#setHibernatingGlobally
*/
public abstract void setHibernatingGlobally(String packageName, boolean isHibernating);
+
+ /**
+ * @see AppHibernationService#isOatArtifactDeletionEnabled
+ */
+ public abstract boolean isOatArtifactDeletionEnabled();
}
diff --git a/services/core/java/com/android/server/apphibernation/AppHibernationService.java b/services/core/java/com/android/server/apphibernation/AppHibernationService.java
index bd066ff..4d025c9 100644
--- a/services/core/java/com/android/server/apphibernation/AppHibernationService.java
+++ b/services/core/java/com/android/server/apphibernation/AppHibernationService.java
@@ -200,6 +200,14 @@
}
/**
+ * Whether global hibernation should delete ART ahead-of-time compilation artifacts and prevent
+ * package manager from re-optimizing the APK.
+ */
+ private boolean isOatArtifactDeletionEnabled() {
+ return mOatArtifactDeletionEnabled;
+ }
+
+ /**
* Whether a package is hibernating for a given user.
*
* @param packageName the package to check
@@ -730,6 +738,11 @@
public boolean isHibernatingGlobally(String packageName) {
return mService.isHibernatingGlobally(packageName);
}
+
+ @Override
+ public boolean isOatArtifactDeletionEnabled() {
+ return mService.isOatArtifactDeletionEnabled();
+ }
}
private final AppHibernationServiceStub mServiceStub = new AppHibernationServiceStub(this);
diff --git a/services/core/java/com/android/server/audio/AudioDeviceBroker.java b/services/core/java/com/android/server/audio/AudioDeviceBroker.java
index 4cb786a..e5e29a6 100644
--- a/services/core/java/com/android/server/audio/AudioDeviceBroker.java
+++ b/services/core/java/com/android/server/audio/AudioDeviceBroker.java
@@ -1774,19 +1774,36 @@
MESSAGES_MUTE_MUSIC.add(MSG_L_A2DP_DEVICE_CONNECTION_CHANGE_EXT_DISCONNECTION);
MESSAGES_MUTE_MUSIC.add(MSG_L_LE_AUDIO_DEVICE_OUT_CONNECTION_CHANGE_EXT);
MESSAGES_MUTE_MUSIC.add(MSG_IIL_SET_FORCE_BT_A2DP_USE);
- MESSAGES_MUTE_MUSIC.add(MSG_REPORT_NEW_ROUTES_A2DP);
}
private AtomicBoolean mMusicMuted = new AtomicBoolean(false);
+ boolean messageMutesMusic(int message) {
+ if (message == 0) {
+ return false;
+ }
+ // Do not mute if we are disconnecting an A2DP device and music is playing
+ // on a wired headset.
+ if ((message == MSG_IL_SET_A2DP_SINK_CONNECTION_STATE_DISCONNECTED
+ || message == MSG_L_A2DP_DEVICE_CONNECTION_CHANGE_EXT_DISCONNECTION)
+ && AudioSystem.isStreamActive(AudioSystem.STREAM_MUSIC, 0)
+ && mDeviceInventory.DEVICE_OVERRIDE_A2DP_ROUTE_ON_PLUG_SET.contains(
+ mAudioService.getDevicesForStream(AudioSystem.STREAM_MUSIC))) {
+ return false;
+ }
+ return true;
+ }
+
/** Mutes or unmutes music according to pending A2DP messages */
private void checkMessagesMuteMusic(int message) {
- boolean mute = message != 0;
+ boolean mute = messageMutesMusic(message);
if (!mute) {
for (int msg : MESSAGES_MUTE_MUSIC) {
if (mBrokerHandler.hasMessages(msg)) {
- mute = true;
- break;
+ if (messageMutesMusic(msg)) {
+ mute = true;
+ break;
+ }
}
}
}
diff --git a/services/core/java/com/android/server/audio/AudioDeviceInventory.java b/services/core/java/com/android/server/audio/AudioDeviceInventory.java
index 6c3c736..5909f80 100644
--- a/services/core/java/com/android/server/audio/AudioDeviceInventory.java
+++ b/services/core/java/com/android/server/audio/AudioDeviceInventory.java
@@ -581,7 +581,7 @@
mDeviceBroker.postObserveDevicesForAllStreams();
}
- private static final Set<Integer> DEVICE_OVERRIDE_A2DP_ROUTE_ON_PLUG_SET;
+ /* package */ static final Set<Integer> DEVICE_OVERRIDE_A2DP_ROUTE_ON_PLUG_SET;
static {
DEVICE_OVERRIDE_A2DP_ROUTE_ON_PLUG_SET = new HashSet<>();
DEVICE_OVERRIDE_A2DP_ROUTE_ON_PLUG_SET.add(AudioSystem.DEVICE_OUT_WIRED_HEADSET);
diff --git a/services/core/java/com/android/server/audio/AudioService.java b/services/core/java/com/android/server/audio/AudioService.java
index 34277a2..2cd63b5 100644
--- a/services/core/java/com/android/server/audio/AudioService.java
+++ b/services/core/java/com/android/server/audio/AudioService.java
@@ -6214,9 +6214,15 @@
*/
public @AudioManager.DeviceVolumeBehavior
int getDeviceVolumeBehavior(@NonNull AudioDeviceAttributes device) {
+ Objects.requireNonNull(device);
// verify permissions
enforceQueryStateOrModifyRoutingPermission();
+ return getDeviceVolumeBehaviorInt(device);
+ }
+
+ private @AudioManager.DeviceVolumeBehavior
+ int getDeviceVolumeBehaviorInt(@NonNull AudioDeviceAttributes device) {
// translate Java device type to native device type (for the devices masks for full / fixed)
final int audioSystemDeviceOut = AudioDeviceInfo.convertDeviceTypeToInternalDevice(
device.getType());
@@ -6244,6 +6250,29 @@
return AudioManager.DEVICE_VOLUME_BEHAVIOR_VARIABLE;
}
+ /**
+ * @see AudioManager#isVolumeFixed()
+ * Note there are no permission checks on this operation, as this is part of API 21
+ * @return true if the current device's volume behavior for media is
+ * DEVICE_VOLUME_BEHAVIOR_FIXED
+ */
+ public boolean isVolumeFixed() {
+ if (mUseFixedVolume) {
+ return true;
+ }
+ final AudioAttributes attributes = new AudioAttributes.Builder()
+ .setUsage(AudioAttributes.USAGE_MEDIA)
+ .build();
+ // calling getDevice*Int to bypass permission check
+ final List<AudioDeviceAttributes> devices = getDevicesForAttributesInt(attributes);
+ for (AudioDeviceAttributes device : devices) {
+ if (getDeviceVolumeBehaviorInt(device) == AudioManager.DEVICE_VOLUME_BEHAVIOR_FIXED) {
+ return true;
+ }
+ }
+ return false;
+ }
+
/*package*/ static final int CONNECTION_STATE_DISCONNECTED = 0;
/*package*/ static final int CONNECTION_STATE_CONNECTED = 1;
/**
diff --git a/services/core/java/com/android/server/biometrics/sensors/fingerprint/FingerprintStateCallback.java b/services/core/java/com/android/server/biometrics/sensors/fingerprint/FingerprintStateCallback.java
index 0050a89..be0e6ed 100644
--- a/services/core/java/com/android/server/biometrics/sensors/fingerprint/FingerprintStateCallback.java
+++ b/services/core/java/com/android/server/biometrics/sensors/fingerprint/FingerprintStateCallback.java
@@ -23,7 +23,6 @@
import static android.hardware.fingerprint.FingerprintStateListener.STATE_KEYGUARD_AUTH;
import android.annotation.NonNull;
-import android.content.Context;
import android.hardware.fingerprint.FingerprintStateListener;
import android.hardware.fingerprint.IFingerprintStateListener;
import android.os.RemoteException;
@@ -34,8 +33,6 @@
import com.android.server.biometrics.sensors.BaseClientMonitor;
import com.android.server.biometrics.sensors.EnrollClient;
import com.android.server.biometrics.sensors.EnrollmentModifier;
-import com.android.server.biometrics.sensors.RemovalConsumer;
-import com.android.server.biometrics.sensors.fingerprint.hidl.FingerprintEnrollClient;
import java.util.concurrent.CopyOnWriteArrayList;
@@ -70,7 +67,7 @@
} else {
mFingerprintState = STATE_AUTH_OTHER;
}
- } else if (client instanceof FingerprintEnrollClient) {
+ } else if (client instanceof EnrollClient) {
mFingerprintState = STATE_ENROLLING;
} else {
Slog.w(FingerprintService.TAG,
@@ -143,6 +140,7 @@
/**
* Enables clients to register a FingerprintStateListener. Used by FingerprintService to forward
* updates in fingerprint sensor state to the SideFpNsEventHandler
+ *
* @param listener
*/
public void registerFingerprintStateListener(@NonNull IFingerprintStateListener listener) {
diff --git a/services/core/java/com/android/server/biometrics/sensors/fingerprint/aidl/FingerprintAuthenticationClient.java b/services/core/java/com/android/server/biometrics/sensors/fingerprint/aidl/FingerprintAuthenticationClient.java
index ca051e9..e4d5fba 100644
--- a/services/core/java/com/android/server/biometrics/sensors/fingerprint/aidl/FingerprintAuthenticationClient.java
+++ b/services/core/java/com/android/server/biometrics/sensors/fingerprint/aidl/FingerprintAuthenticationClient.java
@@ -229,6 +229,7 @@
@Override
public void onLockoutTimed(long durationMillis) {
+ super.onLockoutTimed(durationMillis);
mLockoutCache.setLockoutModeForUser(getTargetUserId(), LockoutTracker.LOCKOUT_TIMED);
// Lockout metrics are logged as an error code.
final int error = BiometricFingerprintConstants.FINGERPRINT_ERROR_LOCKOUT;
@@ -246,6 +247,7 @@
@Override
public void onLockoutPermanent() {
+ super.onLockoutPermanent();
mLockoutCache.setLockoutModeForUser(getTargetUserId(), LockoutTracker.LOCKOUT_PERMANENT);
// Lockout metrics are logged as an error code.
final int error = BiometricFingerprintConstants.FINGERPRINT_ERROR_LOCKOUT_PERMANENT;
diff --git a/services/core/java/com/android/server/connectivity/MultipathPolicyTracker.java b/services/core/java/com/android/server/connectivity/MultipathPolicyTracker.java
index 091e6c4..a56a8ea 100644
--- a/services/core/java/com/android/server/connectivity/MultipathPolicyTracker.java
+++ b/services/core/java/com/android/server/connectivity/MultipathPolicyTracker.java
@@ -227,7 +227,7 @@
subscriberId = tele.getSubscriberId();
mNetworkTemplate = new NetworkTemplate(
NetworkTemplate.MATCH_MOBILE, subscriberId, new String[] { subscriberId },
- null, NetworkStats.METERED_ALL, NetworkStats.ROAMING_ALL,
+ null, NetworkStats.METERED_YES, NetworkStats.ROAMING_ALL,
NetworkStats.DEFAULT_NETWORK_NO, NETWORK_TYPE_ALL, OEM_MANAGED_ALL,
SUBSCRIBER_ID_MATCH_RULE_EXACT);
mUsageCallback = new UsageCallback() {
diff --git a/services/core/java/com/android/server/connectivity/Vpn.java b/services/core/java/com/android/server/connectivity/Vpn.java
index 243a336b..bf4ef48 100644
--- a/services/core/java/com/android/server/connectivity/Vpn.java
+++ b/services/core/java/com/android/server/connectivity/Vpn.java
@@ -126,6 +126,7 @@
import libcore.io.IoUtils;
import java.io.File;
+import java.io.FileDescriptor;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
@@ -195,6 +196,7 @@
private final Context mContext;
private final ConnectivityManager mConnectivityManager;
+ private final AppOpsManager mAppOpsManager;
// The context is for specific user which is created from mUserId
private final Context mUserIdContext;
@VisibleForTesting final Dependencies mDeps;
@@ -407,6 +409,46 @@
public boolean isInterfacePresent(final Vpn vpn, final String iface) {
return vpn.jniCheck(iface) != 0;
}
+
+ /**
+ * @see ParcelFileDescriptor#adoptFd(int)
+ */
+ public ParcelFileDescriptor adoptFd(Vpn vpn, int mtu) {
+ return ParcelFileDescriptor.adoptFd(jniCreate(vpn, mtu));
+ }
+
+ /**
+ * Call native method to create the VPN interface and return the FileDescriptor of /dev/tun.
+ */
+ public int jniCreate(Vpn vpn, int mtu) {
+ return vpn.jniCreate(mtu);
+ }
+
+ /**
+ * Call native method to get the interface name of VPN.
+ */
+ public String jniGetName(Vpn vpn, int fd) {
+ return vpn.jniGetName(fd);
+ }
+
+ /**
+ * Call native method to set the VPN addresses and return the number of addresses.
+ */
+ public int jniSetAddresses(Vpn vpn, String interfaze, String addresses) {
+ return vpn.jniSetAddresses(interfaze, addresses);
+ }
+
+ /**
+ * @see IoUtils#setBlocking(FileDescriptor, boolean)
+ */
+ public void setBlocking(FileDescriptor fd, boolean blocking) {
+ try {
+ IoUtils.setBlocking(fd, blocking);
+ } catch (IOException e) {
+ throw new IllegalStateException(
+ "Cannot set tunnel's fd as blocking=" + blocking, e);
+ }
+ }
}
public Vpn(Looper looper, Context context, INetworkManagementService netService, INetd netd,
@@ -431,6 +473,7 @@
mVpnProfileStore = vpnProfileStore;
mContext = context;
mConnectivityManager = mContext.getSystemService(ConnectivityManager.class);
+ mAppOpsManager = mContext.getSystemService(AppOpsManager.class);
mUserIdContext = context.createContextAsUser(UserHandle.of(userId), 0 /* flags */);
mDeps = deps;
mNms = netService;
@@ -826,7 +869,6 @@
VpnProfile profile = getVpnProfilePrivileged(alwaysOnPackage);
if (profile != null) {
startVpnProfilePrivileged(profile, alwaysOnPackage);
-
// If the above startVpnProfilePrivileged() call returns, the Ikev2VpnProfile was
// correctly parsed, and the VPN has started running in a different thread. The only
// other possibility is that the above call threw an exception, which will be
@@ -974,9 +1016,15 @@
} catch (Exception e) {
// ignore
}
+ mAppOpsManager.finishOp(
+ AppOpsManager.OPSTR_ESTABLISH_VPN_SERVICE, mOwnerUID, mPackage, null);
mContext.unbindService(mConnection);
cleanupVpnStateLocked();
} else if (mVpnRunner != null) {
+ if (!VpnConfig.LEGACY_VPN.equals(mPackage)) {
+ mAppOpsManager.finishOp(
+ AppOpsManager.OPSTR_ESTABLISH_VPN_MANAGER, mOwnerUID, mPackage, null);
+ }
// cleanupVpnStateLocked() is called from mVpnRunner.exit()
mVpnRunner.exit();
}
@@ -1041,10 +1089,8 @@
return false;
}
- final AppOpsManager appOpMgr =
- (AppOpsManager) mContext.getSystemService(Context.APP_OPS_SERVICE);
for (final String appOpStr : toChange) {
- appOpMgr.setMode(
+ mAppOpsManager.setMode(
appOpStr,
uid,
packageName,
@@ -1366,9 +1412,9 @@
Set<Range<Integer>> oldUsers = mNetworkCapabilities.getUids();
// Configure the interface. Abort if any of these steps fails.
- ParcelFileDescriptor tun = ParcelFileDescriptor.adoptFd(jniCreate(config.mtu));
+ final ParcelFileDescriptor tun = mDeps.adoptFd(this, config.mtu);
try {
- String interfaze = jniGetName(tun.getFd());
+ final String interfaze = mDeps.jniGetName(this, tun.getFd());
// TEMP use the old jni calls until there is support for netd address setting
StringBuilder builder = new StringBuilder();
@@ -1376,7 +1422,7 @@
builder.append(" ");
builder.append(address);
}
- if (jniSetAddresses(interfaze, builder.toString()) < 1) {
+ if (mDeps.jniSetAddresses(this, interfaze, builder.toString()) < 1) {
throw new IllegalArgumentException("At least one address must be specified");
}
Connection connection = new Connection();
@@ -1422,11 +1468,11 @@
jniReset(oldInterface);
}
- try {
- IoUtils.setBlocking(tun.getFileDescriptor(), config.blocking);
- } catch (IOException e) {
- throw new IllegalStateException(
- "Cannot set tunnel's fd as blocking=" + config.blocking, e);
+ mDeps.setBlocking(tun.getFileDescriptor(), config.blocking);
+ // Record that the VPN connection is established by an app which uses VpnService API.
+ if (oldNetworkAgent != mNetworkAgent) {
+ mAppOpsManager.startOp(
+ AppOpsManager.OPSTR_ESTABLISH_VPN_SERVICE, mOwnerUID, mPackage, null, null);
}
} catch (RuntimeException e) {
IoUtils.closeQuietly(tun);
@@ -1781,9 +1827,17 @@
synchronized (Vpn.this) {
if (interfaze.equals(mInterface) && jniCheck(interfaze) == 0) {
if (mConnection != null) {
+ mAppOpsManager.finishOp(
+ AppOpsManager.OPSTR_ESTABLISH_VPN_SERVICE, mOwnerUID, mPackage,
+ null);
mContext.unbindService(mConnection);
cleanupVpnStateLocked();
} else if (mVpnRunner != null) {
+ if (!VpnConfig.LEGACY_VPN.equals(mPackage)) {
+ mAppOpsManager.finishOp(
+ AppOpsManager.OPSTR_ESTABLISH_VPN_MANAGER, mOwnerUID, mPackage,
+ null);
+ }
// cleanupVpnStateLocked() is called from mVpnRunner.exit()
mVpnRunner.exit();
}
@@ -3254,8 +3308,7 @@
*
* @param packageName the package name of the app provisioning this profile
*/
- public synchronized void startVpnProfile(
- @NonNull String packageName) {
+ public synchronized void startVpnProfile(@NonNull String packageName) {
requireNonNull(packageName, "No package name provided");
enforceNotRestrictedUser();
@@ -3318,6 +3371,13 @@
Log.d(TAG, "Unknown VPN profile type: " + profile.type);
break;
}
+
+ // Record that the VPN connection is established by an app which uses VpnManager API.
+ if (!VpnConfig.LEGACY_VPN.equals(packageName)) {
+ mAppOpsManager.startOp(
+ AppOpsManager.OPSTR_ESTABLISH_VPN_MANAGER, mOwnerUID, mPackage, null,
+ null);
+ }
} catch (GeneralSecurityException e) {
// Reset mConfig
mConfig = null;
diff --git a/services/core/java/com/android/server/display/DisplayManagerService.java b/services/core/java/com/android/server/display/DisplayManagerService.java
index 5178f35..8481ad0 100644
--- a/services/core/java/com/android/server/display/DisplayManagerService.java
+++ b/services/core/java/com/android/server/display/DisplayManagerService.java
@@ -2117,9 +2117,6 @@
pw.println();
mLogicalDisplayMapper.dumpLocked(pw);
- pw.println();
- mDisplayModeDirector.dump(pw);
-
final int callbackCount = mCallbacks.size();
pw.println();
pw.println("Callbacks: size=" + callbackCount);
@@ -2142,6 +2139,8 @@
pw.println();
mPersistentDataStore.dump(pw);
}
+ pw.println();
+ mDisplayModeDirector.dump(pw);
}
private static float[] getFloatArray(TypedArray array) {
diff --git a/services/core/java/com/android/server/display/DisplayModeDirector.java b/services/core/java/com/android/server/display/DisplayModeDirector.java
index 87b9e6a..c82b16d 100644
--- a/services/core/java/com/android/server/display/DisplayModeDirector.java
+++ b/services/core/java/com/android/server/display/DisplayModeDirector.java
@@ -524,7 +524,10 @@
*/
public void setShouldAlwaysRespectAppRequestedMode(boolean enabled) {
synchronized (mLock) {
- mAlwaysRespectAppRequest = enabled;
+ if (mAlwaysRespectAppRequest != enabled) {
+ mAlwaysRespectAppRequest = enabled;
+ notifyDesiredDisplayModeSpecsChangedLocked();
+ }
}
}
diff --git a/services/core/java/com/android/server/display/DisplayPowerState.java b/services/core/java/com/android/server/display/DisplayPowerState.java
index 147050c..2f22d33 100644
--- a/services/core/java/com/android/server/display/DisplayPowerState.java
+++ b/services/core/java/com/android/server/display/DisplayPowerState.java
@@ -48,7 +48,7 @@
final class DisplayPowerState {
private static final String TAG = "DisplayPowerState";
- private static boolean DEBUG = false;
+ private static final boolean DEBUG = false;
private static String COUNTER_COLOR_FADE = "ColorFadeLevel";
private final Handler mHandler;
diff --git a/services/core/java/com/android/server/dreams/DreamController.java b/services/core/java/com/android/server/dreams/DreamController.java
index 5bc69943..76754d3 100644
--- a/services/core/java/com/android/server/dreams/DreamController.java
+++ b/services/core/java/com/android/server/dreams/DreamController.java
@@ -117,7 +117,8 @@
}
public void startDream(Binder token, ComponentName name,
- boolean isTest, boolean canDoze, int userId, PowerManager.WakeLock wakeLock) {
+ boolean isTest, boolean canDoze, int userId, PowerManager.WakeLock wakeLock,
+ ComponentName overlayComponentName) {
stopDream(true /*immediate*/, "starting new dream");
Trace.traceBegin(Trace.TRACE_TAG_POWER, "startDream");
@@ -138,6 +139,7 @@
Intent intent = new Intent(DreamService.SERVICE_INTERFACE);
intent.setComponent(name);
intent.addFlags(Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS);
+ intent.putExtra(DreamService.EXTRA_DREAM_OVERLAY_COMPONENT, overlayComponentName);
try {
if (!mContext.bindServiceAsUser(intent, mCurrentDream,
Context.BIND_AUTO_CREATE | Context.BIND_FOREGROUND_SERVICE,
diff --git a/services/core/java/com/android/server/dreams/DreamManagerService.java b/services/core/java/com/android/server/dreams/DreamManagerService.java
index 3a7220f7..258689a 100644
--- a/services/core/java/com/android/server/dreams/DreamManagerService.java
+++ b/services/core/java/com/android/server/dreams/DreamManagerService.java
@@ -95,6 +95,8 @@
private int mCurrentDreamDozeScreenState = Display.STATE_UNKNOWN;
private int mCurrentDreamDozeScreenBrightness = PowerManager.BRIGHTNESS_DEFAULT;
+ private ComponentName mDreamOverlayServiceName;
+
private AmbientDisplayConfiguration mDozeConfig;
@VisibleForTesting
@@ -421,7 +423,8 @@
if (!mCurrentDreamName.equals(mAmbientDisplayComponent)) {
mUiEventLogger.log(DreamManagerEvent.DREAM_START);
}
- mController.startDream(newToken, name, isTest, canDoze, userId, wakeLock);
+ mController.startDream(newToken, name, isTest, canDoze, userId, wakeLock,
+ mDreamOverlayServiceName);
}));
}
@@ -592,6 +595,15 @@
}
@Override // Binder call
+ public void registerDreamOverlayService(ComponentName overlayComponent) {
+ checkPermission(android.Manifest.permission.WRITE_DREAM_STATE);
+
+ // Store the overlay service component so that it can be passed to the dream when it is
+ // invoked.
+ mDreamOverlayServiceName = overlayComponent;
+ }
+
+ @Override // Binder call
public ComponentName getDefaultDreamComponentForUser(int userId) {
checkPermission(android.Manifest.permission.READ_DREAM_STATE);
userId = ActivityManager.handleIncomingUser(Binder.getCallingPid(),
diff --git a/services/core/java/com/android/server/hdmi/HdmiCecLocalDevice.java b/services/core/java/com/android/server/hdmi/HdmiCecLocalDevice.java
index f356c36..3aa2f42 100755
--- a/services/core/java/com/android/server/hdmi/HdmiCecLocalDevice.java
+++ b/services/core/java/com/android/server/hdmi/HdmiCecLocalDevice.java
@@ -208,6 +208,12 @@
void init() {
assertRunOnServiceThread();
mPreferredAddress = getPreferredAddress();
+ if (mHandler.hasMessages(MSG_DISABLE_DEVICE_TIMEOUT)) {
+ // Remove and trigger the queued message for clearing all actions when going to standby.
+ // This is necessary because the device may wake up before the message is triggered.
+ mHandler.removeMessages(MSG_DISABLE_DEVICE_TIMEOUT);
+ handleDisableDeviceTimeout();
+ }
mPendingActionClearedCallback = null;
}
diff --git a/services/core/java/com/android/server/hdmi/HdmiControlService.java b/services/core/java/com/android/server/hdmi/HdmiControlService.java
index b5bb8bd..69f7af2 100644
--- a/services/core/java/com/android/server/hdmi/HdmiControlService.java
+++ b/services/core/java/com/android/server/hdmi/HdmiControlService.java
@@ -3166,7 +3166,7 @@
Slog.v(TAG, "On standby-action cleared:" + device.mDeviceType);
devices.remove(device);
if (devices.isEmpty()) {
- onStandbyCompleted(standbyAction);
+ onPendingActionsCleared(standbyAction);
// We will not clear local devices here, since some OEM/SOC will keep passing
// the received packets until the application processor enters to the sleep
// actually.
@@ -3227,10 +3227,17 @@
mHdmiCecNetwork.clearLocalDevices();
}
+ /**
+ * Normally called after all devices have cleared their pending actions, to execute the final
+ * phase of the standby flow.
+ *
+ * This can also be called during wakeup, when pending actions are cleared after failing to be
+ * cleared during standby. In this case, it does not execute the standby flow.
+ */
@ServiceThreadOnly
- private void onStandbyCompleted(int standbyAction) {
+ private void onPendingActionsCleared(int standbyAction) {
assertRunOnServiceThread();
- Slog.v(TAG, "onStandbyCompleted");
+ Slog.v(TAG, "onPendingActionsCleared");
if (!mPowerStatusController.isPowerStatusTransientToStandby()) {
return;
diff --git a/services/core/java/com/android/server/inputmethod/OWNERS b/services/core/java/com/android/server/inputmethod/OWNERS
index c09ade9..00cd700 100644
--- a/services/core/java/com/android/server/inputmethod/OWNERS
+++ b/services/core/java/com/android/server/inputmethod/OWNERS
@@ -5,3 +5,4 @@
tarandeep@google.com
lumark@google.com
roosa@google.com
+wilsonwu@google.com
diff --git a/services/core/java/com/android/server/location/contexthub/ContextHubService.java b/services/core/java/com/android/server/location/contexthub/ContextHubService.java
index 686926f..1c04d8c 100644
--- a/services/core/java/com/android/server/location/contexthub/ContextHubService.java
+++ b/services/core/java/com/android/server/location/contexthub/ContextHubService.java
@@ -49,6 +49,7 @@
import android.os.RemoteException;
import android.os.ResultReceiver;
import android.os.ShellCallback;
+import android.os.SystemClock;
import android.os.UserHandle;
import android.provider.Settings;
import android.util.Log;
@@ -184,6 +185,7 @@
}
public ContextHubService(Context context) {
+ long startTimeNs = SystemClock.elapsedRealtimeNanos();
mContext = context;
mContextHubWrapper = getContextHubWrapper();
@@ -205,6 +207,9 @@
Log.e(TAG, "RemoteException while getting Context Hub info", e);
hubInfo = new Pair(Collections.emptyList(), Collections.emptyList());
}
+ long bootTimeNs = SystemClock.elapsedRealtimeNanos() - startTimeNs;
+ int numContextHubs = hubInfo.first.size();
+ ContextHubStatsLog.write(ContextHubStatsLog.CONTEXT_HUB_BOOTED, bootTimeNs, numContextHubs);
mContextHubIdToInfoMap = Collections.unmodifiableMap(
ContextHubServiceUtil.createContextHubInfoMap(hubInfo.first));
diff --git a/services/core/java/com/android/server/location/provider/LocationProviderManager.java b/services/core/java/com/android/server/location/provider/LocationProviderManager.java
index 83de0b3..cbca48c9 100644
--- a/services/core/java/com/android/server/location/provider/LocationProviderManager.java
+++ b/services/core/java/com/android/server/location/provider/LocationProviderManager.java
@@ -1996,6 +1996,11 @@
+ TimeUtils.formatDuration(delayMs));
}
+ if (mDelayedRegister != null) {
+ mAlarmHelper.cancel(mDelayedRegister);
+ mDelayedRegister = null;
+ }
+
mDelayedRegister = new OnAlarmListener() {
@Override
public void onAlarm() {
diff --git a/services/core/java/com/android/server/media/AudioPlayerStateMonitor.java b/services/core/java/com/android/server/media/AudioPlayerStateMonitor.java
index d285c43..4873467 100644
--- a/services/core/java/com/android/server/media/AudioPlayerStateMonitor.java
+++ b/services/core/java/com/android/server/media/AudioPlayerStateMonitor.java
@@ -40,7 +40,7 @@
* Monitors the state changes of audio players.
*/
class AudioPlayerStateMonitor {
- private static boolean DEBUG = MediaSessionService.DEBUG;
+ private static final boolean DEBUG = MediaSessionService.DEBUG;
private static String TAG = "AudioPlayerStateMonitor";
private static AudioPlayerStateMonitor sInstance;
diff --git a/services/core/java/com/android/server/net/NetworkPolicyLogger.java b/services/core/java/com/android/server/net/NetworkPolicyLogger.java
index b45d87f..d0aa40b 100644
--- a/services/core/java/com/android/server/net/NetworkPolicyLogger.java
+++ b/services/core/java/com/android/server/net/NetworkPolicyLogger.java
@@ -15,12 +15,14 @@
*/
package com.android.server.net;
+import static android.net.ConnectivityManager.BLOCKED_REASON_NONE;
import static android.net.INetd.FIREWALL_CHAIN_DOZABLE;
import static android.net.INetd.FIREWALL_CHAIN_POWERSAVE;
import static android.net.INetd.FIREWALL_CHAIN_RESTRICTED;
import static android.net.INetd.FIREWALL_CHAIN_STANDBY;
import static android.net.INetd.FIREWALL_RULE_ALLOW;
import static android.net.INetd.FIREWALL_RULE_DENY;
+import static android.net.NetworkPolicyManager.ALLOWED_REASON_NONE;
import static android.net.NetworkPolicyManager.FIREWALL_CHAIN_NAME_DOZABLE;
import static android.net.NetworkPolicyManager.FIREWALL_CHAIN_NAME_POWERSAVE;
import static android.net.NetworkPolicyManager.FIREWALL_CHAIN_NAME_RESTRICTED;
@@ -29,6 +31,7 @@
import static android.os.PowerExemptionManager.reasonCodeToString;
import static android.os.Process.INVALID_UID;
+import android.annotation.Nullable;
import android.app.ActivityManager;
import android.app.ActivityManager.ProcessCapability;
import android.net.NetworkPolicyManager;
@@ -81,13 +84,18 @@
private final Object mLock = new Object();
- void networkBlocked(int uid, UidBlockedState uidBlockedState) {
+ void networkBlocked(int uid, @Nullable UidBlockedState uidBlockedState) {
synchronized (mLock) {
if (LOGD || uid == mDebugUid) {
Slog.d(TAG, "Blocked state of uid: " + uidBlockedState.toString());
}
- mNetworkBlockedBuffer.networkBlocked(uid, uidBlockedState.blockedReasons,
- uidBlockedState.allowedReasons, uidBlockedState.effectiveBlockedReasons);
+ if (uidBlockedState == null) {
+ mNetworkBlockedBuffer.networkBlocked(uid, BLOCKED_REASON_NONE, ALLOWED_REASON_NONE,
+ BLOCKED_REASON_NONE);
+ } else {
+ mNetworkBlockedBuffer.networkBlocked(uid, uidBlockedState.blockedReasons,
+ uidBlockedState.allowedReasons, uidBlockedState.effectiveBlockedReasons);
+ }
}
}
diff --git a/services/core/java/com/android/server/notification/NotificationManagerService.java b/services/core/java/com/android/server/notification/NotificationManagerService.java
index f14f7695..f701c2a 100755
--- a/services/core/java/com/android/server/notification/NotificationManagerService.java
+++ b/services/core/java/com/android/server/notification/NotificationManagerService.java
@@ -2824,6 +2824,12 @@
mPreferencesHelper.getNotificationChannel(pkg, uid, channel.getId(), true);
mPreferencesHelper.updateNotificationChannel(pkg, uid, channel, true);
+ if (mEnableAppSettingMigration) {
+ if (mPreferencesHelper.onlyHasDefaultChannel(pkg, uid)) {
+ mPermissionHelper.setNotificationPermission(pkg, UserHandle.getUserId(uid),
+ channel.getImportance() != IMPORTANCE_NONE, true);
+ }
+ }
maybeNotifyChannelOwner(pkg, uid, preUpdate, channel);
if (!fromListener) {
diff --git a/services/core/java/com/android/server/notification/PreferencesHelper.java b/services/core/java/com/android/server/notification/PreferencesHelper.java
index b94721a..c74813a 100644
--- a/services/core/java/com/android/server/notification/PreferencesHelper.java
+++ b/services/core/java/com/android/server/notification/PreferencesHelper.java
@@ -1043,9 +1043,11 @@
r.channels.put(updatedChannel.getId(), updatedChannel);
if (onlyHasDefaultChannel(pkg, uid)) {
- // copy settings to app level so they are inherited by new channels
- // when the app migrates
- r.importance = updatedChannel.getImportance();
+ if (!mPermissionHelper.isMigrationEnabled()) {
+ // copy settings to app level so they are inherited by new channels
+ // when the app migrates
+ r.importance = updatedChannel.getImportance();
+ }
r.priority = updatedChannel.canBypassDnd()
? Notification.PRIORITY_MAX : Notification.PRIORITY_DEFAULT;
r.visibility = updatedChannel.getLockscreenVisibility();
diff --git a/services/core/java/com/android/server/pm/ComputerEngine.java b/services/core/java/com/android/server/pm/ComputerEngine.java
index aa4d6bb..569d651 100644
--- a/services/core/java/com/android/server/pm/ComputerEngine.java
+++ b/services/core/java/com/android/server/pm/ComputerEngine.java
@@ -798,7 +798,8 @@
for (int n = 0; n < count; n++) {
ResolveInfo info = candidates.get(n);
if (blockInstant && (info.isInstantAppAvailable
- || isInstantApp(info.activityInfo.packageName, userId))) {
+ || isInstantAppInternal(info.activityInfo.packageName, userId,
+ Process.SYSTEM_UID))) {
continue;
}
@@ -1075,7 +1076,8 @@
resolveInfos.remove(i);
continue;
}
- if (blockInstant && isInstantApp(info.activityInfo.packageName, userId)) {
+ if (blockInstant && isInstantAppInternal(
+ info.activityInfo.packageName, userId, Process.SYSTEM_UID)) {
resolveInfos.remove(i);
continue;
}
diff --git a/services/core/java/com/android/server/pm/DexOptHelper.java b/services/core/java/com/android/server/pm/DexOptHelper.java
index 9390284..5c3a991 100644
--- a/services/core/java/com/android/server/pm/DexOptHelper.java
+++ b/services/core/java/com/android/server/pm/DexOptHelper.java
@@ -49,8 +49,6 @@
import com.android.internal.R;
import com.android.internal.annotations.GuardedBy;
import com.android.internal.logging.MetricsLogger;
-import com.android.server.apphibernation.AppHibernationManagerInternal;
-import com.android.server.apphibernation.AppHibernationService;
import com.android.server.pm.dex.DexManager;
import com.android.server.pm.dex.DexoptOptions;
import com.android.server.pm.parsing.pkg.AndroidPackage;
@@ -171,7 +169,7 @@
}
}
- if (!PackageDexOptimizer.canOptimizePackage(pkg)) {
+ if (!mPm.mPackageDexOptimizer.canOptimizePackage(pkg)) {
if (DEBUG_DEXOPT) {
Log.i(TAG, "Skipping update of non-optimizable app " + pkg.getPackageName());
}
@@ -291,16 +289,11 @@
ArraySet<String> pkgs = new ArraySet<>();
synchronized (mPm.mLock) {
for (AndroidPackage p : mPm.mPackages.values()) {
- if (PackageDexOptimizer.canOptimizePackage(p)) {
+ if (mPm.mPackageDexOptimizer.canOptimizePackage(p)) {
pkgs.add(p.getPackageName());
}
}
}
- if (AppHibernationService.isAppHibernationEnabled()) {
- AppHibernationManagerInternal appHibernationManager =
- mPm.mInjector.getLocalService(AppHibernationManagerInternal.class);
- pkgs.removeIf(pkgName -> appHibernationManager.isHibernatingGlobally(pkgName));
- }
return pkgs;
}
diff --git a/services/core/java/com/android/server/pm/IncrementalProgressListener.java b/services/core/java/com/android/server/pm/IncrementalProgressListener.java
index bb797cb..43a938e 100644
--- a/services/core/java/com/android/server/pm/IncrementalProgressListener.java
+++ b/services/core/java/com/android/server/pm/IncrementalProgressListener.java
@@ -37,7 +37,20 @@
if (ps == null) {
return;
}
- ps.setLoadingProgress(progress);
+
+ boolean wasLoading = ps.isPackageLoading();
+ // Due to asynchronous progress reporting, incomplete progress might be received
+ // after the app is migrated off incremental. Ignore such progress updates.
+ if (wasLoading) {
+ ps.setLoadingProgress(progress);
+ // Only report the state change when loading state changes from loading to not
+ if (!ps.isPackageLoading()) {
+ // Unregister progress listener
+ mPm.mIncrementalManager.unregisterLoadingProgressCallbacks(ps.getPathString());
+ // Make sure the information is preserved
+ mPm.scheduleWriteSettingsLocked();
+ }
+ }
}
}
}
diff --git a/services/core/java/com/android/server/pm/IncrementalStates.java b/services/core/java/com/android/server/pm/IncrementalStates.java
deleted file mode 100644
index 3101ca7..0000000
--- a/services/core/java/com/android/server/pm/IncrementalStates.java
+++ /dev/null
@@ -1,232 +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.server.pm;
-
-import android.content.pm.IncrementalStatesInfo;
-import android.os.Handler;
-import android.util.Slog;
-
-import com.android.internal.annotations.GuardedBy;
-import com.android.internal.os.BackgroundThread;
-import com.android.internal.util.function.pooled.PooledLambda;
-
-/**
- * Manages state transitions of a package installed on Incremental File System. Currently manages:
- * 1. loading state (whether a package is still loading or has been fully loaded).
- *
- * The following events might change the states of a package:
- * 1. Installation commit
- * 2. Loading progress changes
- *
- * @hide
- */
-public final class IncrementalStates {
- private static final String TAG = "IncrementalStates";
- private static final boolean DEBUG = false;
- private final Handler mHandler = BackgroundThread.getHandler();
- private final Object mLock = new Object();
- @GuardedBy("mLock")
- private final LoadingState mLoadingState;
- @GuardedBy("mLock")
- private Callback mCallback = null;
-
- public IncrementalStates() {
- // By default the package is not fully loaded (i.e., is loading)
- this(true, 0);
- }
-
- public IncrementalStates(boolean isLoading, float loadingProgress) {
- mLoadingState = new LoadingState(isLoading, loadingProgress);
- }
-
- /**
- * Callback interface to report that the loading state of this package has changed.
- */
- public interface Callback {
- /**
- * Reports that package is fully loaded.
- */
- void onPackageFullyLoaded();
- }
-
- /**
- * By calling this method, the caller indicates that package installation has just been
- * committed. Set the initial loading state after the package
- * is committed. Incremental packages are by-default loading; non-Incremental packages are not.
- *
- * @param isIncremental whether a package is installed on Incremental or not.
- */
- public void onCommit(boolean isIncremental) {
- if (DEBUG) {
- Slog.i(TAG, "received package commit event");
- }
- if (!isIncremental) {
- synchronized (mLock) {
- updateProgressLocked(1.0f);
- }
- onLoadingStateChanged();
- }
- }
-
- private void onLoadingStateChanged() {
- mHandler.post(PooledLambda.obtainRunnable(
- IncrementalStates::reportFullyLoaded,
- IncrementalStates.this).recycleOnUse());
- }
-
- private void reportFullyLoaded() {
- final Callback callback;
- synchronized (mLock) {
- callback = mCallback;
- }
- if (callback != null) {
- callback.onPackageFullyLoaded();
- }
- }
-
- /**
- * Use the specified callback to report state changing events.
- *
- * @param callback Object to report new state.
- */
- public void setCallback(Callback callback) {
- if (DEBUG) {
- Slog.i(TAG, "registered callback");
- }
- synchronized (mLock) {
- mCallback = callback;
- }
- }
-
- /**
- * Update the package loading progress to specified value.
- *
- * @param progress Value between [0, 1].
- */
- public void setProgress(float progress) {
- final boolean oldLoadingState;
- final boolean newLoadingState;
- synchronized (mLock) {
- oldLoadingState = mLoadingState.isLoading();
- if (oldLoadingState) {
- // Due to asynchronous progress reporting, incomplete progress might be received
- // after the app is migrated off incremental. Ignore such progress updates.
- updateProgressLocked(progress);
- }
- newLoadingState = mLoadingState.isLoading();
- }
- if (oldLoadingState && !newLoadingState) {
- // Only report the state change when loading state changes from true to false
- onLoadingStateChanged();
- }
- }
-
- /**
- * @return all current states in a Parcelable.
- */
- public IncrementalStatesInfo getIncrementalStatesInfo() {
- synchronized (mLock) {
- return new IncrementalStatesInfo(
- mLoadingState.isLoading(),
- mLoadingState.getProgress());
- }
- }
-
- private void updateProgressLocked(float progress) {
- if (DEBUG) {
- Slog.i(TAG, "received progress update: " + progress);
- }
- mLoadingState.setProgress(progress);
- if (Math.abs(1.0f - progress) < 0.00000001f) {
- if (DEBUG) {
- Slog.i(TAG, "package is fully loaded");
- }
- mLoadingState.setProgress(1.0f);
- if (mLoadingState.isLoading()) {
- mLoadingState.adoptNewLoadingStateLocked(false);
- }
- }
- }
-
- private class LoadingState {
- private boolean mIsLoading;
- private float mProgress;
-
- LoadingState(boolean isLoading, float loadingProgress) {
- mIsLoading = isLoading;
- // loading progress is reset to 1 if loading has finished
- mProgress = isLoading ? loadingProgress : 1;
- }
-
- public boolean isLoading() {
- return mIsLoading;
- }
-
- public float getProgress() {
- return mProgress;
- }
-
- public void setProgress(float progress) {
- mProgress = progress;
- }
-
- public void adoptNewLoadingStateLocked(boolean nextState) {
- if (DEBUG) {
- Slog.i(TAG, "Loading state changed from " + mIsLoading + " to " + nextState);
- }
- mIsLoading = nextState;
- }
-
- @Override
- public boolean equals(Object o) {
- if (o == this) {
- return true;
- }
- if (!(o instanceof LoadingState)) {
- return false;
- }
- LoadingState l = (LoadingState) o;
- return l.mIsLoading == mIsLoading && l.mProgress == mProgress;
- }
-
- @Override
- public int hashCode() {
- int hashCode = Boolean.hashCode(mIsLoading);
- hashCode = 31 * hashCode + Float.hashCode(mProgress);
- return hashCode;
- }
- }
-
-
-
- @Override
- public boolean equals(Object o) {
- if (o == this) {
- return true;
- }
- if (!(o instanceof IncrementalStates)) {
- return false;
- }
- IncrementalStates l = (IncrementalStates) o;
- return l.mLoadingState.equals(mLoadingState);
- }
-
- @Override
- public int hashCode() {
- return mLoadingState.hashCode();
- }
-}
diff --git a/services/core/java/com/android/server/pm/IncrementalStatesCallback.java b/services/core/java/com/android/server/pm/IncrementalStatesCallback.java
deleted file mode 100644
index 478c99b..0000000
--- a/services/core/java/com/android/server/pm/IncrementalStatesCallback.java
+++ /dev/null
@@ -1,46 +0,0 @@
-/*
- * Copyright (C) 2021 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;
-
-/**
- * Package states callback, used to listen for package state changes and send broadcasts
- */
-final class IncrementalStatesCallback implements IncrementalStates.Callback {
- private final String mPackageName;
- private final PackageManagerService mPm;
-
- IncrementalStatesCallback(String packageName, PackageManagerService pm) {
- mPackageName = packageName;
- mPm = pm;
- }
-
- @Override
- public void onPackageFullyLoaded() {
- final String codePath;
- synchronized (mPm.mLock) {
- final PackageSetting ps = mPm.mSettings.getPackageLPr(mPackageName);
- if (ps == null) {
- return;
- }
- codePath = ps.getPathString();
- }
- // Unregister progress listener
- mPm.mIncrementalManager.unregisterLoadingProgressCallbacks(codePath);
- // Make sure the information is preserved
- mPm.scheduleWriteSettingsLocked();
- }
-}
diff --git a/services/core/java/com/android/server/pm/InitAndSystemPackageHelper.java b/services/core/java/com/android/server/pm/InitAndSystemPackageHelper.java
index 722198f..5ff0a6f 100644
--- a/services/core/java/com/android/server/pm/InitAndSystemPackageHelper.java
+++ b/services/core/java/com/android/server/pm/InitAndSystemPackageHelper.java
@@ -172,9 +172,16 @@
scanSystemDirs(packageParser, executorService);
// Parse overlay configuration files to set default enable state, mutability, and
// priority of system overlays.
+ final ArrayMap<String, File> apkInApexPreInstalledPaths = new ArrayMap<>();
+ for (ApexManager.ActiveApexInfo apexInfo : mPm.mApexManager.getActiveApexInfos()) {
+ for (String packageName : mPm.mApexManager.getApksInApex(apexInfo.apexModuleName)) {
+ apkInApexPreInstalledPaths.put(packageName, apexInfo.preInstalledApexPath);
+ }
+ }
OverlayConfig overlayConfig = OverlayConfig.initializeSystemInstance(
consumer -> mPm.forEachPackage(
- pkg -> consumer.accept(pkg, pkg.isSystem())));
+ pkg -> consumer.accept(pkg, pkg.isSystem(),
+ apkInApexPreInstalledPaths.get(pkg.getPackageName()))));
cleanupSystemPackagesAndInstallStubs(packageParser, executorService, packageSettings,
startTime, userIds);
packageParser.close();
diff --git a/services/core/java/com/android/server/pm/InstallPackageHelper.java b/services/core/java/com/android/server/pm/InstallPackageHelper.java
index 7569900..4c70cda 100644
--- a/services/core/java/com/android/server/pm/InstallPackageHelper.java
+++ b/services/core/java/com/android/server/pm/InstallPackageHelper.java
@@ -59,6 +59,7 @@
import android.os.Trace;
import android.os.UserHandle;
import android.os.UserManager;
+import android.os.incremental.IncrementalManager;
import android.util.ArrayMap;
import android.util.Log;
import android.util.Slog;
@@ -455,7 +456,10 @@
if (pkgSetting.getInstantApp(userId)) {
mPm.mInstantAppRegistry.addInstantAppLPw(userId, pkgSetting.getAppId());
}
- pkgSetting.setStatesOnCommit();
+
+ if (!IncrementalManager.isIncrementalPath(pkgSetting.getPathString())) {
+ pkgSetting.setLoadingProgress(1f);
+ }
return pkg;
}
diff --git a/services/core/java/com/android/server/pm/InstallParams.java b/services/core/java/com/android/server/pm/InstallParams.java
index bfb5f76..e138188 100644
--- a/services/core/java/com/android/server/pm/InstallParams.java
+++ b/services/core/java/com/android/server/pm/InstallParams.java
@@ -1781,9 +1781,6 @@
final String codePath = ps.getPathString();
if (IncrementalManager.isIncrementalPath(codePath)
&& mPm.mIncrementalManager != null) {
- final IncrementalStatesCallback incrementalStatesCallback =
- new IncrementalStatesCallback(ps.getPackageName(), mPm);
- ps.setIncrementalStatesCallback(incrementalStatesCallback);
mPm.mIncrementalManager.registerLoadingProgressCallback(codePath,
new IncrementalProgressListener(ps.getPackageName(), mPm));
}
diff --git a/services/core/java/com/android/server/pm/OWNERS b/services/core/java/com/android/server/pm/OWNERS
index 3233819..1bdc9f3 100644
--- a/services/core/java/com/android/server/pm/OWNERS
+++ b/services/core/java/com/android/server/pm/OWNERS
@@ -3,27 +3,25 @@
jsharkey@android.com
jsharkey@google.com
narayan@google.com
-patb@google.com
svetoslavganov@android.com
svetoslavganov@google.com
-toddke@android.com
-toddke@google.com
+include /PACKAGE_MANAGER_OWNERS
# apex support
per-file ApexManager.java = dariofreni@google.com, ioffe@google.com, olilan@google.com
per-file StagingManager.java = dariofreni@google.com, ioffe@google.com, olilan@google.com
# dex
-per-file AbstractStatsBase.java = calin@google.com, ngeoffray@google.com
-per-file BackgroundDexOptService.java = calin@google.com, ngeoffray@google.com
-per-file CompilerStats.java = calin@google.com, ngeoffray@google.com
-per-file DynamicCodeLoggingService.java = alanstokes@google.com, calin@google.com, ngeoffray@google.com
-per-file InstructionSets.java = calin@google.com, ngeoffray@google.com
-per-file OtaDexoptService.java = calin@google.com, ngeoffray@google.com
-per-file OtaDexoptShellCommand.java = calin@google.com, ngeoffray@google.com
-per-file PackageDexOptimizer.java = calin@google.com, ngeoffray@google.com
-per-file PackageManagerServiceCompilerMapping.java = calin@google.com, ngeoffray@google.com
-per-file PackageUsage.java = calin@google.com, ngeoffray@google.com
+per-file AbstractStatsBase.java = file:dex/OWNERS
+per-file BackgroundDexOptService.java = file:dex/OWNERS
+per-file CompilerStats.java = file:dex/OWNERS
+per-file DynamicCodeLoggingService.java = file:dex/OWNERS
+per-file InstructionSets.java = file:dex/OWNERS
+per-file OtaDexoptService.java = file:dex/OWNERS
+per-file OtaDexoptShellCommand.java = file:dex/OWNERS
+per-file PackageDexOptimizer.java = file:dex/OWNERS
+per-file PackageManagerServiceCompilerMapping.java = file:dex/OWNERS
+per-file PackageUsage.java = file:dex/OWNERS
# multi user / cross profile
per-file CrossProfileAppsServiceImpl.java = omakoto@google.com, yamasani@google.com
diff --git a/services/core/java/com/android/server/pm/OtaDexoptService.java b/services/core/java/com/android/server/pm/OtaDexoptService.java
index 68801d6..9122221f 100644
--- a/services/core/java/com/android/server/pm/OtaDexoptService.java
+++ b/services/core/java/com/android/server/pm/OtaDexoptService.java
@@ -387,7 +387,7 @@
}
// Does the package have code? If not, there won't be any artifacts.
- if (!PackageDexOptimizer.canOptimizePackage(pkg)) {
+ if (!mPackageManagerService.mPackageDexOptimizer.canOptimizePackage(pkg)) {
continue;
}
if (pkg.getPath() == null) {
diff --git a/services/core/java/com/android/server/pm/PackageDexOptimizer.java b/services/core/java/com/android/server/pm/PackageDexOptimizer.java
index 7739f2f..cac1978 100644
--- a/services/core/java/com/android/server/pm/PackageDexOptimizer.java
+++ b/services/core/java/com/android/server/pm/PackageDexOptimizer.java
@@ -64,7 +64,10 @@
import android.util.SparseArray;
import com.android.internal.annotations.GuardedBy;
+import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.util.IndentingPrintWriter;
+import com.android.server.LocalServices;
+import com.android.server.apphibernation.AppHibernationManagerInternal;
import com.android.server.pm.Installer.InstallerException;
import com.android.server.pm.dex.ArtManagerService;
import com.android.server.pm.dex.ArtStatsLogUtils;
@@ -134,16 +137,24 @@
private volatile boolean mSystemReady;
private final ArtStatsLogger mArtStatsLogger = new ArtStatsLogger();
+ private final Injector mInjector;
+
private static final Random sRandom = new Random();
PackageDexOptimizer(Installer installer, Object installLock, Context context,
String wakeLockTag) {
- this.mInstaller = installer;
- this.mInstallLock = installLock;
+ this(new Injector() {
+ @Override
+ public AppHibernationManagerInternal getAppHibernationManagerInternal() {
+ return LocalServices.getService(AppHibernationManagerInternal.class);
+ }
- PowerManager powerManager = (PowerManager)context.getSystemService(Context.POWER_SERVICE);
- mDexoptWakeLock = powerManager.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, wakeLockTag);
+ @Override
+ public PowerManager getPowerManager(Context context) {
+ return context.getSystemService(PowerManager.class);
+ }
+ }, installer, installLock, context, wakeLockTag);
}
protected PackageDexOptimizer(PackageDexOptimizer from) {
@@ -151,9 +162,21 @@
this.mInstallLock = from.mInstallLock;
this.mDexoptWakeLock = from.mDexoptWakeLock;
this.mSystemReady = from.mSystemReady;
+ this.mInjector = from.mInjector;
}
- static boolean canOptimizePackage(AndroidPackage pkg) {
+ @VisibleForTesting
+ PackageDexOptimizer(@NonNull Injector injector, Installer installer, Object installLock,
+ Context context, String wakeLockTag) {
+ this.mInstaller = installer;
+ this.mInstallLock = installLock;
+
+ PowerManager powerManager = injector.getPowerManager(context);
+ mDexoptWakeLock = powerManager.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, wakeLockTag);
+ mInjector = injector;
+ }
+
+ boolean canOptimizePackage(AndroidPackage pkg) {
// We do not dexopt a package with no code.
// Note that the system package is marked as having no code, however we can
// still optimize it via dexoptSystemServerPath.
@@ -161,6 +184,13 @@
return false;
}
+ // We do not dexopt unused packages.
+ AppHibernationManagerInternal ahm = mInjector.getAppHibernationManagerInternal();
+ if (ahm.isHibernatingGlobally(pkg.getPackageName())
+ && ahm.isOatArtifactDeletionEnabled()) {
+ return false;
+ }
+
return true;
}
@@ -1000,4 +1030,13 @@
private Installer getInstallerWithoutLock() {
return mInstaller;
}
+
+ /**
+ * Injector for {@link PackageDexOptimizer} dependencies
+ */
+ interface Injector {
+ AppHibernationManagerInternal getAppHibernationManagerInternal();
+
+ PowerManager getPowerManager(Context context);
+ }
}
diff --git a/services/core/java/com/android/server/pm/PackageInstallerService.java b/services/core/java/com/android/server/pm/PackageInstallerService.java
index 2595bb4..fc266c8 100644
--- a/services/core/java/com/android/server/pm/PackageInstallerService.java
+++ b/services/core/java/com/android/server/pm/PackageInstallerService.java
@@ -174,6 +174,7 @@
private final File mSessionsDir;
private final InternalCallback mInternalCallback = new InternalCallback();
+ private final PackageSessionVerifier mSessionVerifier;
/**
* Used for generating session IDs. Since this is created at boot time,
@@ -257,8 +258,9 @@
mSessionsDir.mkdirs();
mApexManager = ApexManager.getInstance();
- mStagingManager = new StagingManager(context, apexParserSupplier,
- mInstallThread.getLooper());
+ mStagingManager = new StagingManager(context);
+ mSessionVerifier = new PackageSessionVerifier(context, mPm, mApexManager,
+ apexParserSupplier, mInstallThread.getLooper());
LocalServices.getService(SystemServiceManager.class).startService(
new Lifecycle(context, this));
@@ -1160,6 +1162,11 @@
}
@Override
+ public PackageSessionVerifier getSessionVerifier() {
+ return mSessionVerifier;
+ }
+
+ @Override
public void bypassNextStagedInstallerCheck(boolean value) {
if (!isCalledBySystemOrShell(Binder.getCallingUid())) {
throw new SecurityException("Caller not allowed to bypass staged installer check");
diff --git a/services/core/java/com/android/server/pm/PackageInstallerSession.java b/services/core/java/com/android/server/pm/PackageInstallerSession.java
index 3805977..97f8dc2 100644
--- a/services/core/java/com/android/server/pm/PackageInstallerSession.java
+++ b/services/core/java/com/android/server/pm/PackageInstallerSession.java
@@ -732,11 +732,10 @@
}
/**
- * Notified by the staging manager or PIS that pre-reboot verification has ended.
+ * Called when pre-reboot verification has ended.
* Now it is safe to clean up the session if {@link #abandon()} has been called previously.
*/
- @Override
- public void notifyEndPreRebootVerification() {
+ private void notifyEndPreRebootVerification() {
synchronized (mLock) {
if (!mInPreRebootVerification) {
throw new IllegalStateException("Pre-reboot verification not started");
@@ -2382,6 +2381,16 @@
private void verify() {
try {
+ List<PackageInstallerSession> children = getChildSessions();
+ if (isMultiPackage()) {
+ for (PackageInstallerSession child : children) {
+ child.prepareInheritedFiles();
+ child.parseApkAndExtractNativeLibraries();
+ }
+ } else {
+ prepareInheritedFiles();
+ parseApkAndExtractNativeLibraries();
+ }
verifyNonStaged();
} catch (PackageManagerException e) {
final String completeMsg = ExceptionUtils.getCompleteMessage(e);
@@ -2401,6 +2410,118 @@
}
}
+ /**
+ * Prepares staged directory with any inherited APKs.
+ */
+ private void prepareInheritedFiles() throws PackageManagerException {
+ if (isApexSession() || params.mode != SessionParams.MODE_INHERIT_EXISTING) {
+ return;
+ }
+ synchronized (mLock) {
+ if (mRelinquished) {
+ throw new PackageManagerException(INSTALL_FAILED_INTERNAL_ERROR,
+ "Session relinquished");
+ }
+ if (mDestroyed) {
+ throw new PackageManagerException(INSTALL_FAILED_INTERNAL_ERROR,
+ "Session destroyed");
+ }
+ if (!mSealed) {
+ throw new PackageManagerException(INSTALL_FAILED_INTERNAL_ERROR,
+ "Session not sealed");
+ }
+ // Inherit any packages and native libraries from existing install that
+ // haven't been overridden.
+ try {
+ final List<File> fromFiles = mResolvedInheritedFiles;
+ final File toDir = stageDir;
+
+ if (LOGD) Slog.d(TAG, "Inherited files: " + mResolvedInheritedFiles);
+ if (!mResolvedInheritedFiles.isEmpty() && mInheritedFilesBase == null) {
+ throw new IllegalStateException("mInheritedFilesBase == null");
+ }
+
+ if (isLinkPossible(fromFiles, toDir)) {
+ if (!mResolvedInstructionSets.isEmpty()) {
+ final File oatDir = new File(toDir, "oat");
+ createOatDirs(mResolvedInstructionSets, oatDir);
+ }
+ // pre-create lib dirs for linking if necessary
+ if (!mResolvedNativeLibPaths.isEmpty()) {
+ for (String libPath : mResolvedNativeLibPaths) {
+ // "/lib/arm64" -> ["lib", "arm64"]
+ final int splitIndex = libPath.lastIndexOf('/');
+ if (splitIndex < 0 || splitIndex >= libPath.length() - 1) {
+ Slog.e(TAG,
+ "Skipping native library creation for linking due"
+ + " to invalid path: " + libPath);
+ continue;
+ }
+ final String libDirPath = libPath.substring(1, splitIndex);
+ final File libDir = new File(toDir, libDirPath);
+ if (!libDir.exists()) {
+ NativeLibraryHelper.createNativeLibrarySubdir(libDir);
+ }
+ final String archDirPath = libPath.substring(splitIndex + 1);
+ NativeLibraryHelper.createNativeLibrarySubdir(
+ new File(libDir, archDirPath));
+ }
+ }
+ linkFiles(fromFiles, toDir, mInheritedFilesBase);
+ } else {
+ // TODO: this should delegate to DCS so the system process
+ // avoids holding open FDs into containers.
+ copyFiles(fromFiles, toDir);
+ }
+ } catch (IOException e) {
+ throw new PackageManagerException(INSTALL_FAILED_INSUFFICIENT_STORAGE,
+ "Failed to inherit existing install", e);
+ }
+ }
+ }
+
+ private void parseApkAndExtractNativeLibraries() throws PackageManagerException {
+ synchronized (mLock) {
+ if (mRelinquished) {
+ throw new PackageManagerException(INSTALL_FAILED_INTERNAL_ERROR,
+ "Session relinquished");
+ }
+ if (mDestroyed) {
+ throw new PackageManagerException(INSTALL_FAILED_INTERNAL_ERROR,
+ "Session destroyed");
+ }
+ if (!mSealed) {
+ throw new PackageManagerException(INSTALL_FAILED_INTERNAL_ERROR,
+ "Session not sealed");
+ }
+ Objects.requireNonNull(mPackageName);
+ Objects.requireNonNull(mSigningDetails);
+ Objects.requireNonNull(mResolvedBaseFile);
+ final PackageLite result;
+ if (!isApexSession()) {
+ // For mode inherit existing, it would link/copy existing files to stage dir in
+ // prepareInheritedFiles(). Therefore, we need to parse the complete package in
+ // stage dir here.
+ // Besides, PackageLite may be null for staged sessions that don't complete
+ // pre-reboot verification.
+ result = getOrParsePackageLiteLocked(stageDir, /* flags */ 0);
+ } else {
+ result = getOrParsePackageLiteLocked(mResolvedBaseFile, /* flags */ 0);
+ }
+ if (result != null) {
+ mPackageLite = result;
+ if (!isApexSession()) {
+ synchronized (mProgressLock) {
+ mInternalProgress = 0.5f;
+ computeProgressLocked(true);
+ }
+ extractNativeLibraries(
+ mPackageLite, stageDir, params.abiOverride, mayInheritNativeLibs());
+ }
+ }
+ }
+ }
+
private void verifyNonStaged()
throws PackageManagerException {
final VerificationParams verifyingSession = prepareForVerification();
@@ -2501,19 +2622,6 @@
throw new PackageManagerException(INSTALL_FAILED_INTERNAL_ERROR,
"Session not sealed");
}
- PackageLite result = parseApkLite();
- if (result != null) {
- mPackageLite = result;
- if (!isApexSession()) {
- synchronized (mProgressLock) {
- mInternalProgress = 0.5f;
- computeProgressLocked(true);
- }
-
- extractNativeLibraries(
- mPackageLite, stageDir, params.abiOverride, mayInheritNativeLibs());
- }
- }
return makeVerificationParamsLocked();
}
}
@@ -2533,82 +2641,6 @@
closeInternal(false);
}
- /**
- * Prepares staged directory with any inherited APKs and returns the parsed package.
- */
- @GuardedBy("mLock")
- @Nullable
- private PackageLite parseApkLite() throws PackageManagerException {
-
-
- if (isMultiPackage()) {
- return null;
- }
- Objects.requireNonNull(mPackageName);
- Objects.requireNonNull(mSigningDetails);
- Objects.requireNonNull(mResolvedBaseFile);
-
- // Inherit any packages and native libraries from existing install that
- // haven't been overridden.
- if (!isApexSession() && params.mode == SessionParams.MODE_INHERIT_EXISTING) {
- try {
- final List<File> fromFiles = mResolvedInheritedFiles;
- final File toDir = stageDir;
-
- if (LOGD) Slog.d(TAG, "Inherited files: " + mResolvedInheritedFiles);
- if (!mResolvedInheritedFiles.isEmpty() && mInheritedFilesBase == null) {
- throw new IllegalStateException("mInheritedFilesBase == null");
- }
-
- if (isLinkPossible(fromFiles, toDir)) {
- if (!mResolvedInstructionSets.isEmpty()) {
- final File oatDir = new File(toDir, "oat");
- createOatDirs(mResolvedInstructionSets, oatDir);
- }
- // pre-create lib dirs for linking if necessary
- if (!mResolvedNativeLibPaths.isEmpty()) {
- for (String libPath : mResolvedNativeLibPaths) {
- // "/lib/arm64" -> ["lib", "arm64"]
- final int splitIndex = libPath.lastIndexOf('/');
- if (splitIndex < 0 || splitIndex >= libPath.length() - 1) {
- Slog.e(TAG,
- "Skipping native library creation for linking due"
- + " to invalid path: " + libPath);
- continue;
- }
- final String libDirPath = libPath.substring(1, splitIndex);
- final File libDir = new File(toDir, libDirPath);
- if (!libDir.exists()) {
- NativeLibraryHelper.createNativeLibrarySubdir(libDir);
- }
- final String archDirPath = libPath.substring(splitIndex + 1);
- NativeLibraryHelper.createNativeLibrarySubdir(
- new File(libDir, archDirPath));
- }
- }
- linkFiles(fromFiles, toDir, mInheritedFilesBase);
- } else {
- // TODO: this should delegate to DCS so the system process
- // avoids holding open FDs into containers.
- copyFiles(fromFiles, toDir);
- }
- } catch (IOException e) {
- throw new PackageManagerException(INSTALL_FAILED_INSUFFICIENT_STORAGE,
- "Failed to inherit existing install", e);
- }
- }
-
- if (!isApexSession()) {
- // For mode inherit existing, it would link/copy existing files to stage dir in the
- // above block. Therefore, we need to parse the complete package in stage dir here.
- // Besides, PackageLite may be null for staged sessions that don't complete
- // pre-reboot verification.
- return getOrParsePackageLiteLocked(stageDir, /* flags */ 0);
- } else {
- return getOrParsePackageLiteLocked(mResolvedBaseFile, /* flags */ 0);
- }
- }
-
@GuardedBy("mLock")
@Nullable
/**
@@ -2659,7 +2691,12 @@
// staged session or not. For a staged session, we will hand it over to the staging
// manager to complete the installation.
if (isStaged()) {
- mStagingManager.commitSession(mStagedSession);
+ mSessionProvider.getSessionVerifier().verifyStaged(mStagedSession, (error, msg) -> {
+ mStagedSession.notifyEndPreRebootVerification();
+ if (error == SessionInfo.STAGED_SESSION_NO_ERROR) {
+ mStagingManager.commitSession(mStagedSession);
+ }
+ });
return;
}
diff --git a/services/core/java/com/android/server/pm/PackageManagerService.java b/services/core/java/com/android/server/pm/PackageManagerService.java
index 3eaa26e..3d916ae4 100644
--- a/services/core/java/com/android/server/pm/PackageManagerService.java
+++ b/services/core/java/com/android/server/pm/PackageManagerService.java
@@ -142,7 +142,6 @@
import android.content.pm.overlay.OverlayPaths;
import android.content.pm.parsing.ParsingPackageUtils;
import android.content.pm.parsing.component.ParsedActivity;
-import android.content.pm.parsing.component.ParsedActivityImpl;
import android.content.pm.parsing.component.ParsedInstrumentation;
import android.content.pm.parsing.component.ParsedIntentInfo;
import android.content.pm.parsing.component.ParsedMainComponent;
@@ -4875,7 +4874,7 @@
return;
}
} else {
- if (isInstantApp(packageName, callingUserId)) {
+ if (isInstantAppInternal(packageName, callingUserId, Process.SYSTEM_UID)) {
return;
}
}
@@ -4982,7 +4981,8 @@
public void reconcileSecondaryDexFiles(String packageName) {
if (getInstantAppPackageName(Binder.getCallingUid()) != null) {
return;
- } else if (isInstantApp(packageName, UserHandle.getCallingUserId())) {
+ } else if (isInstantAppInternal(
+ packageName, UserHandle.getCallingUserId(), Process.SYSTEM_UID)) {
return;
}
mDexManager.reconcileSecondaryDexFiles(packageName);
@@ -6597,7 +6597,8 @@
if (DEBUG_BACKUP) {
Slog.i(TAG, "Package " + packageName + " sending normal FIRST_LAUNCH");
}
- final boolean isInstantApp = isInstantApp(packageName, userId);
+ final boolean isInstantApp = isInstantAppInternal(
+ packageName, userId, Process.SYSTEM_UID);
final int[] userIds = isInstantApp ? EMPTY_INT_ARRAY : new int[] { userId };
final int[] instantUserIds = isInstantApp ? new int[] { userId } : EMPTY_INT_ARRAY;
mBroadcastHelper.sendFirstLaunchBroadcast(
@@ -7992,7 +7993,7 @@
void sendPackageChangedBroadcast(String packageName,
boolean dontKillApp, ArrayList<String> componentNames, int packageUid, String reason) {
final int userId = UserHandle.getUserId(packageUid);
- final boolean isInstantApp = isInstantApp(packageName, userId);
+ final boolean isInstantApp = isInstantAppInternal(packageName, userId, Process.SYSTEM_UID);
final int[] userIds = isInstantApp ? EMPTY_INT_ARRAY : new int[] { userId };
final int[] instantUserIds = isInstantApp ? new int[] { userId } : EMPTY_INT_ARRAY;
final SparseArray<int[]> broadcastAllowList = getBroadcastAllowList(
@@ -8914,7 +8915,8 @@
* return {@code true} if any one application belongs to the shared user ID meets the criteria.
*/
boolean canQueryPackage(int callingUid, @Nullable String targetPackageName) {
- if (targetPackageName == null) {
+ // Since getSettingLPr returns null for ROOT_UID, add an extra check for it here.
+ if (callingUid == Process.ROOT_UID || targetPackageName == null) {
return true;
}
synchronized (mLock) {
@@ -10006,7 +10008,7 @@
if (ps == null) {
return null;
}
- return ps.getIncrementalStatesInfo();
+ return new IncrementalStatesInfo(ps.isPackageLoading(), ps.getLoadingProgress());
}
@Override
@@ -10340,7 +10342,7 @@
throw new SecurityException(
"Caller uid " + callingUid + " does not own package " + packageName);
}
- if (isInstantAppInternal(packageName, userId, callingUid)) {
+ if (isInstantAppInternal(packageName, userId, Process.SYSTEM_UID)) {
return false;
}
final AndroidPackage pkg;
diff --git a/services/core/java/com/android/server/pm/PackageSessionProvider.java b/services/core/java/com/android/server/pm/PackageSessionProvider.java
index af11e77..ad5cf13 100644
--- a/services/core/java/com/android/server/pm/PackageSessionProvider.java
+++ b/services/core/java/com/android/server/pm/PackageSessionProvider.java
@@ -16,7 +16,10 @@
package com.android.server.pm;
-/** Provides access to individual sessions managed by the install service */
+/**
+ * Provides access to individual sessions managed by the install service as well as utilities
+ * used by the install process.
+ */
public interface PackageSessionProvider {
/**
@@ -25,4 +28,5 @@
*/
PackageInstallerSession getSession(int sessionId);
+ PackageSessionVerifier getSessionVerifier();
}
diff --git a/services/core/java/com/android/server/pm/PackageSessionVerifier.java b/services/core/java/com/android/server/pm/PackageSessionVerifier.java
new file mode 100644
index 0000000..3f5410d
--- /dev/null
+++ b/services/core/java/com/android/server/pm/PackageSessionVerifier.java
@@ -0,0 +1,485 @@
+/*
+ * Copyright (C) 2021 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;
+
+import android.apex.ApexInfo;
+import android.apex.ApexInfoList;
+import android.apex.ApexSessionInfo;
+import android.apex.ApexSessionParams;
+import android.content.Context;
+import android.content.pm.PackageInfo;
+import android.content.pm.PackageInstaller.SessionInfo;
+import android.content.pm.PackageManager;
+import android.content.pm.PackageManagerInternal;
+import android.content.pm.SigningDetails;
+import android.content.pm.parsing.PackageInfoWithoutStateUtils;
+import android.content.pm.parsing.result.ParseResult;
+import android.content.pm.parsing.result.ParseTypeImpl;
+import android.content.rollback.RollbackInfo;
+import android.content.rollback.RollbackManager;
+import android.os.Handler;
+import android.os.Looper;
+import android.os.RemoteException;
+import android.util.IntArray;
+import android.util.Slog;
+import android.util.apk.ApkSignatureVerifier;
+
+import com.android.internal.content.PackageHelper;
+import com.android.server.LocalServices;
+import com.android.server.pm.parsing.PackageParser2;
+import com.android.server.pm.parsing.pkg.ParsedPackage;
+import com.android.server.rollback.RollbackManagerInternal;
+
+import java.io.File;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.function.Supplier;
+
+final class PackageSessionVerifier {
+ private static final String TAG = "PackageSessionVerifier";
+
+ interface Callback {
+ void onResult(int returnCode, String msg);
+ }
+
+ private final Context mContext;
+ private final PackageManagerService mPm;
+ private final ApexManager mApexManager;
+ private final Supplier<PackageParser2> mPackageParserSupplier;
+ // The handler thread to run verification tasks. Since all tasks run in the same thread,
+ // there is no need for synchronization.
+ private final Handler mHandler;
+ // Parent sessions for checking session conflicts.
+ private final List<StagingManager.StagedSession> mStagedSessions = new ArrayList<>();
+
+ PackageSessionVerifier(Context context, PackageManagerService pm,
+ ApexManager apexManager, Supplier<PackageParser2> packageParserSupplier,
+ Looper looper) {
+ mContext = context;
+ mPm = pm;
+ mApexManager = apexManager;
+ mPackageParserSupplier = packageParserSupplier;
+ mHandler = new Handler(looper);
+ }
+
+ /**
+ * Starts pre-reboot verification for the staged-session. This operation is broken into the
+ * following phases:
+ * <ul>
+ * <li>Checks if multiple active sessions are supported.</li>
+ * <li>Checks conflicts in rollbacks and overlapping packages.</li>
+ * <li>Submits apex sessions to apex service.</li>
+ * <li>Validates signatures of apex files.</li>
+ * <li>Notifies the result of verification.</li>
+ * </ul>
+ *
+ * Note it is the responsibility of the caller to ensure the staging files remain unchanged
+ * while the verification is in progress.
+ */
+ void verifyStaged(StagingManager.StagedSession session, Callback callback) {
+ Slog.d(TAG, "Starting preRebootVerification for session " + session.sessionId());
+ mHandler.post(() -> {
+ try {
+ storeSession(session);
+ checkActiveSessions();
+ checkRollbacks(session);
+ if (session.isMultiPackage()) {
+ for (StagingManager.StagedSession child : session.getChildSessions()) {
+ checkOverlaps(session, child);
+ }
+ } else {
+ checkOverlaps(session, session);
+ }
+ dispatchVerifyApex(session, callback);
+ } catch (PackageManagerException e) {
+ onVerificationFailure(session, callback, e.error, e.getMessage());
+ }
+ });
+ }
+
+ /**
+ * Stores staged-sessions for checking package overlapping and rollback conflicts.
+ */
+ private void storeSession(StagingManager.StagedSession session) {
+ mStagedSessions.add(session);
+ }
+
+ private void onVerificationSuccess(StagingManager.StagedSession session, Callback callback) {
+ callback.onResult(SessionInfo.STAGED_SESSION_NO_ERROR, null);
+ }
+
+ private void onVerificationFailure(StagingManager.StagedSession session, Callback callback,
+ @SessionInfo.StagedSessionErrorCode int errorCode, String errorMessage) {
+ if (!ensureActiveApexSessionIsAborted(session)) {
+ Slog.e(TAG, "Failed to abort apex session " + session.sessionId());
+ // Safe to ignore active apex session abortion failure since session will be marked
+ // failed on next step and staging directory for session will be deleted.
+ }
+ session.setSessionFailed(errorCode, errorMessage);
+ callback.onResult(errorCode, errorMessage);
+ }
+
+ private void dispatchVerifyApex(StagingManager.StagedSession session, Callback callback) {
+ mHandler.post(() -> {
+ try {
+ verifyApex(session);
+ dispatchEndVerification(session, callback);
+ } catch (PackageManagerException e) {
+ onVerificationFailure(session, callback, e.error, e.getMessage());
+ }
+ });
+ }
+
+ private void dispatchEndVerification(StagingManager.StagedSession session, Callback callback) {
+ mHandler.post(() -> {
+ try {
+ endVerification(session);
+ onVerificationSuccess(session, callback);
+ } catch (PackageManagerException e) {
+ onVerificationFailure(session, callback, e.error, e.getMessage());
+ }
+ });
+ }
+
+ /**
+ * Pre-reboot verification phase for apex files:
+ *
+ * <p><ul>
+ * <li>submits session to apex service</li>
+ * <li>validates signatures of apex files</li>
+ * </ul></p>
+ */
+ private void verifyApex(StagingManager.StagedSession session) throws PackageManagerException {
+ int rollbackId = -1;
+ if ((session.sessionParams().installFlags & PackageManager.INSTALL_ENABLE_ROLLBACK) != 0) {
+ // If rollback is enabled for this session, we call through to the RollbackManager
+ // with the list of sessions it must enable rollback for. Note that
+ // notifyStagedSession is a synchronous operation.
+ final RollbackManagerInternal rm =
+ LocalServices.getService(RollbackManagerInternal.class);
+ try {
+ // NOTE: To stay consistent with the non-staged install flow, we don't fail the
+ // entire install if rollbacks can't be enabled.
+ rollbackId = rm.notifyStagedSession(session.sessionId());
+ } catch (RuntimeException re) {
+ Slog.e(TAG, "Failed to notifyStagedSession for session: "
+ + session.sessionId(), re);
+ }
+ } else if (isRollback(session)) {
+ rollbackId = retrieveRollbackIdForCommitSession(session.sessionId());
+ }
+
+ final boolean hasApex = session.containsApexSession();
+ // APEX checks. For single-package sessions, check if they contain an APEX. For
+ // multi-package sessions, find all the child sessions that contain an APEX.
+ if (hasApex) {
+ final List<PackageInfo> apexPackages = submitSessionToApexService(session, rollbackId);
+ for (int i = 0, size = apexPackages.size(); i < size; i++) {
+ validateApexSignature(apexPackages.get(i));
+ }
+ final PackageManagerInternal packageManagerInternal =
+ LocalServices.getService(PackageManagerInternal.class);
+ packageManagerInternal.pruneCachedApksInApex(apexPackages);
+ }
+ }
+
+ /**
+ * Pre-reboot verification phase for wrapping up:
+ * <p><ul>
+ * <li>enables checkpoint if supported</li>
+ * <li>marks session as ready</li>
+ * </ul></p>
+ */
+ private void endVerification(StagingManager.StagedSession session)
+ throws PackageManagerException {
+ // Before marking the session as ready, start checkpoint service if available
+ try {
+ if (PackageHelper.getStorageManager().supportsCheckpoint()) {
+ PackageHelper.getStorageManager().startCheckpoint(2);
+ }
+ } catch (Exception e) {
+ // Failed to get hold of StorageManager
+ Slog.e(TAG, "Failed to get hold of StorageManager", e);
+ throw new PackageManagerException(
+ SessionInfo.STAGED_SESSION_UNKNOWN,
+ "Failed to get hold of StorageManager");
+ }
+ // Proactively mark session as ready before calling apexd. Although this call order
+ // looks counter-intuitive, this is the easiest way to ensure that session won't end up
+ // in the inconsistent state:
+ // - If device gets rebooted right before call to apexd, then apexd will never activate
+ // apex files of this staged session. This will result in StagingManager failing
+ // the session.
+ // On the other hand, if the order of the calls was inverted (first call apexd, then
+ // mark session as ready), then if a device gets rebooted right after the call to apexd,
+ // only apex part of the train will be applied, leaving device in an inconsistent state.
+ Slog.d(TAG, "Marking session " + session.sessionId() + " as ready");
+ session.setSessionReady();
+ if (session.isSessionReady()) {
+ final boolean hasApex = session.containsApexSession();
+ if (hasApex) {
+ mApexManager.markStagedSessionReady(session.sessionId());
+ }
+ }
+ }
+
+ /**
+ * Validates the signature used to sign the container of the new apex package
+ *
+ * @param newApexPkg The new apex package that is being installed
+ */
+ private void validateApexSignature(PackageInfo newApexPkg) throws PackageManagerException {
+ // Get signing details of the new package
+ final String apexPath = newApexPkg.applicationInfo.sourceDir;
+ final String packageName = newApexPkg.packageName;
+ int minSignatureScheme = ApkSignatureVerifier.getMinimumSignatureSchemeVersionForTargetSdk(
+ newApexPkg.applicationInfo.targetSdkVersion);
+
+ final ParseTypeImpl input = ParseTypeImpl.forDefaultParsing();
+ final ParseResult<SigningDetails> newResult = ApkSignatureVerifier.verify(
+ input.reset(), apexPath, minSignatureScheme);
+ if (newResult.isError()) {
+ throw new PackageManagerException(SessionInfo.STAGED_SESSION_VERIFICATION_FAILED,
+ "Failed to parse APEX package " + apexPath + " : "
+ + newResult.getException(), newResult.getException());
+ }
+ final SigningDetails newSigningDetails = newResult.getResult();
+
+ // Get signing details of the existing package
+ final PackageInfo existingApexPkg = mApexManager.getPackageInfo(packageName,
+ ApexManager.MATCH_ACTIVE_PACKAGE);
+ if (existingApexPkg == null) {
+ // This should never happen, because submitSessionToApexService ensures that no new
+ // apexes were installed.
+ throw new IllegalStateException("Unknown apex package " + packageName);
+ }
+
+ final ParseResult<SigningDetails> existingResult = ApkSignatureVerifier.verify(
+ input.reset(), existingApexPkg.applicationInfo.sourceDir,
+ SigningDetails.SignatureSchemeVersion.JAR);
+ if (existingResult.isError()) {
+ throw new PackageManagerException(SessionInfo.STAGED_SESSION_VERIFICATION_FAILED,
+ "Failed to parse APEX package " + existingApexPkg.applicationInfo.sourceDir
+ + " : " + existingResult.getException(), existingResult.getException());
+ }
+ final SigningDetails existingSigningDetails = existingResult.getResult();
+
+ // Verify signing details for upgrade
+ if (newSigningDetails.checkCapability(existingSigningDetails,
+ SigningDetails.CertCapabilities.INSTALLED_DATA)
+ || existingSigningDetails.checkCapability(newSigningDetails,
+ SigningDetails.CertCapabilities.ROLLBACK)) {
+ return;
+ }
+
+ throw new PackageManagerException(SessionInfo.STAGED_SESSION_VERIFICATION_FAILED,
+ "APK-container signature of APEX package " + packageName + " with version "
+ + newApexPkg.versionCodeMajor + " and path " + apexPath + " is not"
+ + " compatible with the one currently installed on device");
+ }
+
+ private List<PackageInfo> submitSessionToApexService(StagingManager.StagedSession session,
+ int rollbackId) throws PackageManagerException {
+ final IntArray childSessionIds = new IntArray();
+ if (session.isMultiPackage()) {
+ for (StagingManager.StagedSession s : session.getChildSessions()) {
+ if (s.isApexSession()) {
+ childSessionIds.add(s.sessionId());
+ }
+ }
+ }
+ ApexSessionParams apexSessionParams = new ApexSessionParams();
+ apexSessionParams.sessionId = session.sessionId();
+ apexSessionParams.childSessionIds = childSessionIds.toArray();
+ if (session.sessionParams().installReason == PackageManager.INSTALL_REASON_ROLLBACK) {
+ apexSessionParams.isRollback = true;
+ apexSessionParams.rollbackId = rollbackId;
+ } else {
+ if (rollbackId != -1) {
+ apexSessionParams.hasRollbackEnabled = true;
+ apexSessionParams.rollbackId = rollbackId;
+ }
+ }
+ // submitStagedSession will throw a PackageManagerException if apexd verification fails,
+ // which will be propagated to populate stagedSessionErrorMessage of this session.
+ final ApexInfoList apexInfoList = mApexManager.submitStagedSession(apexSessionParams);
+ final List<PackageInfo> result = new ArrayList<>();
+ final List<String> apexPackageNames = new ArrayList<>();
+ for (ApexInfo apexInfo : apexInfoList.apexInfos) {
+ final PackageInfo packageInfo;
+ final int flags = PackageManager.GET_META_DATA;
+ try (PackageParser2 packageParser = mPackageParserSupplier.get()) {
+ File apexFile = new File(apexInfo.modulePath);
+ final ParsedPackage parsedPackage = packageParser.parsePackage(
+ apexFile, flags, false);
+ packageInfo = PackageInfoWithoutStateUtils.generate(parsedPackage, apexInfo, flags);
+ if (packageInfo == null) {
+ throw new PackageManagerException(
+ SessionInfo.STAGED_SESSION_VERIFICATION_FAILED,
+ "Unable to generate package info: " + apexInfo.modulePath);
+ }
+ } catch (PackageManagerException e) {
+ throw new PackageManagerException(SessionInfo.STAGED_SESSION_VERIFICATION_FAILED,
+ "Failed to parse APEX package " + apexInfo.modulePath + " : " + e, e);
+ }
+ result.add(packageInfo);
+ apexPackageNames.add(packageInfo.packageName);
+ }
+ Slog.d(TAG, "Session " + session.sessionId() + " has following APEX packages: "
+ + apexPackageNames);
+ return result;
+ }
+
+ private int retrieveRollbackIdForCommitSession(int sessionId) throws PackageManagerException {
+ RollbackManager rm = mContext.getSystemService(RollbackManager.class);
+
+ final List<RollbackInfo> rollbacks = rm.getRecentlyCommittedRollbacks();
+ for (int i = 0, size = rollbacks.size(); i < size; i++) {
+ final RollbackInfo rollback = rollbacks.get(i);
+ if (rollback.getCommittedSessionId() == sessionId) {
+ return rollback.getRollbackId();
+ }
+ }
+ throw new PackageManagerException(
+ SessionInfo.STAGED_SESSION_VERIFICATION_FAILED,
+ "Could not find rollback id for commit session: " + sessionId);
+ }
+
+ private static boolean isRollback(StagingManager.StagedSession session) {
+ return session.sessionParams().installReason == PackageManager.INSTALL_REASON_ROLLBACK;
+ }
+
+ private static boolean isApexSessionFinalized(ApexSessionInfo info) {
+ /* checking if the session is in a final state, i.e., not active anymore */
+ return info.isUnknown || info.isActivationFailed || info.isSuccess
+ || info.isReverted;
+ }
+
+ private boolean ensureActiveApexSessionIsAborted(StagingManager.StagedSession session) {
+ if (!session.containsApexSession()) {
+ return true;
+ }
+ final int sessionId = session.sessionId();
+ final ApexSessionInfo apexSession = mApexManager.getStagedSessionInfo(sessionId);
+ if (apexSession == null || isApexSessionFinalized(apexSession)) {
+ return true;
+ }
+ return mApexManager.abortStagedSession(sessionId);
+ }
+
+ /**
+ * Checks if multiple staged-sessions are supported. It is supported only when the system
+ * supports checkpoint.
+ */
+ private void checkActiveSessions() throws PackageManagerException {
+ final boolean supportsCheckpoint;
+ try {
+ supportsCheckpoint = PackageHelper.getStorageManager().supportsCheckpoint();
+ } catch (RemoteException e) {
+ throw new PackageManagerException(SessionInfo.STAGED_SESSION_VERIFICATION_FAILED,
+ "Can't query fs-checkpoint status : " + e);
+ }
+ int activeSessions = 0;
+ for (StagingManager.StagedSession stagedSession : mStagedSessions) {
+ if (stagedSession.isDestroyed() || stagedSession.isInTerminalState()) {
+ continue;
+ }
+ ++activeSessions;
+ }
+ if (!supportsCheckpoint && activeSessions > 1) {
+ throw new PackageManagerException(
+ SessionInfo.STAGED_SESSION_VERIFICATION_FAILED,
+ "Cannot stage multiple sessions without checkpoint support");
+ }
+ }
+
+ /**
+ * Fails non-rollback sessions if any rollback session exists. A rollback session might cause
+ * downgrade of SDK extension which in turn will result in dependency violation of other
+ * non-rollback sessions.
+ */
+ private void checkRollbacks(StagingManager.StagedSession session)
+ throws PackageManagerException {
+ for (StagingManager.StagedSession stagedSession : mStagedSessions) {
+ if (stagedSession.isDestroyed() || stagedSession.isInTerminalState()) {
+ continue;
+ }
+ if (isRollback(session) && !isRollback(stagedSession)) {
+ // If the new session is a rollback, then it gets priority. The existing
+ // session is failed to reduce risk and avoid an SDK extension dependency
+ // violation.
+ if (!ensureActiveApexSessionIsAborted(stagedSession)) {
+ Slog.e(TAG, "Failed to abort apex session " + stagedSession.sessionId());
+ // Safe to ignore active apex session abort failure since session
+ // will be marked failed on next step and staging directory for session
+ // will be deleted.
+ }
+ stagedSession.setSessionFailed(
+ SessionInfo.STAGED_SESSION_CONFLICT,
+ "Session was failed by rollback session: " + session.sessionId());
+ Slog.i(TAG, "Session " + stagedSession.sessionId() + " is marked failed due to "
+ + "rollback session: " + session.sessionId());
+ } else if (!isRollback(session) && isRollback(stagedSession)) {
+ throw new PackageManagerException(
+ SessionInfo.STAGED_SESSION_CONFLICT,
+ "Session was failed by rollback session: " + stagedSession.sessionId());
+
+ }
+ }
+ }
+
+ /**
+ * Fails the session that is committed later when overlapping packages are detected.
+ *
+ * @param parent The parent session.
+ * @param child The child session whose package name will be checked.
+ * This will equal to {@code parent} for a single-package session.
+ */
+ private void checkOverlaps(StagingManager.StagedSession parent,
+ StagingManager.StagedSession child) throws PackageManagerException {
+ final String packageName = child.getPackageName();
+ if (packageName == null) {
+ throw new PackageManagerException(
+ SessionInfo.STAGED_SESSION_VERIFICATION_FAILED,
+ "Cannot stage session " + child.sessionId() + " with package name null");
+ }
+ for (StagingManager.StagedSession stagedSession : mStagedSessions) {
+ if (stagedSession.isDestroyed() || stagedSession.isInTerminalState()
+ || stagedSession.sessionId() == parent.sessionId()) {
+ continue;
+ }
+ if (stagedSession.sessionContains(s -> packageName.equals(s.getPackageName()))) {
+ if (stagedSession.getCommittedMillis() < parent.getCommittedMillis()) {
+ // Fail the session committed later when there are overlapping packages
+ throw new PackageManagerException(
+ SessionInfo.STAGED_SESSION_VERIFICATION_FAILED,
+ "Package: " + packageName + " in session: "
+ + child.sessionId()
+ + " has been staged already by session: "
+ + stagedSession.sessionId());
+ } else {
+ stagedSession.setSessionFailed(
+ SessionInfo.STAGED_SESSION_VERIFICATION_FAILED,
+ "Package: " + packageName + " in session: "
+ + stagedSession.sessionId()
+ + " has been staged already by session: "
+ + child.sessionId());
+ }
+ }
+ }
+ }
+}
diff --git a/services/core/java/com/android/server/pm/PackageSetting.java b/services/core/java/com/android/server/pm/PackageSetting.java
index 1a5415c..b8e354e 100644
--- a/services/core/java/com/android/server/pm/PackageSetting.java
+++ b/services/core/java/com/android/server/pm/PackageSetting.java
@@ -25,7 +25,6 @@
import android.annotation.UserIdInt;
import android.content.ComponentName;
import android.content.pm.ApplicationInfo;
-import android.content.pm.IncrementalStatesInfo;
import android.content.pm.PackageManager;
import android.content.pm.SharedLibraryInfo;
import android.content.pm.SigningDetails;
@@ -36,7 +35,6 @@
import android.content.pm.pkg.PackageUserState;
import android.content.pm.pkg.PackageUserStateInternal;
import android.os.PersistableBundle;
-import android.os.incremental.IncrementalManager;
import android.service.pm.PackageProto;
import android.util.ArrayMap;
import android.util.ArraySet;
@@ -66,8 +64,8 @@
import java.util.Map;
import java.util.Objects;
import java.util.Set;
-import java.util.function.Predicate;
import java.util.UUID;
+import java.util.function.Predicate;
/**
* Settings data for a particular package we know about.
@@ -103,9 +101,6 @@
@Nullable
Set<String> mOldCodePaths;
- @NonNull
- private IncrementalStates incrementalStates;
-
@Nullable
String[] usesStaticLibraries;
@@ -153,6 +148,8 @@
@NonNull
private String mPathString;
+ private float mLoadingProgress;
+
@Nullable
private String mPrimaryCpuAbi;
@@ -183,6 +180,7 @@
// TODO: Access is not locked.
// Whether this package is currently stopped, thus can not be
// started until explicitly launched by the user.
+ @NonNull
private final SparseArray<PackageUserStateInternalImpl> mUserState = new SparseArray<>();
@NonNull
@@ -242,7 +240,6 @@
this.versionCode = longVersionCode;
this.signatures = new PackageSignatures();
this.installSource = InstallSource.EMPTY;
- this.incrementalStates = new IncrementalStates();
this.sharedUserId = sharedUserId;
mDomainSetId = domainSetId;
copyMimeGroups(mimeGroups);
@@ -614,7 +611,7 @@
super.copySettingBase(other);
sharedUserId = other.sharedUserId;
mimeGroups = other.mimeGroups;
- incrementalStates = other.incrementalStates;
+ mLoadingProgress = other.mLoadingProgress;
legacyNativeLibraryPath = other.legacyNativeLibraryPath;
mName = other.mName;
mRealName = other.mRealName;
@@ -708,6 +705,7 @@
void setInstalled(boolean inst, int userId) {
modifyUserState(userId).setInstalled(inst);
+ onChanged();
}
boolean getInstalled(int userId) {
@@ -720,6 +718,7 @@
void setInstallReason(int installReason, int userId) {
modifyUserState(userId).setInstallReason(installReason);
+ onChanged();
}
int getUninstallReason(int userId) {
@@ -728,10 +727,15 @@
void setUninstallReason(@PackageManager.UninstallReason int uninstallReason, int userId) {
modifyUserState(userId).setUninstallReason(uninstallReason);
+ onChanged();
}
boolean setOverlayPaths(OverlayPaths overlayPaths, int userId) {
- return modifyUserState(userId).setOverlayPaths(overlayPaths);
+ boolean changed = modifyUserState(userId).setOverlayPaths(overlayPaths);
+ if (changed) {
+ onChanged();
+ }
+ return changed;
}
@NonNull
@@ -740,7 +744,10 @@
}
boolean setOverlayPathsForLibrary(String libName, OverlayPaths overlayPaths, int userId) {
- return modifyUserState(userId).setSharedLibraryOverlayPaths(libName, overlayPaths);
+ boolean changed = modifyUserState(userId)
+ .setSharedLibraryOverlayPaths(libName, overlayPaths);
+ onChanged();
+ return changed;
}
@NonNull
@@ -787,6 +794,7 @@
void setCeDataInode(long ceDataInode, int userId) {
modifyUserState(userId).setCeDataInode(ceDataInode);
+ onChanged();
}
boolean getStopped(int userId) {
@@ -795,6 +803,7 @@
void setStopped(boolean stop, int userId) {
modifyUserState(userId).setStopped(stop);
+ onChanged();
}
boolean getNotLaunched(int userId) {
@@ -803,6 +812,7 @@
void setNotLaunched(boolean stop, int userId) {
modifyUserState(userId).setNotLaunched(stop);
+ onChanged();
}
boolean getHidden(int userId) {
@@ -811,6 +821,7 @@
void setHidden(boolean hidden, int userId) {
modifyUserState(userId).setHidden(hidden);
+ onChanged();
}
int getDistractionFlags(int userId) {
@@ -819,6 +830,7 @@
void setDistractionFlags(int distractionFlags, int userId) {
modifyUserState(userId).setDistractionFlags(distractionFlags);
+ onChanged();
}
boolean getSuspended(int userId) {
@@ -886,6 +898,7 @@
void setInstantApp(boolean instantApp, int userId) {
modifyUserState(userId).setInstantApp(instantApp);
+ onChanged();
}
boolean getVirtualPreload(int userId) {
@@ -894,6 +907,7 @@
void setVirtualPreload(boolean virtualPreload, int userId) {
modifyUserState(userId).setVirtualPreload(virtualPreload);
+ onChanged();
}
void setUserState(int userId, long ceDataInode, int enabled, boolean installed, boolean stopped,
@@ -948,20 +962,24 @@
void setEnabledComponents(ArraySet<String> components, int userId) {
modifyUserState(userId).setEnabledComponents(components);
+ onChanged();
}
void setDisabledComponents(ArraySet<String> components, int userId) {
modifyUserState(userId).setDisabledComponents(components);
+ onChanged();
}
void setEnabledComponentsCopy(ArraySet<String> components, int userId) {
modifyUserState(userId).setEnabledComponents(components != null
? new ArraySet<String>(components) : null);
+ onChanged();
}
void setDisabledComponentsCopy(ArraySet<String> components, int userId) {
modifyUserState(userId).setDisabledComponents(components != null
? new ArraySet<String>(components) : null);
+ onChanged();
}
PackageUserStateInternalImpl modifyUserStateComponents(int userId, boolean disabled,
@@ -985,11 +1003,13 @@
void addDisabledComponent(String componentClassName, int userId) {
modifyUserStateComponents(userId, true, false)
.getDisabledComponentsNoCopy().add(componentClassName);
+ onChanged();
}
void addEnabledComponent(String componentClassName, int userId) {
modifyUserStateComponents(userId, false, true)
.getEnabledComponentsNoCopy().add(componentClassName);
+ onChanged();
}
boolean enableComponentLPw(String componentClassName, int userId) {
@@ -997,6 +1017,9 @@
boolean changed = state.getDisabledComponentsNoCopy() != null
? state.getDisabledComponentsNoCopy().remove(componentClassName) : false;
changed |= state.getEnabledComponentsNoCopy().add(componentClassName);
+ if (changed) {
+ onChanged();
+ }
return changed;
}
@@ -1005,6 +1028,9 @@
boolean changed = state.getEnabledComponentsNoCopy() != null
? state.getEnabledComponentsNoCopy().remove(componentClassName) : false;
changed |= state.getDisabledComponentsNoCopy().add(componentClassName);
+ if (changed) {
+ onChanged();
+ }
return changed;
}
@@ -1014,6 +1040,9 @@
? state.getDisabledComponentsNoCopy().remove(componentClassName) : false;
changed |= state.getEnabledComponentsNoCopy() != null
? state.getEnabledComponentsNoCopy().remove(componentClassName) : false;
+ if (changed) {
+ onChanged();
+ }
return changed;
}
@@ -1131,6 +1160,7 @@
PackageSetting setPath(@NonNull File path) {
this.mPath = path;
this.mPathString = path.toString();
+ onChanged();
return this;
}
@@ -1147,7 +1177,9 @@
@VisibleForTesting(visibility = VisibleForTesting.Visibility.PACKAGE)
public boolean overrideNonLocalizedLabelAndIcon(@NonNull ComponentName component,
@Nullable String label, @Nullable Integer icon, @UserIdInt int userId) {
- return modifyUserState(userId).overrideLabelAndIcon(component, label, icon);
+ boolean changed = modifyUserState(userId).overrideLabelAndIcon(component, label, icon);
+ onChanged();
+ return changed;
}
/**
@@ -1157,6 +1189,7 @@
*/
public void resetOverrideComponentLabelIcon(@UserIdInt int userId) {
modifyUserState(userId).resetOverrideComponentLabelIcon();
+ onChanged();
}
/**
@@ -1184,39 +1217,13 @@
* @return True if package is still being loaded, false if the package is fully loaded.
*/
public boolean isPackageLoading() {
- return incrementalStates.getIncrementalStatesInfo().isLoading();
+ return Math.abs(1.0f - mLoadingProgress) >= 0.00000001f;
}
- /**
- * @return all current states in a Parcelable.
- */
- public IncrementalStatesInfo getIncrementalStatesInfo() {
- return incrementalStates.getIncrementalStatesInfo();
- }
-
- /**
- * Called to indicate that the package installation has been committed. This will create a
- * new startable state and a new loading state with default values. By default, the package is
- * startable after commit. For a package installed on Incremental, the loading state is true.
- * For non-Incremental packages, the loading state is false.
- */
- public void setStatesOnCommit() {
- incrementalStates.onCommit(IncrementalManager.isIncrementalPath(getPathString()));
- }
-
- /**
- * Called to set the callback to listen for startable state changes.
- */
- public void setIncrementalStatesCallback(IncrementalStates.Callback callback) {
- incrementalStates.setCallback(callback);
- }
-
- /**
- * Called to report progress changes. This might trigger loading state change.
- * @see IncrementalStates#setProgress(float)
- */
- public void setLoadingProgress(float progress) {
- incrementalStates.setProgress(progress);
+ public PackageSetting setLoadingProgress(float progress) {
+ mLoadingProgress = progress;
+ onChanged();
+ return this;
}
@NonNull
@@ -1342,13 +1349,6 @@
return this;
}
- public PackageSetting setIncrementalStates(
- IncrementalStates incrementalStates) {
- this.incrementalStates = incrementalStates;
- onChanged();
- return this;
- }
-
// Code below generated by codegen v1.0.23.
@@ -1377,11 +1377,6 @@
return mOldCodePaths;
}
- @DataClass.Generated.Member
- public @NonNull IncrementalStates getIncrementalStates() {
- return incrementalStates;
- }
-
/**
* The path under which native libraries have been unpacked. This path is
* always derived at runtime, and is only stored here for cleanup when a
@@ -1438,6 +1433,11 @@
}
@DataClass.Generated.Member
+ public float getLoadingProgress() {
+ return mLoadingProgress;
+ }
+
+ @DataClass.Generated.Member
public @Nullable String getPrimaryCpuAbi() {
return mPrimaryCpuAbi;
}
@@ -1537,10 +1537,10 @@
}
@DataClass.Generated(
- time = 1628017546382L,
+ time = 1635295317317L,
codegenVersion = "1.0.23",
sourceFile = "frameworks/base/services/core/java/com/android/server/pm/PackageSetting.java",
- inputSignatures = "static final android.content.pm.PackageUserState DEFAULT_USER_STATE\nprotected int sharedUserId\n @android.annotation.Nullable java.util.Map<java.lang.String,android.util.ArraySet<java.lang.String>> mimeGroups\n @java.lang.Deprecated @android.annotation.Nullable java.util.Set<java.lang.String> mOldCodePaths\nprivate @android.annotation.NonNull com.android.server.pm.IncrementalStates incrementalStates\n @android.annotation.Nullable java.lang.String[] usesStaticLibraries\n @android.annotation.Nullable long[] usesStaticLibrariesVersions\nprivate @android.annotation.Nullable @java.lang.Deprecated java.lang.String legacyNativeLibraryPath\nprivate @android.annotation.NonNull java.lang.String mName\nprivate @android.annotation.NonNull java.lang.String mRealName\nprivate int mAppId\nprivate @android.annotation.Nullable com.android.server.pm.parsing.pkg.AndroidPackage pkg\nprivate @android.annotation.Nullable com.android.server.pm.SharedUserSetting sharedUser\nprivate @android.annotation.NonNull java.io.File mPath\nprivate @android.annotation.NonNull java.lang.String mPathString\nprivate @android.annotation.Nullable java.lang.String mPrimaryCpuAbi\nprivate @android.annotation.Nullable java.lang.String mSecondaryCpuAbi\nprivate @android.annotation.Nullable java.lang.String mCpuAbiOverride\nprivate long mLastModifiedTime\nprivate long firstInstallTime\nprivate long lastUpdateTime\nprivate long versionCode\nprivate @android.annotation.NonNull com.android.server.pm.PackageSignatures signatures\nprivate boolean installPermissionsFixed\nprivate @android.annotation.NonNull com.android.server.pm.PackageKeySetData keySetData\nprivate final @android.annotation.NonNull android.util.SparseArray<android.content.pm.PackageUserState> mUserState\nprivate @android.annotation.NonNull com.android.server.pm.InstallSource installSource\nprivate @android.annotation.Nullable java.lang.String volumeUuid\nprivate int categoryOverride\nprivate boolean updateAvailable\nprivate boolean forceQueryableOverride\nprivate @android.annotation.NonNull com.android.server.pm.pkg.PackageStateUnserialized pkgState\nprivate @android.annotation.NonNull java.util.UUID mDomainSetId\nprivate final @android.annotation.NonNull com.android.server.utils.SnapshotCache<com.android.server.pm.PackageSetting> mSnapshot\nprivate com.android.server.utils.SnapshotCache<com.android.server.pm.PackageSetting> makeCache()\npublic com.android.server.pm.PackageSetting snapshot()\npublic void dumpDebug(android.util.proto.ProtoOutputStream,long,java.util.List<android.content.pm.UserInfo>,com.android.server.pm.permission.LegacyPermissionDataProvider)\npublic java.util.List<java.lang.String> getMimeGroup(java.lang.String)\nprivate android.util.ArraySet<java.lang.String> getMimeGroupInternal(java.lang.String)\npublic boolean isMatch(int)\npublic boolean isSharedUser()\npublic com.android.server.pm.PackageSetting setAppId(int)\npublic com.android.server.pm.PackageSetting setCpuAbiOverride(java.lang.String)\npublic com.android.server.pm.PackageSetting setFirstInstallTime(long)\npublic com.android.server.pm.PackageSetting setForceQueryableOverride(boolean)\npublic com.android.server.pm.PackageSetting setInstallerPackageName(java.lang.String)\npublic com.android.server.pm.PackageSetting setInstallSource(com.android.server.pm.InstallSource)\n com.android.server.pm.PackageSetting removeInstallerPackage(java.lang.String)\npublic com.android.server.pm.PackageSetting setIsOrphaned(boolean)\npublic com.android.server.pm.PackageSetting setKeySetData(com.android.server.pm.PackageKeySetData)\npublic com.android.server.pm.PackageSetting setLastModifiedTime(long)\npublic com.android.server.pm.PackageSetting setLastUpdateTime(long)\npublic com.android.server.pm.PackageSetting setLongVersionCode(long)\npublic boolean setMimeGroup(java.lang.String,java.util.List<java.lang.String>)\npublic com.android.server.pm.PackageSetting setPkg(com.android.server.pm.parsing.pkg.AndroidPackage)\npublic com.android.server.pm.PackageSetting setPrimaryCpuAbi(java.lang.String)\npublic com.android.server.pm.PackageSetting setSecondaryCpuAbi(java.lang.String)\npublic com.android.server.pm.PackageSetting setSignatures(com.android.server.pm.PackageSignatures)\npublic com.android.server.pm.PackageSetting setVolumeUuid(java.lang.String)\npublic @java.lang.Override boolean isExternalStorage()\npublic com.android.server.pm.PackageSetting setUpdateAvailable(boolean)\npublic int getSharedUserIdInt()\npublic @java.lang.Override java.lang.String toString()\nprotected void copyMimeGroups(java.util.Map<java.lang.String,android.util.ArraySet<java.lang.String>>)\npublic void updateFrom(com.android.server.pm.PackageSetting)\n com.android.server.pm.PackageSetting updateMimeGroups(java.util.Set<java.lang.String>)\npublic @java.lang.Deprecated @java.lang.Override com.android.server.pm.permission.LegacyPermissionState getLegacyPermissionState()\npublic com.android.server.pm.PackageSetting setInstallPermissionsFixed(boolean)\npublic boolean isPrivileged()\npublic boolean isOem()\npublic boolean isVendor()\npublic boolean isProduct()\npublic @java.lang.Override boolean isRequiredForSystemUser()\npublic boolean isSystemExt()\npublic boolean isOdm()\npublic boolean isSystem()\npublic android.content.pm.SigningDetails getSigningDetails()\npublic com.android.server.pm.PackageSetting setSigningDetails(android.content.pm.SigningDetails)\npublic void copyFrom(com.android.server.pm.PackageSetting)\nprivate void doCopy(com.android.server.pm.PackageSetting)\n @com.android.internal.annotations.VisibleForTesting android.content.pm.PackageUserState modifyUserState(int)\npublic @android.annotation.NonNull android.content.pm.PackageUserState readUserState(int)\npublic @android.annotation.Nullable android.content.pm.PackageUserState readUserStateNullable(int)\n void setEnabled(int,int,java.lang.String)\n int getEnabled(int)\n java.lang.String getLastDisabledAppCaller(int)\n void setInstalled(boolean,int)\n boolean getInstalled(int)\n int getInstallReason(int)\n void setInstallReason(int,int)\n int getUninstallReason(int)\n void setUninstallReason(int,int)\n boolean setOverlayPaths(android.content.pm.overlay.OverlayPaths,int)\n @android.annotation.NonNull android.content.pm.overlay.OverlayPaths getOverlayPaths(int)\n boolean setOverlayPathsForLibrary(java.lang.String,android.content.pm.overlay.OverlayPaths,int)\n @android.annotation.NonNull java.util.Map<java.lang.String,android.content.pm.overlay.OverlayPaths> getOverlayPathsForLibrary(int)\n @com.android.internal.annotations.VisibleForTesting android.util.SparseArray<android.content.pm.PackageUserState> getUserState()\n boolean isAnyInstalled(int[])\n int[] queryInstalledUsers(int[],boolean)\n long getCeDataInode(int)\n void setCeDataInode(long,int)\n boolean getStopped(int)\n void setStopped(boolean,int)\n boolean getNotLaunched(int)\n void setNotLaunched(boolean,int)\n boolean getHidden(int)\n void setHidden(boolean,int)\n int getDistractionFlags(int)\n void setDistractionFlags(int,int)\n boolean getSuspended(int)\n boolean isSuspendedBy(java.lang.String,int)\n void addOrUpdateSuspension(java.lang.String,android.content.pm.SuspendDialogInfo,android.os.PersistableBundle,android.os.PersistableBundle,int)\n void removeSuspension(java.lang.String,int)\n void removeSuspension(java.util.function.Predicate<java.lang.String>,int)\npublic boolean getInstantApp(int)\n void setInstantApp(boolean,int)\n boolean getVirtualPreload(int)\n void setVirtualPreload(boolean,int)\n void setUserState(int,long,int,boolean,boolean,boolean,boolean,int,boolean,android.util.ArrayMap<java.lang.String,android.content.pm.PackageUserState.SuspendParams>,boolean,boolean,java.lang.String,android.util.ArraySet<java.lang.String>,android.util.ArraySet<java.lang.String>,int,int,java.lang.String,java.lang.String)\n void setUserState(int,android.content.pm.PackageUserState)\n android.util.ArraySet<java.lang.String> getEnabledComponents(int)\n android.util.ArraySet<java.lang.String> getDisabledComponents(int)\n void setEnabledComponents(android.util.ArraySet<java.lang.String>,int)\n void setDisabledComponents(android.util.ArraySet<java.lang.String>,int)\n void setEnabledComponentsCopy(android.util.ArraySet<java.lang.String>,int)\n void setDisabledComponentsCopy(android.util.ArraySet<java.lang.String>,int)\n android.content.pm.PackageUserState modifyUserStateComponents(int,boolean,boolean)\n void addDisabledComponent(java.lang.String,int)\n void addEnabledComponent(java.lang.String,int)\n boolean enableComponentLPw(java.lang.String,int)\n boolean disableComponentLPw(java.lang.String,int)\n boolean restoreComponentLPw(java.lang.String,int)\n int getCurrentEnabledStateLPr(java.lang.String,int)\n void removeUser(int)\npublic int[] getNotInstalledUserIds()\n void writePackageUserPermissionsProto(android.util.proto.ProtoOutputStream,long,java.util.List<android.content.pm.UserInfo>,com.android.server.pm.permission.LegacyPermissionDataProvider)\nprotected void writeUsersInfoToProto(android.util.proto.ProtoOutputStream,long)\n void setHarmfulAppWarning(int,java.lang.String)\n java.lang.String getHarmfulAppWarning(int)\n com.android.server.pm.PackageSetting setPath(java.io.File)\n java.lang.String getPathString()\npublic @com.android.internal.annotations.VisibleForTesting boolean overrideNonLocalizedLabelAndIcon(android.content.ComponentName,java.lang.String,java.lang.Integer,int)\npublic void resetOverrideComponentLabelIcon(int)\npublic void setSplashScreenTheme(int,java.lang.String)\npublic @android.annotation.Nullable java.lang.String getSplashScreenTheme(int)\npublic boolean isPackageLoading()\npublic android.content.pm.IncrementalStatesInfo getIncrementalStatesInfo()\npublic void setStatesOnCommit()\npublic void setIncrementalStatesCallback(com.android.server.pm.IncrementalStates.Callback)\npublic void setLoadingProgress(float)\npublic @android.annotation.NonNull @java.lang.Override long getLongVersionCode()\npublic @android.annotation.Nullable @java.lang.Override java.util.Map<java.lang.String,java.util.Set<java.lang.String>> getMimeGroups()\npublic @android.annotation.NonNull @java.lang.Override java.lang.String getPackageName()\npublic @android.annotation.Nullable @java.lang.Override com.android.server.pm.pkg.AndroidPackageApi getAndroidPackage()\npublic @android.annotation.Nullable @java.lang.Override java.lang.Integer getSharedUserId()\npublic @android.annotation.NonNull android.content.pm.SigningInfo getSigningInfo()\npublic @android.annotation.NonNull @java.lang.Override java.lang.String[] getUsesStaticLibraries()\npublic @android.annotation.NonNull @java.lang.Override long[] getUsesStaticLibrariesVersions()\npublic @android.annotation.NonNull @java.lang.Override java.util.List<android.content.pm.SharedLibraryInfo> getUsesLibraryInfos()\npublic @android.annotation.NonNull @java.lang.Override java.util.List<java.lang.String> getUsesLibraryFiles()\npublic @java.lang.Override boolean isHiddenUntilInstalled()\npublic @android.annotation.Nullable @java.lang.Override java.lang.String getSeInfoOverride()\npublic @android.annotation.NonNull @java.lang.Override long[] getLastPackageUsageTime()\npublic @java.lang.Override boolean isUpdatedSystemApp()\npublic @java.lang.Deprecated @java.lang.Override int[] getUserIds()\npublic @java.lang.Override android.content.pm.PackageUserState getUserState(int)\npublic com.android.server.pm.PackageSetting setDomainSetId(java.util.UUID)\npublic com.android.server.pm.PackageSetting setSharedUser(com.android.server.pm.SharedUserSetting)\npublic com.android.server.pm.PackageSetting setCategoryOverride(int)\npublic com.android.server.pm.PackageSetting setLegacyNativeLibraryPath(java.lang.String)\npublic com.android.server.pm.PackageSetting setIncrementalStates(com.android.server.pm.IncrementalStates)\nclass PackageSetting extends com.android.server.pm.SettingBase implements [com.android.server.pm.pkg.PackageState]\n@com.android.internal.util.DataClass(genGetters=true, genConstructor=false, genSetters=false, genBuilder=false)")
+ inputSignatures = "protected int sharedUserId\n @android.annotation.Nullable java.util.Map<java.lang.String,android.util.ArraySet<java.lang.String>> mimeGroups\n @java.lang.Deprecated @android.annotation.Nullable java.util.Set<java.lang.String> mOldCodePaths\n @android.annotation.Nullable java.lang.String[] usesStaticLibraries\n @android.annotation.Nullable long[] usesStaticLibrariesVersions\nprivate @android.annotation.Nullable @java.lang.Deprecated java.lang.String legacyNativeLibraryPath\nprivate @android.annotation.NonNull java.lang.String mName\nprivate @android.annotation.NonNull java.lang.String mRealName\nprivate int mAppId\nprivate @android.annotation.Nullable com.android.server.pm.parsing.pkg.AndroidPackage pkg\nprivate @android.annotation.Nullable com.android.server.pm.SharedUserSetting sharedUser\nprivate @android.annotation.NonNull java.io.File mPath\nprivate @android.annotation.NonNull java.lang.String mPathString\nprivate float loadingProgress\nprivate @android.annotation.Nullable java.lang.String mPrimaryCpuAbi\nprivate @android.annotation.Nullable java.lang.String mSecondaryCpuAbi\nprivate @android.annotation.Nullable java.lang.String mCpuAbiOverride\nprivate long mLastModifiedTime\nprivate long firstInstallTime\nprivate long lastUpdateTime\nprivate long versionCode\nprivate @android.annotation.NonNull com.android.server.pm.PackageSignatures signatures\nprivate boolean installPermissionsFixed\nprivate @android.annotation.NonNull com.android.server.pm.PackageKeySetData keySetData\nprivate final @android.annotation.NonNull android.util.SparseArray<com.android.server.pm.pkg.PackageUserStateInternalImpl> mUserState\nprivate @android.annotation.NonNull com.android.server.pm.InstallSource installSource\nprivate @android.annotation.Nullable java.lang.String volumeUuid\nprivate int categoryOverride\nprivate boolean updateAvailable\nprivate boolean forceQueryableOverride\nprivate @android.annotation.NonNull com.android.server.pm.pkg.PackageStateUnserialized pkgState\nprivate @android.annotation.NonNull java.util.UUID mDomainSetId\nprivate final @android.annotation.NonNull com.android.server.utils.SnapshotCache<com.android.server.pm.PackageSetting> mSnapshot\nprivate com.android.server.utils.SnapshotCache<com.android.server.pm.PackageSetting> makeCache()\npublic com.android.server.pm.PackageSetting snapshot()\npublic void dumpDebug(android.util.proto.ProtoOutputStream,long,java.util.List<android.content.pm.UserInfo>,com.android.server.pm.permission.LegacyPermissionDataProvider)\npublic java.util.List<java.lang.String> getMimeGroup(java.lang.String)\nprivate android.util.ArraySet<java.lang.String> getMimeGroupInternal(java.lang.String)\npublic boolean isMatch(int)\npublic boolean isSharedUser()\npublic com.android.server.pm.PackageSetting setAppId(int)\npublic com.android.server.pm.PackageSetting setCpuAbiOverride(java.lang.String)\npublic com.android.server.pm.PackageSetting setFirstInstallTime(long)\npublic com.android.server.pm.PackageSetting setForceQueryableOverride(boolean)\npublic com.android.server.pm.PackageSetting setInstallerPackageName(java.lang.String)\npublic com.android.server.pm.PackageSetting setInstallSource(com.android.server.pm.InstallSource)\n com.android.server.pm.PackageSetting removeInstallerPackage(java.lang.String)\npublic com.android.server.pm.PackageSetting setIsOrphaned(boolean)\npublic com.android.server.pm.PackageSetting setKeySetData(com.android.server.pm.PackageKeySetData)\npublic com.android.server.pm.PackageSetting setLastModifiedTime(long)\npublic com.android.server.pm.PackageSetting setLastUpdateTime(long)\npublic com.android.server.pm.PackageSetting setLongVersionCode(long)\npublic boolean setMimeGroup(java.lang.String,java.util.List<java.lang.String>)\npublic com.android.server.pm.PackageSetting setPkg(com.android.server.pm.parsing.pkg.AndroidPackage)\npublic com.android.server.pm.PackageSetting setPrimaryCpuAbi(java.lang.String)\npublic com.android.server.pm.PackageSetting setSecondaryCpuAbi(java.lang.String)\npublic com.android.server.pm.PackageSetting setSignatures(com.android.server.pm.PackageSignatures)\npublic com.android.server.pm.PackageSetting setVolumeUuid(java.lang.String)\npublic @java.lang.Override boolean isExternalStorage()\npublic com.android.server.pm.PackageSetting setUpdateAvailable(boolean)\npublic int getSharedUserIdInt()\npublic @java.lang.Override java.lang.String toString()\nprotected void copyMimeGroups(java.util.Map<java.lang.String,android.util.ArraySet<java.lang.String>>)\npublic void updateFrom(com.android.server.pm.PackageSetting)\n com.android.server.pm.PackageSetting updateMimeGroups(java.util.Set<java.lang.String>)\npublic @java.lang.Deprecated @java.lang.Override com.android.server.pm.permission.LegacyPermissionState getLegacyPermissionState()\npublic com.android.server.pm.PackageSetting setInstallPermissionsFixed(boolean)\npublic boolean isPrivileged()\npublic boolean isOem()\npublic boolean isVendor()\npublic boolean isProduct()\npublic @java.lang.Override boolean isRequiredForSystemUser()\npublic boolean isSystemExt()\npublic boolean isOdm()\npublic boolean isSystem()\npublic android.content.pm.SigningDetails getSigningDetails()\npublic com.android.server.pm.PackageSetting setSigningDetails(android.content.pm.SigningDetails)\npublic void copyPackageSetting(com.android.server.pm.PackageSetting)\n @com.android.internal.annotations.VisibleForTesting com.android.server.pm.pkg.PackageUserStateInternalImpl modifyUserState(int)\npublic @android.annotation.NonNull android.content.pm.pkg.PackageUserStateInternal readUserState(int)\npublic @android.annotation.Nullable android.content.pm.pkg.PackageUserState readUserStateNullable(int)\n void setEnabled(int,int,java.lang.String)\n int getEnabled(int)\n java.lang.String getLastDisabledAppCaller(int)\n void setInstalled(boolean,int)\n boolean getInstalled(int)\n int getInstallReason(int)\n void setInstallReason(int,int)\n int getUninstallReason(int)\n void setUninstallReason(int,int)\n boolean setOverlayPaths(android.content.pm.overlay.OverlayPaths,int)\n @android.annotation.NonNull android.content.pm.overlay.OverlayPaths getOverlayPaths(int)\n boolean setOverlayPathsForLibrary(java.lang.String,android.content.pm.overlay.OverlayPaths,int)\n @android.annotation.NonNull java.util.Map<java.lang.String,android.content.pm.overlay.OverlayPaths> getOverlayPathsForLibrary(int)\n @com.android.internal.annotations.VisibleForTesting android.util.SparseArray<com.android.server.pm.pkg.PackageUserStateInternalImpl> getUserState()\n boolean isAnyInstalled(int[])\n int[] queryInstalledUsers(int[],boolean)\n long getCeDataInode(int)\n void setCeDataInode(long,int)\n boolean getStopped(int)\n void setStopped(boolean,int)\n boolean getNotLaunched(int)\n void setNotLaunched(boolean,int)\n boolean getHidden(int)\n void setHidden(boolean,int)\n int getDistractionFlags(int)\n void setDistractionFlags(int,int)\n boolean getSuspended(int)\n boolean isSuspendedBy(java.lang.String,int)\n boolean addOrUpdateSuspension(java.lang.String,android.content.pm.SuspendDialogInfo,android.os.PersistableBundle,android.os.PersistableBundle,int)\n boolean removeSuspension(java.lang.String,int)\n void removeSuspension(java.util.function.Predicate<java.lang.String>,int)\npublic boolean getInstantApp(int)\n void setInstantApp(boolean,int)\n boolean getVirtualPreload(int)\n void setVirtualPreload(boolean,int)\n void setUserState(int,long,int,boolean,boolean,boolean,boolean,int,boolean,android.util.ArrayMap<java.lang.String,android.content.pm.pkg.PackageUserState.SuspendParams>,boolean,boolean,java.lang.String,android.util.ArraySet<java.lang.String>,android.util.ArraySet<java.lang.String>,int,int,java.lang.String,java.lang.String)\n void setUserState(int,android.content.pm.pkg.PackageUserStateInternal)\n android.util.ArraySet<java.lang.String> getEnabledComponents(int)\n android.util.ArraySet<java.lang.String> getDisabledComponents(int)\n void setEnabledComponents(android.util.ArraySet<java.lang.String>,int)\n void setDisabledComponents(android.util.ArraySet<java.lang.String>,int)\n void setEnabledComponentsCopy(android.util.ArraySet<java.lang.String>,int)\n void setDisabledComponentsCopy(android.util.ArraySet<java.lang.String>,int)\n com.android.server.pm.pkg.PackageUserStateInternalImpl modifyUserStateComponents(int,boolean,boolean)\n void addDisabledComponent(java.lang.String,int)\n void addEnabledComponent(java.lang.String,int)\n boolean enableComponentLPw(java.lang.String,int)\n boolean disableComponentLPw(java.lang.String,int)\n boolean restoreComponentLPw(java.lang.String,int)\n int getCurrentEnabledStateLPr(java.lang.String,int)\n void removeUser(int)\npublic int[] getNotInstalledUserIds()\n void writePackageUserPermissionsProto(android.util.proto.ProtoOutputStream,long,java.util.List<android.content.pm.UserInfo>,com.android.server.pm.permission.LegacyPermissionDataProvider)\nprotected void writeUsersInfoToProto(android.util.proto.ProtoOutputStream,long)\n void setHarmfulAppWarning(int,java.lang.String)\n java.lang.String getHarmfulAppWarning(int)\n com.android.server.pm.PackageSetting setPath(java.io.File)\n java.lang.String getPathString()\npublic @com.android.internal.annotations.VisibleForTesting boolean overrideNonLocalizedLabelAndIcon(android.content.ComponentName,java.lang.String,java.lang.Integer,int)\npublic void resetOverrideComponentLabelIcon(int)\npublic void setSplashScreenTheme(int,java.lang.String)\npublic @android.annotation.Nullable java.lang.String getSplashScreenTheme(int)\npublic boolean isPackageLoading()\npublic com.android.server.pm.PackageSetting setLoadingProgress(float)\npublic @android.annotation.NonNull @java.lang.Override long getLongVersionCode()\npublic @android.annotation.Nullable @java.lang.Override java.util.Map<java.lang.String,java.util.Set<java.lang.String>> getMimeGroups()\npublic @android.annotation.NonNull @java.lang.Override java.lang.String getPackageName()\npublic @android.annotation.Nullable @java.lang.Override com.android.server.pm.pkg.AndroidPackageApi getAndroidPackage()\npublic @android.annotation.Nullable @java.lang.Override java.lang.Integer getSharedUserId()\npublic @android.annotation.NonNull android.content.pm.SigningInfo getSigningInfo()\npublic @android.annotation.NonNull @java.lang.Override java.lang.String[] getUsesStaticLibraries()\npublic @android.annotation.NonNull @java.lang.Override long[] getUsesStaticLibrariesVersions()\npublic @android.annotation.NonNull @java.lang.Override java.util.List<android.content.pm.SharedLibraryInfo> getUsesLibraryInfos()\npublic @android.annotation.NonNull @java.lang.Override java.util.List<java.lang.String> getUsesLibraryFiles()\npublic @java.lang.Override boolean isHiddenUntilInstalled()\npublic @android.annotation.Nullable @java.lang.Override java.lang.String getSeInfoOverride()\npublic @android.annotation.NonNull @java.lang.Override long[] getLastPackageUsageTime()\npublic @java.lang.Override boolean isUpdatedSystemApp()\npublic @java.lang.Deprecated @java.lang.Override int[] getUserIds()\npublic @java.lang.Override android.content.pm.pkg.PackageUserState getUserState(int)\npublic com.android.server.pm.PackageSetting setDomainSetId(java.util.UUID)\npublic com.android.server.pm.PackageSetting setSharedUser(com.android.server.pm.SharedUserSetting)\npublic com.android.server.pm.PackageSetting setCategoryOverride(int)\npublic com.android.server.pm.PackageSetting setLegacyNativeLibraryPath(java.lang.String)\nclass PackageSetting extends com.android.server.pm.SettingBase implements [com.android.server.pm.pkg.PackageState]\n@com.android.internal.util.DataClass(genGetters=true, genConstructor=false, genSetters=false, genBuilder=false)")
@Deprecated
private void __metadata() {}
diff --git a/services/core/java/com/android/server/pm/ScanPackageHelper.java b/services/core/java/com/android/server/pm/ScanPackageHelper.java
index 8018011..731c6ca 100644
--- a/services/core/java/com/android/server/pm/ScanPackageHelper.java
+++ b/services/core/java/com/android/server/pm/ScanPackageHelper.java
@@ -1018,9 +1018,6 @@
if (mPm.mIncrementalManager != null && isIncrementalPath(parsedPackage.getPath())) {
if (pkgSetting != null && pkgSetting.isPackageLoading()) {
// Continue monitoring loading progress of active incremental packages
- final IncrementalStatesCallback incrementalStatesCallback =
- new IncrementalStatesCallback(parsedPackage.getPackageName(), mPm);
- pkgSetting.setIncrementalStatesCallback(incrementalStatesCallback);
mPm.mIncrementalManager.registerLoadingProgressCallback(parsedPackage.getPath(),
new IncrementalProgressListener(parsedPackage.getPackageName(), mPm));
}
diff --git a/services/core/java/com/android/server/pm/Settings.java b/services/core/java/com/android/server/pm/Settings.java
index f89d9eb..6df1006 100644
--- a/services/core/java/com/android/server/pm/Settings.java
+++ b/services/core/java/com/android/server/pm/Settings.java
@@ -73,7 +73,6 @@
import android.os.Trace;
import android.os.UserHandle;
import android.os.UserManager;
-import android.os.incremental.IncrementalManager;
import android.os.storage.StorageManager;
import android.os.storage.VolumeInfo;
import android.service.pm.PackageServiceDumpProto;
@@ -1087,9 +1086,6 @@
pkgSetting.setLegacyNativeLibraryPath(legacyNativeLibraryPath);
}
pkgSetting.setPath(codePath);
- if (IncrementalManager.isIncrementalPath(codePath.getAbsolutePath())) {
- pkgSetting.setIncrementalStates(new IncrementalStates());
- }
}
// If what we are scanning is a system (and possibly privileged) package,
// then make it so, regardless of whether it was previously installed only
@@ -2708,8 +2704,7 @@
} else {
serializer.attributeInt(null, "sharedUserId", pkg.getAppId());
}
- serializer.attributeFloat(null, "loadingProgress",
- pkg.getIncrementalStates().getIncrementalStatesInfo().getProgress());
+ serializer.attributeFloat(null, "loadingProgress", pkg.getLoadingProgress());
writeUsesStaticLibLPw(serializer, pkg.usesStaticLibraries, pkg.usesStaticLibrariesVersions);
@@ -2784,8 +2779,7 @@
if (pkg.isPackageLoading()) {
serializer.attributeBoolean(null, "isLoading", true);
}
- serializer.attributeFloat(null, "loadingProgress",
- pkg.getIncrementalStates().getIncrementalStatesInfo().getProgress());
+ serializer.attributeFloat(null, "loadingProgress", pkg.getLoadingProgress());
serializer.attribute(null, "domainSetId", pkg.getDomainSetId().toString());
@@ -3531,7 +3525,6 @@
PackageSetting packageSetting = null;
long versionCode = 0;
boolean installedForceQueryable = false;
- boolean isLoading = false;
float loadingProgress = 0;
UUID domainSetId;
try {
@@ -3549,7 +3542,6 @@
cpuAbiOverrideString = parser.getAttributeValue(null, "cpuAbiOverride");
updateAvailable = parser.getAttributeBoolean(null, "updateAvailable", false);
installedForceQueryable = parser.getAttributeBoolean(null, "forceQueryable", false);
- isLoading = parser.getAttributeBoolean(null, "isLoading", false);
loadingProgress = parser.getAttributeFloat(null, "loadingProgress", 0);
if (primaryCpuAbiString == null && legacyCpuAbiString != null) {
@@ -3706,7 +3698,7 @@
.setSecondaryCpuAbi(secondaryCpuAbiString)
.setUpdateAvailable(updateAvailable)
.setForceQueryableOverride(installedForceQueryable)
- .setIncrementalStates(new IncrementalStates(isLoading, loadingProgress));
+ .setLoadingProgress(loadingProgress);
// Handle legacy string here for single-user mode
final String enabledStr = parser.getAttributeValue(null, ATTR_ENABLED);
if (enabledStr != null) {
@@ -4681,8 +4673,7 @@
}
if (ps.isPackageLoading()) {
pw.print(prefix); pw.println(" loadingProgress=" +
- (int) (ps.getIncrementalStates().getIncrementalStatesInfo().getProgress()
- * 100) + "%");
+ (int) (ps.getLoadingProgress() * 100) + "%");
}
if (ps.getVolumeUuid() != null) {
pw.print(prefix); pw.print(" volumeUuid=");
diff --git a/services/core/java/com/android/server/pm/StagingManager.java b/services/core/java/com/android/server/pm/StagingManager.java
index a2f48c7..c83cdb4 100644
--- a/services/core/java/com/android/server/pm/StagingManager.java
+++ b/services/core/java/com/android/server/pm/StagingManager.java
@@ -19,7 +19,6 @@
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.apex.ApexInfo;
-import android.apex.ApexInfoList;
import android.apex.ApexSessionInfo;
import android.apex.ApexSessionParams;
import android.content.BroadcastReceiver;
@@ -31,25 +30,14 @@
import android.content.IntentSender;
import android.content.pm.ApexStagedEvent;
import android.content.pm.IStagedApexObserver;
-import android.content.pm.PackageInfo;
import android.content.pm.PackageInstaller;
import android.content.pm.PackageInstaller.SessionInfo;
import android.content.pm.PackageInstaller.SessionInfo.StagedSessionErrorCode;
import android.content.pm.PackageManager;
import android.content.pm.PackageManagerInternal;
-import android.content.pm.SigningDetails;
-import android.content.pm.SigningDetails.SignatureSchemeVersion;
import android.content.pm.StagedApexInfo;
-import android.content.pm.parsing.PackageInfoWithoutStateUtils;
-import android.content.pm.parsing.result.ParseResult;
-import android.content.pm.parsing.result.ParseTypeImpl;
-import android.content.rollback.RollbackInfo;
-import android.content.rollback.RollbackManager;
import android.os.Bundle;
-import android.os.Handler;
import android.os.IBinder;
-import android.os.Looper;
-import android.os.Message;
import android.os.PowerManager;
import android.os.RemoteException;
import android.os.SystemProperties;
@@ -62,7 +50,6 @@
import android.util.Slog;
import android.util.SparseArray;
import android.util.TimingsTraceLog;
-import android.util.apk.ApkSignatureVerifier;
import com.android.internal.annotations.GuardedBy;
import com.android.internal.annotations.VisibleForTesting;
@@ -72,10 +59,8 @@
import com.android.server.LocalServices;
import com.android.server.SystemService;
import com.android.server.SystemServiceManager;
-import com.android.server.pm.parsing.PackageParser2;
import com.android.server.pm.parsing.pkg.AndroidPackage;
import com.android.server.pm.parsing.pkg.AndroidPackageUtils;
-import com.android.server.pm.parsing.pkg.ParsedPackage;
import com.android.server.rollback.RollbackManagerInternal;
import com.android.server.rollback.WatchdogRollbackLogger;
@@ -93,7 +78,6 @@
import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.TimeUnit;
import java.util.function.Predicate;
-import java.util.function.Supplier;
/**
* This class handles staged install sessions, i.e. install sessions that require packages to
@@ -106,9 +90,6 @@
private final ApexManager mApexManager;
private final PowerManager mPowerManager;
private final Context mContext;
- @VisibleForTesting
- final PreRebootVerificationHandler mPreRebootVerificationHandler;
- private final Supplier<PackageParser2> mPackageParserSupplier;
private final File mFailureReasonFile = new File("/metadata/staged-install/failure_reason.txt");
private String mFailureReason;
@@ -152,28 +133,19 @@
boolean hasParentSessionId();
long getCommittedMillis();
void abandon();
- void notifyEndPreRebootVerification();
void verifySession();
}
- StagingManager(Context context, Supplier<PackageParser2> packageParserSupplier, Looper looper) {
- this(context, packageParserSupplier, ApexManager.getInstance(), looper);
+ StagingManager(Context context) {
+ this(context, ApexManager.getInstance());
}
@VisibleForTesting
- StagingManager(Context context, Supplier<PackageParser2> packageParserSupplier,
- ApexManager apexManager) {
- this(context, packageParserSupplier, apexManager, BackgroundThread.get().getLooper());
- }
-
- StagingManager(Context context, Supplier<PackageParser2> packageParserSupplier,
- ApexManager apexManager, Looper looper) {
+ StagingManager(Context context, ApexManager apexManager) {
mContext = context;
- mPackageParserSupplier = packageParserSupplier;
mApexManager = apexManager;
mPowerManager = (PowerManager) context.getSystemService(Context.POWER_SERVICE);
- mPreRebootVerificationHandler = new PreRebootVerificationHandler(looper);
if (mFailureReasonFile.exists()) {
try (BufferedReader reader = new BufferedReader(new FileReader(mFailureReasonFile))) {
@@ -244,128 +216,6 @@
}
}
- /**
- * Validates the signature used to sign the container of the new apex package
- *
- * @param newApexPkg The new apex package that is being installed
- */
- private void validateApexSignature(PackageInfo newApexPkg)
- throws PackageManagerException {
- // Get signing details of the new package
- final String apexPath = newApexPkg.applicationInfo.sourceDir;
- final String packageName = newApexPkg.packageName;
- int minSignatureScheme = ApkSignatureVerifier.getMinimumSignatureSchemeVersionForTargetSdk(
- newApexPkg.applicationInfo.targetSdkVersion);
-
- final ParseTypeImpl input = ParseTypeImpl.forDefaultParsing();
- final ParseResult<SigningDetails> newResult = ApkSignatureVerifier.verify(
- input.reset(), apexPath, minSignatureScheme);
- if (newResult.isError()) {
- throw new PackageManagerException(SessionInfo.STAGED_SESSION_VERIFICATION_FAILED,
- "Failed to parse APEX package " + apexPath + " : "
- + newResult.getException(), newResult.getException());
- }
- final SigningDetails newSigningDetails = newResult.getResult();
-
- // Get signing details of the existing package
- final PackageInfo existingApexPkg = mApexManager.getPackageInfo(packageName,
- ApexManager.MATCH_ACTIVE_PACKAGE);
- if (existingApexPkg == null) {
- // This should never happen, because submitSessionToApexService ensures that no new
- // apexes were installed.
- throw new IllegalStateException("Unknown apex package " + packageName);
- }
-
- final ParseResult<SigningDetails> existingResult = ApkSignatureVerifier.verify(
- input.reset(), existingApexPkg.applicationInfo.sourceDir,
- SignatureSchemeVersion.JAR);
- if (existingResult.isError()) {
- throw new PackageManagerException(SessionInfo.STAGED_SESSION_VERIFICATION_FAILED,
- "Failed to parse APEX package " + existingApexPkg.applicationInfo.sourceDir
- + " : " + existingResult.getException(), existingResult.getException());
- }
- final SigningDetails existingSigningDetails = existingResult.getResult();
-
- // Verify signing details for upgrade
- if (newSigningDetails.checkCapability(existingSigningDetails,
- SigningDetails.CertCapabilities.INSTALLED_DATA)
- || existingSigningDetails.checkCapability(newSigningDetails,
- SigningDetails.CertCapabilities.ROLLBACK)) {
- return;
- }
-
- throw new PackageManagerException(SessionInfo.STAGED_SESSION_VERIFICATION_FAILED,
- "APK-container signature of APEX package " + packageName + " with version "
- + newApexPkg.versionCodeMajor + " and path " + apexPath + " is not"
- + " compatible with the one currently installed on device");
- }
-
- private List<PackageInfo> submitSessionToApexService(@NonNull StagedSession session,
- int rollbackId) throws PackageManagerException {
- final IntArray childSessionIds = new IntArray();
- if (session.isMultiPackage()) {
- for (StagedSession s : session.getChildSessions()) {
- if (s.isApexSession()) {
- childSessionIds.add(s.sessionId());
- }
- }
- }
- ApexSessionParams apexSessionParams = new ApexSessionParams();
- apexSessionParams.sessionId = session.sessionId();
- apexSessionParams.childSessionIds = childSessionIds.toArray();
- if (session.sessionParams().installReason == PackageManager.INSTALL_REASON_ROLLBACK) {
- apexSessionParams.isRollback = true;
- apexSessionParams.rollbackId = rollbackId;
- } else {
- if (rollbackId != -1) {
- apexSessionParams.hasRollbackEnabled = true;
- apexSessionParams.rollbackId = rollbackId;
- }
- }
- // submitStagedSession will throw a PackageManagerException if apexd verification fails,
- // which will be propagated to populate stagedSessionErrorMessage of this session.
- final ApexInfoList apexInfoList = mApexManager.submitStagedSession(apexSessionParams);
- final List<PackageInfo> result = new ArrayList<>();
- final List<String> apexPackageNames = new ArrayList<>();
- for (ApexInfo apexInfo : apexInfoList.apexInfos) {
- final PackageInfo packageInfo;
- final int flags = PackageManager.GET_META_DATA;
- try (PackageParser2 packageParser = mPackageParserSupplier.get()) {
- File apexFile = new File(apexInfo.modulePath);
- final ParsedPackage parsedPackage = packageParser.parsePackage(
- apexFile, flags, false);
- packageInfo = PackageInfoWithoutStateUtils.generate(parsedPackage, apexInfo, flags);
- if (packageInfo == null) {
- throw new PackageManagerException(
- SessionInfo.STAGED_SESSION_VERIFICATION_FAILED,
- "Unable to generate package info: " + apexInfo.modulePath);
- }
- } catch (PackageManagerException e) {
- throw new PackageManagerException(SessionInfo.STAGED_SESSION_VERIFICATION_FAILED,
- "Failed to parse APEX package " + apexInfo.modulePath + " : " + e, e);
- }
- result.add(packageInfo);
- apexPackageNames.add(packageInfo.packageName);
- }
- Slog.d(TAG, "Session " + session.sessionId() + " has following APEX packages: "
- + apexPackageNames);
- return result;
- }
-
- private int retrieveRollbackIdForCommitSession(int sessionId) throws PackageManagerException {
- RollbackManager rm = mContext.getSystemService(RollbackManager.class);
-
- final List<RollbackInfo> rollbacks = rm.getRecentlyCommittedRollbacks();
- for (int i = 0, size = rollbacks.size(); i < size; i++) {
- final RollbackInfo rollback = rollbacks.get(i);
- if (rollback.getCommittedSessionId() == sessionId) {
- return rollback.getRollbackId();
- }
- }
- throw new PackageManagerException(
- "Could not find rollback id for commit session: " + sessionId);
- }
-
// Reverts apex sessions and user data (if checkpoint is supported). Also reboots the device.
private void abortCheckpoint(String failureReason, boolean supportsCheckpoint,
boolean needsCheckpoint) {
@@ -663,129 +513,15 @@
}
}
- void commitSession(@NonNull StagedSession session) {
- // Store this parent session which will be used to check overlapping later
- createSession(session);
- mPreRebootVerificationHandler.startPreRebootVerification(session);
- }
-
- private int getSessionIdForParentOrSelf(StagedSession session) {
- return session.hasParentSessionId() ? session.getParentSessionId() : session.sessionId();
- }
-
- private StagedSession getParentSessionOrSelf(StagedSession session) {
- return session.hasParentSessionId()
- ? getStagedSession(session.getParentSessionId())
- : session;
- }
-
- private boolean isRollback(StagedSession session) {
- final StagedSession root = getParentSessionOrSelf(session);
- return root.sessionParams().installReason == PackageManager.INSTALL_REASON_ROLLBACK;
- }
-
- /**
- * <p> Check if the session provided is non-overlapping with the active staged sessions.
- *
- * <p> A session is non-overlapping if it meets one of the following conditions: </p>
- * <ul>
- * <li>It is a parent session</li>
- * <li>It is already one of the active sessions</li>
- * <li>Its package name is not same as any of the active sessions</li>
- * </ul>
- * @throws PackageManagerException if session fails the check
- */
- // TODO(b/192625695): Rename this method which checks rollbacks in addition to overlapping
@VisibleForTesting
- void checkNonOverlappingWithStagedSessions(@NonNull StagedSession session)
- throws PackageManagerException {
- if (session.isMultiPackage()) {
- // We cannot say a parent session overlaps until we process its children
- return;
- }
+ void commitSession(@NonNull StagedSession session) {
+ createSession(session);
+ handleCommittedSession(session);
+ }
- String packageName = session.getPackageName();
- if (packageName == null) {
- throw new PackageManagerException(SessionInfo.STAGED_SESSION_VERIFICATION_FAILED,
- "Cannot stage session " + session.sessionId() + " with package name null");
- }
-
- boolean supportsCheckpoint;
- try {
- supportsCheckpoint = PackageHelper.getStorageManager().supportsCheckpoint();
- } catch (RemoteException e) {
- throw new PackageManagerException(SessionInfo.STAGED_SESSION_VERIFICATION_FAILED,
- "Can't query fs-checkpoint status : " + e);
- }
-
- final boolean isRollback = isRollback(session);
-
- synchronized (mStagedSessions) {
- for (int i = 0; i < mStagedSessions.size(); i++) {
- final StagedSession stagedSession = mStagedSessions.valueAt(i);
- if (stagedSession.hasParentSessionId() || !stagedSession.isCommitted()
- || stagedSession.isInTerminalState()
- || stagedSession.isDestroyed()) {
- continue;
- }
-
- // From here on, stagedSession is a parent active staged session
-
- // Check if session is one of the active sessions
- if (getSessionIdForParentOrSelf(session) == stagedSession.sessionId()) {
- Slog.w(TAG, "Session " + session.sessionId() + " is already staged");
- continue;
- }
-
- if (isRollback && !isRollback(stagedSession)) {
- // If the new session is a rollback, then it gets priority. The existing
- // session is failed to reduce risk and avoid an SDK extension dependency
- // violation.
- final StagedSession root = stagedSession;
- if (!ensureActiveApexSessionIsAborted(root)) {
- Slog.e(TAG, "Failed to abort apex session " + root.sessionId());
- // Safe to ignore active apex session abort failure since session
- // will be marked failed on next step and staging directory for session
- // will be deleted.
- }
- root.setSessionFailed(
- SessionInfo.STAGED_SESSION_CONFLICT,
- "Session was failed by rollback session: " + session.sessionId());
- Slog.i(TAG, "Session " + root.sessionId() + " is marked failed due to "
- + "rollback session: " + session.sessionId());
- } else if (!isRollback && isRollback(stagedSession)) {
- throw new PackageManagerException(
- SessionInfo.STAGED_SESSION_CONFLICT,
- "Session was failed by rollback session: " + stagedSession.sessionId());
- } else if (stagedSession.sessionContains(
- s -> s.getPackageName().equals(packageName))) {
- // Fail the session committed later when there are overlapping packages
- if (stagedSession.getCommittedMillis() < session.getCommittedMillis()) {
- throw new PackageManagerException(
- SessionInfo.STAGED_SESSION_VERIFICATION_FAILED,
- "Package: " + session.getPackageName() + " in session: "
- + session.sessionId()
- + " has been staged already by session: "
- + stagedSession.sessionId(), null);
- } else {
- stagedSession.setSessionFailed(
- SessionInfo.STAGED_SESSION_VERIFICATION_FAILED,
- "Package: " + packageName + " in session: "
- + stagedSession.sessionId()
- + " has been staged already by session: "
- + session.sessionId());
- }
- }
-
- // Staging multiple root sessions is not allowed if device doesn't support
- // checkpoint. If session and stagedSession do not have common ancestor, they are
- // from two different root sessions.
- if (!supportsCheckpoint) {
- throw new PackageManagerException(
- SessionInfo.STAGED_SESSION_VERIFICATION_FAILED,
- "Cannot stage multiple sessions without checkpoint support", null);
- }
- }
+ private void handleCommittedSession(@NonNull StagedSession session) {
+ if (session.isSessionReady() && session.containsApexSession()) {
+ notifyStagedApexObservers();
}
}
@@ -1234,237 +970,4 @@
}
}
}
-
- @VisibleForTesting
- final class PreRebootVerificationHandler extends Handler {
-
- PreRebootVerificationHandler(Looper looper) {
- super(looper);
- }
-
- /**
- * Handler for states of pre reboot verification. The states are arranged linearly (shown
- * below) with each state either calling the next state, or calling some other method that
- * eventually calls the next state.
- *
- * <p><ul>
- * <li>MSG_PRE_REBOOT_VERIFICATION_START</li>
- * <li>MSG_PRE_REBOOT_VERIFICATION_APEX</li>
- * <li>MSG_PRE_REBOOT_VERIFICATION_END</li>
- * </ul></p>
- *
- * Details about each of state can be found in corresponding handler of node.
- */
- private static final int MSG_PRE_REBOOT_VERIFICATION_START = 1;
- private static final int MSG_PRE_REBOOT_VERIFICATION_APEX = 2;
- @VisibleForTesting
- static final int MSG_PRE_REBOOT_VERIFICATION_END = 3;
-
- @Override
- public void handleMessage(Message msg) {
- final int sessionId = msg.arg1;
- final int rollbackId = msg.arg2;
- final StagedSession session = (StagedSession) msg.obj;
- if (session.isDestroyed() || session.isSessionFailed()) {
- // No point in running verification on a destroyed/failed session
- onPreRebootVerificationComplete(session);
- return;
- }
- try {
- switch (msg.what) {
- case MSG_PRE_REBOOT_VERIFICATION_START:
- handlePreRebootVerification_Start(session);
- break;
- case MSG_PRE_REBOOT_VERIFICATION_APEX:
- handlePreRebootVerification_Apex(session, rollbackId);
- break;
- case MSG_PRE_REBOOT_VERIFICATION_END:
- handlePreRebootVerification_End(session);
- break;
- }
- } catch (Exception e) {
- Slog.e(TAG, "Pre-reboot verification failed due to unhandled exception", e);
- onPreRebootVerificationFailure(session,
- SessionInfo.STAGED_SESSION_ACTIVATION_FAILED,
- "Pre-reboot verification failed due to unhandled exception: " + e);
- }
- }
-
- // Method for starting the pre-reboot verification
- private synchronized void startPreRebootVerification(
- @NonNull StagedSession session) {
- mBootCompleted.thenRun(() -> {
- int sessionId = session.sessionId();
- Slog.d(TAG, "Starting preRebootVerification for session " + sessionId);
- obtainMessage(MSG_PRE_REBOOT_VERIFICATION_START, sessionId, -1, session)
- .sendToTarget();
- });
- }
-
- private void onPreRebootVerificationFailure(StagedSession session,
- @SessionInfo.StagedSessionErrorCode int errorCode, String errorMessage) {
- if (!ensureActiveApexSessionIsAborted(session)) {
- Slog.e(TAG, "Failed to abort apex session " + session.sessionId());
- // Safe to ignore active apex session abortion failure since session will be marked
- // failed on next step and staging directory for session will be deleted.
- }
- session.setSessionFailed(errorCode, errorMessage);
- onPreRebootVerificationComplete(session);
- }
-
- // Things to do when pre-reboot verification completes for a particular sessionId
- private void onPreRebootVerificationComplete(StagedSession session) {
- int sessionId = session.sessionId();
- Slog.d(TAG, "Stopping preRebootVerification for session " + sessionId);
- session.notifyEndPreRebootVerification();
- }
-
- private void notifyPreRebootVerification_Start_Complete(
- @NonNull StagedSession session, int rollbackId) {
- obtainMessage(MSG_PRE_REBOOT_VERIFICATION_APEX, session.sessionId(), rollbackId,
- session).sendToTarget();
- }
-
- private void notifyPreRebootVerification_Apex_Complete(
- @NonNull StagedSession session) {
- obtainMessage(MSG_PRE_REBOOT_VERIFICATION_END, session.sessionId(), -1, session)
- .sendToTarget();
- }
-
- /**
- * A placeholder state for starting the pre reboot verification.
- *
- * See {@link PreRebootVerificationHandler} to see all nodes of pre reboot verification
- */
- private void handlePreRebootVerification_Start(@NonNull StagedSession session) {
- try {
- if (session.isMultiPackage()) {
- for (StagedSession s : session.getChildSessions()) {
- checkNonOverlappingWithStagedSessions(s);
- }
- } else {
- checkNonOverlappingWithStagedSessions(session);
- }
- } catch (PackageManagerException e) {
- onPreRebootVerificationFailure(session, e.error, e.getMessage());
- return;
- }
-
- int rollbackId = -1;
- if ((session.sessionParams().installFlags & PackageManager.INSTALL_ENABLE_ROLLBACK)
- != 0) {
- // If rollback is enabled for this session, we call through to the RollbackManager
- // with the list of sessions it must enable rollback for. Note that
- // notifyStagedSession is a synchronous operation.
- final RollbackManagerInternal rm =
- LocalServices.getService(RollbackManagerInternal.class);
- try {
- // NOTE: To stay consistent with the non-staged install flow, we don't fail the
- // entire install if rollbacks can't be enabled.
- rollbackId = rm.notifyStagedSession(session.sessionId());
- } catch (RuntimeException re) {
- Slog.e(TAG, "Failed to notifyStagedSession for session: "
- + session.sessionId(), re);
- }
- } else if (session.sessionParams().installReason
- == PackageManager.INSTALL_REASON_ROLLBACK) {
- try {
- rollbackId = retrieveRollbackIdForCommitSession(session.sessionId());
- } catch (PackageManagerException e) {
- onPreRebootVerificationFailure(session, e.error, e.getMessage());
- return;
- }
- }
-
- notifyPreRebootVerification_Start_Complete(session, rollbackId);
- }
-
- /**
- * Pre-reboot verification state for apex files:
- *
- * <p><ul>
- * <li>submits session to apex service</li>
- * <li>validates signatures of apex files</li>
- * </ul></p>
- */
- private void handlePreRebootVerification_Apex(
- @NonNull StagedSession session, int rollbackId) {
- final boolean hasApex = session.containsApexSession();
-
- // APEX checks. For single-package sessions, check if they contain an APEX. For
- // multi-package sessions, find all the child sessions that contain an APEX.
- if (hasApex) {
- final List<PackageInfo> apexPackages;
- try {
- apexPackages = submitSessionToApexService(session, rollbackId);
- for (int i = 0, size = apexPackages.size(); i < size; i++) {
- validateApexSignature(apexPackages.get(i));
- }
- } catch (PackageManagerException e) {
- onPreRebootVerificationFailure(session, e.error, e.getMessage());
- return;
- }
-
- final PackageManagerInternal packageManagerInternal =
- LocalServices.getService(PackageManagerInternal.class);
- packageManagerInternal.pruneCachedApksInApex(apexPackages);
- }
-
- notifyPreRebootVerification_Apex_Complete(session);
- }
-
- /**
- * Pre-reboot verification state for wrapping up:
- * <p><ul>
- * <li>enables rollback if required</li>
- * <li>marks session as ready</li>
- * </ul></p>
- */
- private void handlePreRebootVerification_End(@NonNull StagedSession session) {
- // Before marking the session as ready, start checkpoint service if available
- try {
- if (PackageHelper.getStorageManager().supportsCheckpoint()) {
- PackageHelper.getStorageManager().startCheckpoint(2);
- }
- } catch (Exception e) {
- // Failed to get hold of StorageManager
- Slog.e(TAG, "Failed to get hold of StorageManager", e);
- onPreRebootVerificationFailure(session, SessionInfo.STAGED_SESSION_UNKNOWN,
- "Failed to get hold of StorageManager");
- return;
- }
-
- // Stop pre-reboot verification before marking session ready. From this point on, if we
- // abandon the session then it will be cleaned up immediately. If session is abandoned
- // after this point, then even if for some reason system tries to install the session
- // or activate its apex, there won't be any files to work with as they will be cleaned
- // up by the system as part of abandonment. If session is abandoned before this point,
- // then the session is already destroyed and cannot be marked ready anymore.
- onPreRebootVerificationComplete(session);
-
- // Proactively mark session as ready before calling apexd. Although this call order
- // looks counter-intuitive, this is the easiest way to ensure that session won't end up
- // in the inconsistent state:
- // - If device gets rebooted right before call to apexd, then apexd will never activate
- // apex files of this staged session. This will result in StagingManager failing
- // the session.
- // On the other hand, if the order of the calls was inverted (first call apexd, then
- // mark session as ready), then if a device gets rebooted right after the call to apexd,
- // only apex part of the train will be applied, leaving device in an inconsistent state.
- Slog.d(TAG, "Marking session " + session.sessionId() + " as ready");
- session.setSessionReady();
- if (session.isSessionReady()) {
- final boolean hasApex = session.containsApexSession();
- if (hasApex) {
- try {
- mApexManager.markStagedSessionReady(session.sessionId());
- notifyStagedApexObservers();
- } catch (PackageManagerException e) {
- session.setSessionFailed(e.error, e.getMessage());
- return;
- }
- }
- }
- }
- }
}
diff --git a/services/core/java/com/android/server/pm/TEST_MAPPING b/services/core/java/com/android/server/pm/TEST_MAPPING
index c8deffb..d54acb7 100644
--- a/services/core/java/com/android/server/pm/TEST_MAPPING
+++ b/services/core/java/com/android/server/pm/TEST_MAPPING
@@ -21,9 +21,6 @@
"name": "CtsAppEnumerationTestCases"
},
{
- "name": "AppEnumerationInternalTests"
- },
- {
"name": "CtsMatchFlagTestCases"
},
{
diff --git a/services/core/java/com/android/server/policy/PhoneWindowManager.java b/services/core/java/com/android/server/policy/PhoneWindowManager.java
index 61076ce..ea3ef650 100644
--- a/services/core/java/com/android/server/policy/PhoneWindowManager.java
+++ b/services/core/java/com/android/server/policy/PhoneWindowManager.java
@@ -21,15 +21,12 @@
import static android.Manifest.permission.SYSTEM_APPLICATION_OVERLAY;
import static android.app.AppOpsManager.OP_SYSTEM_ALERT_WINDOW;
import static android.app.AppOpsManager.OP_TOAST_WINDOW;
-import static android.content.Context.CONTEXT_RESTRICTED;
-import static android.content.Context.WINDOW_SERVICE;
import static android.content.pm.PackageManager.FEATURE_AUTOMOTIVE;
import static android.content.pm.PackageManager.FEATURE_HDMI_CEC;
import static android.content.pm.PackageManager.FEATURE_LEANBACK;
import static android.content.pm.PackageManager.FEATURE_PICTURE_IN_PICTURE;
import static android.content.pm.PackageManager.FEATURE_WATCH;
import static android.content.pm.PackageManager.PERMISSION_GRANTED;
-import static android.content.res.Configuration.EMPTY;
import static android.os.Build.VERSION_CODES.M;
import static android.os.Build.VERSION_CODES.O;
import static android.provider.Settings.Secure.VOLUME_HUSH_OFF;
@@ -47,7 +44,6 @@
import static android.view.WindowManager.LayoutParams.FIRST_APPLICATION_WINDOW;
import static android.view.WindowManager.LayoutParams.FIRST_SUB_WINDOW;
import static android.view.WindowManager.LayoutParams.FIRST_SYSTEM_WINDOW;
-import static android.view.WindowManager.LayoutParams.FLAG_SHOW_WHEN_LOCKED;
import static android.view.WindowManager.LayoutParams.LAST_APPLICATION_WINDOW;
import static android.view.WindowManager.LayoutParams.LAST_SUB_WINDOW;
import static android.view.WindowManager.LayoutParams.LAST_SYSTEM_WINDOW;
@@ -117,13 +113,10 @@
import android.content.pm.PackageManager;
import android.content.pm.ResolveInfo;
import android.content.pm.ServiceInfo;
-import android.content.res.CompatibilityInfo;
import android.content.res.Configuration;
import android.content.res.Resources;
-import android.content.res.TypedArray;
import android.database.ContentObserver;
import android.graphics.Rect;
-import android.graphics.drawable.Drawable;
import android.hardware.display.DisplayManager;
import android.hardware.display.DisplayManagerInternal;
import android.hardware.hdmi.HdmiAudioSystemClient;
@@ -182,7 +175,6 @@
import android.view.KeyCharacterMap.FallbackAction;
import android.view.KeyEvent;
import android.view.MotionEvent;
-import android.view.View;
import android.view.ViewConfiguration;
import android.view.WindowManager;
import android.view.WindowManagerGlobal;
@@ -249,9 +241,7 @@
static final boolean localLOGV = false;
static final boolean DEBUG_INPUT = false;
static final boolean DEBUG_KEYGUARD = false;
- static final boolean DEBUG_SPLASH_SCREEN = false;
static final boolean DEBUG_WAKEUP = false;
- static final boolean SHOW_SPLASH_SCREENS = true;
// Whether to allow dock apps with METADATA_DOCK_HOME to temporarily take over the Home key.
// No longer recommended for desk docks;
@@ -1357,7 +1347,7 @@
}
try {
ActivityManager.getService().startActivityFromRecents(targetTask.persistentId, null);
- } catch (RemoteException e) {
+ } catch (RemoteException | IllegalArgumentException e) {
Slog.e(TAG, "Failed to start task " + targetTask.persistentId + " from recents", e);
}
}
@@ -2354,7 +2344,7 @@
POWER_BUTTON_SUPPRESSION_DELAY_DEFAULT_MILLIS);
if (!mContext.getResources()
.getBoolean(com.android.internal.R.bool.config_volumeHushGestureEnabled)) {
- mRingerToggleChord = Settings.Secure.VOLUME_HUSH_OFF;
+ mRingerToggleChord = VOLUME_HUSH_OFF;
}
// Configure wake gesture.
@@ -2572,191 +2562,6 @@
return attrs.type == TYPE_NOTIFICATION_SHADE;
}
- /** {@inheritDoc} */
- @Override
- public StartingSurface addSplashScreen(IBinder appToken, int userId, String packageName,
- int theme, CompatibilityInfo compatInfo, CharSequence nonLocalizedLabel, int labelRes,
- int icon, int logo, int windowFlags, Configuration overrideConfig, int displayId) {
- if (!SHOW_SPLASH_SCREENS) {
- return null;
- }
- if (packageName == null) {
- return null;
- }
-
- WindowManager wm = null;
- View view = null;
-
- try {
- Context context = mContext;
- if (DEBUG_SPLASH_SCREEN) Slog.d(TAG, "addSplashScreen " + packageName
- + ": nonLocalizedLabel=" + nonLocalizedLabel + " theme="
- + Integer.toHexString(theme));
-
- // Obtain proper context to launch on the right display.
- final Context displayContext = getDisplayContext(context, displayId);
- if (displayContext == null) {
- // Can't show splash screen on requested display, so skip showing at all.
- return null;
- }
- context = displayContext;
-
- if (theme != context.getThemeResId() || labelRes != 0) {
- try {
- context = context.createPackageContextAsUser(packageName, CONTEXT_RESTRICTED,
- UserHandle.of(userId));
- context.setTheme(theme);
- } catch (PackageManager.NameNotFoundException e) {
- Slog.w(TAG, "Failed creating package context with package name "
- + packageName + " for user " + userId, e);
- }
- }
-
- if (overrideConfig != null && !overrideConfig.equals(EMPTY)) {
- if (DEBUG_SPLASH_SCREEN) Slog.d(TAG, "addSplashScreen: creating context based"
- + " on overrideConfig" + overrideConfig + " for splash screen");
- final Context overrideContext = context.createConfigurationContext(overrideConfig);
- overrideContext.setTheme(theme);
- final TypedArray typedArray = overrideContext.obtainStyledAttributes(
- com.android.internal.R.styleable.Window);
- final int resId = typedArray.getResourceId(R.styleable.Window_windowBackground, 0);
- if (resId != 0 && overrideContext.getDrawable(resId) != null) {
- // We want to use the windowBackground for the override context if it is
- // available, otherwise we use the default one to make sure a themed starting
- // window is displayed for the app.
- if (DEBUG_SPLASH_SCREEN) Slog.d(TAG, "addSplashScreen: apply overrideConfig"
- + overrideConfig + " to starting window resId=" + resId);
- context = overrideContext;
- }
- typedArray.recycle();
- }
-
- final PhoneWindow win = new PhoneWindow(context);
- win.setIsStartingWindow(true);
-
- CharSequence label = context.getResources().getText(labelRes, null);
- // Only change the accessibility title if the label is localized
- if (label != null) {
- win.setTitle(label, true);
- } else {
- win.setTitle(nonLocalizedLabel, false);
- }
-
- win.setType(
- WindowManager.LayoutParams.TYPE_APPLICATION_STARTING);
-
- synchronized (mWindowManagerFuncs.getWindowManagerLock()) {
- // Assumes it's safe to show starting windows of launched apps while
- // the keyguard is being hidden. This is okay because starting windows never show
- // secret information.
- // TODO(b/113840485): Occluded may not only happen on default display
- if (displayId == DEFAULT_DISPLAY && isKeyguardOccluded()) {
- windowFlags |= FLAG_SHOW_WHEN_LOCKED;
- }
- }
-
- // Force the window flags: this is a fake window, so it is not really
- // touchable or focusable by the user. We also add in the ALT_FOCUSABLE_IM
- // flag because we do know that the next window will take input
- // focus, so we want to get the IME window up on top of us right away.
- win.setFlags(
- windowFlags|
- WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE|
- WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE|
- WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM,
- windowFlags|
- WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE|
- WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE|
- WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM);
-
- win.setDefaultIcon(icon);
- win.setDefaultLogo(logo);
-
- win.setLayout(WindowManager.LayoutParams.MATCH_PARENT,
- WindowManager.LayoutParams.MATCH_PARENT);
-
- final WindowManager.LayoutParams params = win.getAttributes();
- params.token = appToken;
- params.packageName = packageName;
- params.windowAnimations = win.getWindowStyle().getResourceId(
- com.android.internal.R.styleable.Window_windowAnimationStyle, 0);
- params.privateFlags |= WindowManager.LayoutParams.SYSTEM_FLAG_SHOW_FOR_ALL_USERS;
- // Setting as trusted overlay to let touches pass through. This is safe because this
- // window is controlled by the system.
- params.privateFlags |= WindowManager.LayoutParams.PRIVATE_FLAG_TRUSTED_OVERLAY;
-
- if (!compatInfo.supportsScreen()) {
- params.privateFlags |= WindowManager.LayoutParams.PRIVATE_FLAG_COMPATIBLE_WINDOW;
- }
-
- params.setTitle("Splash Screen " + packageName);
- addSplashscreenContent(win, context);
-
- wm = (WindowManager) context.getSystemService(WINDOW_SERVICE);
- view = win.getDecorView();
-
- if (DEBUG_SPLASH_SCREEN) Slog.d(TAG, "Adding splash screen window for "
- + packageName + " / " + appToken + ": " + (view.getParent() != null ? view : null));
-
- wm.addView(view, params);
-
- // Only return the view if it was successfully added to the
- // window manager... which we can tell by it having a parent.
- return view.getParent() != null ? new SplashScreenSurface(view, appToken) : null;
- } catch (WindowManager.BadTokenException e) {
- // ignore
- Log.w(TAG, appToken + " already running, starting window not displayed. " +
- e.getMessage());
- } catch (RuntimeException e) {
- // don't crash if something else bad happens, for example a
- // failure loading resources because we are loading from an app
- // on external storage that has been unmounted.
- Log.w(TAG, appToken + " failed creating starting window", e);
- } finally {
- if (view != null && view.getParent() == null) {
- Log.w(TAG, "view not successfully added to wm, removing view");
- wm.removeViewImmediate(view);
- }
- }
-
- return null;
- }
-
- private void addSplashscreenContent(PhoneWindow win, Context ctx) {
- final TypedArray a = ctx.obtainStyledAttributes(R.styleable.Window);
- final int resId = a.getResourceId(R.styleable.Window_windowSplashscreenContent, 0);
- a.recycle();
- if (resId == 0) {
- return;
- }
- final Drawable drawable = ctx.getDrawable(resId);
- if (drawable == null) {
- return;
- }
-
- // We wrap this into a view so the system insets get applied to the drawable.
- final View v = new View(ctx);
- v.setBackground(drawable);
- win.setContentView(v);
- }
-
- /** Obtain proper context for showing splash screen on the provided display. */
- private Context getDisplayContext(Context context, int displayId) {
- if (displayId == DEFAULT_DISPLAY) {
- // The default context fits.
- return context;
- }
-
- final Display targetDisplay = mDisplayManager.getDisplay(displayId);
- if (targetDisplay == null) {
- // Failed to obtain the non-default display where splash screen should be shown,
- // lets not show at all.
- return null;
- }
-
- return context.createDisplayContext(targetDisplay);
- }
-
@Override
public Animation createHiddenByKeyguardExit(boolean onWallpaper,
boolean goingToNotificationShade, boolean subtleAnimation) {
@@ -2937,6 +2742,24 @@
Slog.wtf(TAG, "KEYCODE_VOICE_ASSIST should be handled in"
+ " interceptKeyBeforeQueueing");
return key_consumed;
+ case KeyEvent.KEYCODE_VIDEO_APP_1:
+ case KeyEvent.KEYCODE_VIDEO_APP_2:
+ case KeyEvent.KEYCODE_VIDEO_APP_3:
+ case KeyEvent.KEYCODE_VIDEO_APP_4:
+ case KeyEvent.KEYCODE_VIDEO_APP_5:
+ case KeyEvent.KEYCODE_VIDEO_APP_6:
+ case KeyEvent.KEYCODE_VIDEO_APP_7:
+ case KeyEvent.KEYCODE_VIDEO_APP_8:
+ case KeyEvent.KEYCODE_FEATURED_APP_1:
+ case KeyEvent.KEYCODE_FEATURED_APP_2:
+ case KeyEvent.KEYCODE_FEATURED_APP_3:
+ case KeyEvent.KEYCODE_FEATURED_APP_4:
+ case KeyEvent.KEYCODE_DEMO_APP_1:
+ case KeyEvent.KEYCODE_DEMO_APP_2:
+ case KeyEvent.KEYCODE_DEMO_APP_3:
+ case KeyEvent.KEYCODE_DEMO_APP_4:
+ Slog.wtf(TAG, "KEYCODE_APP_X should be handled in interceptKeyBeforeQueueing");
+ return key_consumed;
case KeyEvent.KEYCODE_SYSRQ:
if (down && repeatCount == 0) {
mScreenshotRunnable.setScreenshotType(TAKE_SCREENSHOT_FULLSCREEN);
@@ -4040,6 +3863,26 @@
}
break;
}
+ case KeyEvent.KEYCODE_VIDEO_APP_1:
+ case KeyEvent.KEYCODE_VIDEO_APP_2:
+ case KeyEvent.KEYCODE_VIDEO_APP_3:
+ case KeyEvent.KEYCODE_VIDEO_APP_4:
+ case KeyEvent.KEYCODE_VIDEO_APP_5:
+ case KeyEvent.KEYCODE_VIDEO_APP_6:
+ case KeyEvent.KEYCODE_VIDEO_APP_7:
+ case KeyEvent.KEYCODE_VIDEO_APP_8:
+ case KeyEvent.KEYCODE_FEATURED_APP_1:
+ case KeyEvent.KEYCODE_FEATURED_APP_2:
+ case KeyEvent.KEYCODE_FEATURED_APP_3:
+ case KeyEvent.KEYCODE_FEATURED_APP_4:
+ case KeyEvent.KEYCODE_DEMO_APP_1:
+ case KeyEvent.KEYCODE_DEMO_APP_2:
+ case KeyEvent.KEYCODE_DEMO_APP_3:
+ case KeyEvent.KEYCODE_DEMO_APP_4: {
+ // Just drop if keys are not intercepted for direct key.
+ result &= ~ACTION_PASS_TO_USER;
+ break;
+ }
}
// Intercept the Accessibility keychord (CTRL + ALT + Z) for keyboard users.
@@ -4878,6 +4721,12 @@
return mKeyguardDelegate.isInputRestricted();
}
+ /** {@inheritDoc} */
+ @Override
+ public boolean isKeyguardUnoccluding() {
+ return keyguardOn() && !mWindowManagerFuncs.isAppTransitionStateIdle();
+ }
+
@Override
public void dismissKeyguardLw(IKeyguardDismissCallback callback, CharSequence message) {
if (mKeyguardDelegate != null && mKeyguardDelegate.isShowing()) {
diff --git a/services/core/java/com/android/server/policy/SplashScreenSurface.java b/services/core/java/com/android/server/policy/SplashScreenSurface.java
deleted file mode 100644
index 72933a0..0000000
--- a/services/core/java/com/android/server/policy/SplashScreenSurface.java
+++ /dev/null
@@ -1,55 +0,0 @@
-/*
- * Copyright (C) 2016 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.policy;
-
-import static com.android.server.policy.PhoneWindowManager.DEBUG_SPLASH_SCREEN;
-
-import android.os.Debug;
-import android.os.IBinder;
-import android.util.Slog;
-import android.view.View;
-import android.view.WindowManager;
-
-import com.android.internal.policy.DecorView;
-import com.android.internal.policy.PhoneWindow;
-import com.android.server.policy.WindowManagerPolicy.StartingSurface;
-
-/**
- * Holds the contents of a splash screen starting window, i.e. the {@link DecorView} of a
- * {@link PhoneWindow}. This is just a wrapper such that we can return it from
- * {@link WindowManagerPolicy#addSplashScreen}.
- */
-class SplashScreenSurface implements StartingSurface {
-
- private static final String TAG = PhoneWindowManager.TAG;
- private final View mView;
- private final IBinder mAppToken;
-
- SplashScreenSurface(View view, IBinder appToken) {
- mView = view;
- mAppToken = appToken;
- }
-
- @Override
- public void remove(boolean animate) {
- if (DEBUG_SPLASH_SCREEN) Slog.v(TAG, "Removing splash screen window for " + mAppToken + ": "
- + this + " Callers=" + Debug.getCallers(4));
-
- final WindowManager wm = mView.getContext().getSystemService(WindowManager.class);
- wm.removeView(mView);
- }
-}
diff --git a/services/core/java/com/android/server/policy/WindowManagerPolicy.java b/services/core/java/com/android/server/policy/WindowManagerPolicy.java
index 81dd9c5..5ec2f83 100644
--- a/services/core/java/com/android/server/policy/WindowManagerPolicy.java
+++ b/services/core/java/com/android/server/policy/WindowManagerPolicy.java
@@ -69,7 +69,6 @@
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.content.Context;
-import android.content.res.CompatibilityInfo;
import android.content.res.Configuration;
import android.graphics.Rect;
import android.os.Bundle;
@@ -224,21 +223,6 @@
}
/**
- * Holds the contents of a starting window. {@link #addSplashScreen} needs to wrap the
- * contents of the starting window into an class implementing this interface, which then will be
- * held by WM and released with {@link #remove} when no longer needed.
- */
- interface StartingSurface {
-
- /**
- * Removes the starting window surface. Do not hold the window manager lock when calling
- * this method!
- * @param animate Whether need to play the default exit animation for starting window.
- */
- void remove(boolean animate);
- }
-
- /**
* Interface for calling back in to the window manager that is private
* between it and the policy.
*/
@@ -362,6 +346,12 @@
* as the top display.
*/
void moveDisplayToTop(int displayId);
+
+ /**
+ * Return whether the app transition state is idle.
+ * @return {@code true} if app transition state is idle on the default display.
+ */
+ boolean isAppTransitionStateIdle();
}
/**
@@ -533,43 +523,44 @@
case TYPE_PHONE:
return 3;
case TYPE_SEARCH_BAR:
- case TYPE_VOICE_INTERACTION_STARTING:
return 4;
- case TYPE_VOICE_INTERACTION:
- // voice interaction layer is almost immediately above apps.
- return 5;
case TYPE_INPUT_CONSUMER:
- return 6;
+ return 5;
case TYPE_SYSTEM_DIALOG:
- return 7;
+ return 6;
case TYPE_TOAST:
// toasts and the plugged-in battery thing
- return 8;
+ return 7;
case TYPE_PRIORITY_PHONE:
// SIM errors and unlock. Not sure if this really should be in a high layer.
- return 9;
+ return 8;
case TYPE_SYSTEM_ALERT:
// like the ANR / app crashed dialogs
// Type is deprecated for non-system apps. For system apps, this type should be
// in a higher layer than TYPE_APPLICATION_OVERLAY.
- return canAddInternalSystemWindow ? 13 : 10;
+ return canAddInternalSystemWindow ? 12 : 9;
case TYPE_APPLICATION_OVERLAY:
- return 12;
+ return 11;
case TYPE_INPUT_METHOD:
// on-screen keyboards and other such input method user interfaces go here.
- return 15;
+ return 13;
case TYPE_INPUT_METHOD_DIALOG:
// on-screen keyboards and other such input method user interfaces go here.
- return 16;
+ return 14;
case TYPE_STATUS_BAR:
- return 17;
+ return 15;
case TYPE_STATUS_BAR_ADDITIONAL:
- return 18;
+ return 16;
case TYPE_NOTIFICATION_SHADE:
- return 19;
+ return 17;
case TYPE_STATUS_BAR_SUB_PANEL:
- return 20;
+ return 18;
case TYPE_KEYGUARD_DIALOG:
+ return 19;
+ case TYPE_VOICE_INTERACTION_STARTING:
+ return 20;
+ case TYPE_VOICE_INTERACTION:
+ // voice interaction layer should show above the lock screen.
return 21;
case TYPE_VOLUME_OVERLAY:
// the on-screen volume indicator and controller shown when the user
@@ -578,7 +569,7 @@
case TYPE_SYSTEM_OVERLAY:
// the on-screen volume indicator and controller shown when the user
// changes the device volume
- return canAddInternalSystemWindow ? 23 : 11;
+ return canAddInternalSystemWindow ? 23 : 10;
case TYPE_NAVIGATION_BAR:
// the navigation bar, if available, shows atop most things
return 24;
@@ -591,7 +582,7 @@
return 26;
case TYPE_SYSTEM_ERROR:
// system-level error dialogs
- return canAddInternalSystemWindow ? 27 : 10;
+ return canAddInternalSystemWindow ? 27 : 9;
case TYPE_MAGNIFICATION_OVERLAY:
// used to highlight the magnified portion of a display
return 28;
@@ -687,33 +678,6 @@
}
/**
- * Called when the system would like to show a UI to indicate that an
- * application is starting. You can use this to add a
- * APPLICATION_STARTING_TYPE window with the given appToken to the window
- * manager (using the normal window manager APIs) that will be shown until
- * the application displays its own window. This is called without the
- * window manager locked so that you can call back into it.
- *
- * @param appToken Token of the application being started.
- * @param packageName The name of the application package being started.
- * @param theme Resource defining the application's overall visual theme.
- * @param nonLocalizedLabel The default title label of the application if
- * no data is found in the resource.
- * @param labelRes The resource ID the application would like to use as its name.
- * @param icon The resource ID the application would like to use as its icon.
- * @param windowFlags Window layout flags.
- * @param overrideConfig override configuration to consider when generating
- * context to for resources.
- * @param displayId Id of the display to show the splash screen at.
- *
- * @return The starting surface.
- *
- */
- StartingSurface addSplashScreen(IBinder appToken, int userId, String packageName,
- int theme, CompatibilityInfo compatInfo, CharSequence nonLocalizedLabel, int labelRes,
- int icon, int logo, int windowFlags, Configuration overrideConfig, int displayId);
-
- /**
* Create and return an animation to re-display a window that was force hidden by Keyguard.
*/
public Animation createHiddenByKeyguardExit(boolean onWallpaper,
@@ -962,6 +926,14 @@
public boolean isKeyguardOccluded();
/**
+ * Return whether the keyguard is unoccluding.
+ * @return {@code true} if the keyguard is unoccluding.
+ */
+ default boolean isKeyguardUnoccluding() {
+ return false;
+ }
+
+ /**
* @return true if in keyguard is on.
*/
boolean isKeyguardShowing();
diff --git a/services/core/java/com/android/server/security/OWNERS b/services/core/java/com/android/server/security/OWNERS
index e6f5826..41070f3 100644
--- a/services/core/java/com/android/server/security/OWNERS
+++ b/services/core/java/com/android/server/security/OWNERS
@@ -1,3 +1,4 @@
# Bug component: 36824
+per-file AttestationVerificationService.java = file:/core/java/android/security/attestationverification/OWNERS
per-file FileIntegrityService.java = victorhsieh@google.com
diff --git a/services/core/java/com/android/server/stats/pull/StatsPullAtomService.java b/services/core/java/com/android/server/stats/pull/StatsPullAtomService.java
index 106cff1..0c78494 100644
--- a/services/core/java/com/android/server/stats/pull/StatsPullAtomService.java
+++ b/services/core/java/com/android/server/stats/pull/StatsPullAtomService.java
@@ -29,6 +29,7 @@
import static android.net.NetworkIdentity.OEM_PRIVATE;
import static android.net.NetworkStats.DEFAULT_NETWORK_ALL;
import static android.net.NetworkStats.METERED_ALL;
+import static android.net.NetworkStats.METERED_YES;
import static android.net.NetworkStats.ROAMING_ALL;
import static android.net.NetworkTemplate.MATCH_ETHERNET;
import static android.net.NetworkTemplate.MATCH_MOBILE_WILDCARD;
@@ -1348,7 +1349,7 @@
@Nullable private NetworkStats getUidNetworkStatsSnapshotForTransport(int transport) {
final NetworkTemplate template = (transport == TRANSPORT_CELLULAR)
? NetworkTemplate.buildTemplateMobileWithRatType(
- /*subscriptionId=*/null, NETWORK_TYPE_ALL)
+ /*subscriptionId=*/null, NETWORK_TYPE_ALL, METERED_YES)
: NetworkTemplate.buildTemplateWifiWildcard();
return getUidNetworkStatsSnapshotForTemplate(template, /*includeTags=*/false);
}
@@ -1388,7 +1389,8 @@
final List<NetworkStatsExt> ret = new ArrayList<>();
for (final int ratType : getAllCollapsedRatTypes()) {
final NetworkTemplate template =
- buildTemplateMobileWithRatType(subInfo.subscriberId, ratType);
+ buildTemplateMobileWithRatType(subInfo.subscriberId, ratType,
+ METERED_YES);
final NetworkStats stats =
getUidNetworkStatsSnapshotForTemplate(template, /*includeTags=*/false);
if (stats != null) {
@@ -1609,7 +1611,7 @@
int pullBluetoothBytesTransferLocked(int atomTag, List<StatsEvent> pulledData) {
BluetoothActivityEnergyInfo info = fetchBluetoothData();
- if (info == null || info.getUidTraffic() == null) {
+ if (info == null) {
return StatsManager.PULL_SKIP;
}
for (UidTraffic traffic : info.getUidTraffic()) {
@@ -2067,7 +2069,7 @@
if (info == null) {
return StatsManager.PULL_SKIP;
}
- pulledData.add(FrameworkStatsLog.buildStatsEvent(atomTag, info.getTimeStamp(),
+ pulledData.add(FrameworkStatsLog.buildStatsEvent(atomTag, info.getTimestampMillis(),
info.getBluetoothStackState(), info.getControllerTxTimeMillis(),
info.getControllerRxTimeMillis(), info.getControllerIdleTimeMillis(),
info.getControllerEnergyUsed()));
diff --git a/services/core/java/com/android/server/statusbar/StatusBarManagerService.java b/services/core/java/com/android/server/statusbar/StatusBarManagerService.java
index 00d01e1..a0f0367 100644
--- a/services/core/java/com/android/server/statusbar/StatusBarManagerService.java
+++ b/services/core/java/com/android/server/statusbar/StatusBarManagerService.java
@@ -97,6 +97,7 @@
import java.io.FileDescriptor;
import java.io.PrintWriter;
import java.util.ArrayList;
+import java.util.concurrent.TimeUnit;
/**
* A note on locking: We rely on the fact that calls onto mBar are oneway or
@@ -142,6 +143,10 @@
@GuardedBy("mLock")
private IUdfpsHbmListener mUdfpsHbmListener;
+ @GuardedBy("mCurrentRequestAddTilePackages")
+ private final ArrayMap<String, Long> mCurrentRequestAddTilePackages = new ArrayMap<>();
+ private static final long REQUEST_TIME_OUT = TimeUnit.MINUTES.toNanos(5);
+
private class DeathRecipient implements IBinder.DeathRecipient {
public void binderDied() {
mBar.asBinder().unlinkToDeath(this,0);
@@ -1742,13 +1747,39 @@
return;
}
+ synchronized (mCurrentRequestAddTilePackages) {
+ Long lastTime = mCurrentRequestAddTilePackages.get(packageName);
+ final long currentTime = System.nanoTime();
+ if (lastTime != null && currentTime - lastTime < REQUEST_TIME_OUT) {
+ try {
+ callback.onTileRequest(
+ StatusBarManager.TILE_ADD_REQUEST_ERROR_REQUEST_IN_PROGRESS);
+ } catch (RemoteException e) {
+ Slog.e(TAG, "requestAddTile", e);
+ }
+ return;
+ } else {
+ if (lastTime != null) {
+ cancelRequestAddTileInternal(packageName);
+ }
+ }
+
+ mCurrentRequestAddTilePackages.put(packageName, currentTime);
+ }
+
IAddTileResultCallback proxyCallback = new IAddTileResultCallback.Stub() {
@Override
- public void onTileRequest(int i) throws RemoteException {
+ public void onTileRequest(int i) {
if (i == StatusBarManager.TILE_ADD_REQUEST_RESULT_DIALOG_DISMISSED) {
i = StatusBarManager.TILE_ADD_REQUEST_RESULT_TILE_NOT_ADDED;
}
- callback.onTileRequest(i);
+ if (clearTileAddRequest(packageName)) {
+ try {
+ callback.onTileRequest(i);
+ } catch (RemoteException e) {
+ Slog.e(TAG, "requestAddTile - callback", e);
+ }
+ }
}
};
@@ -1757,11 +1788,12 @@
if (mBar != null) {
try {
mBar.requestAddTile(componentName, appName, label, icon, proxyCallback);
+ return;
} catch (RemoteException e) {
Slog.e(TAG, "requestAddTile", e);
}
- return;
}
+ clearTileAddRequest(packageName);
try {
callback.onTileRequest(StatusBarManager.TILE_ADD_REQUEST_ERROR_NO_STATUS_BAR_SERVICE);
} catch (RemoteException e) {
@@ -1769,6 +1801,29 @@
}
}
+ @Override
+ public void cancelRequestAddTile(@NonNull String packageName) {
+ enforceStatusBar();
+ cancelRequestAddTileInternal(packageName);
+ }
+
+ private void cancelRequestAddTileInternal(String packageName) {
+ clearTileAddRequest(packageName);
+ if (mBar != null) {
+ try {
+ mBar.cancelRequestAddTile(packageName);
+ } catch (RemoteException e) {
+ Slog.e(TAG, "requestAddTile", e);
+ }
+ }
+ }
+
+ private boolean clearTileAddRequest(String packageName) {
+ synchronized (mCurrentRequestAddTilePackages) {
+ return mCurrentRequestAddTilePackages.remove(packageName) != null;
+ }
+ }
+
public String[] getStatusBarIcons() {
return mContext.getResources().getStringArray(R.array.config_statusBarIcons);
}
@@ -1898,6 +1953,16 @@
}
pw.println();
}
+ ArrayList<String> requests;
+ synchronized (mCurrentRequestAddTilePackages) {
+ requests = new ArrayList<>(mCurrentRequestAddTilePackages.keySet());
+ }
+ pw.println(" mCurrentRequestAddTilePackages=[");
+ final int reqN = requests.size();
+ for (int i = 0; i < reqN; i++) {
+ pw.println(" " + requests.get(i) + ",");
+ }
+ pw.println(" ]");
}
}
diff --git a/services/core/java/com/android/server/textclassifier/TextClassificationManagerService.java b/services/core/java/com/android/server/textclassifier/TextClassificationManagerService.java
index 0f37450..e98fa28 100644
--- a/services/core/java/com/android/server/textclassifier/TextClassificationManagerService.java
+++ b/services/core/java/com/android/server/textclassifier/TextClassificationManagerService.java
@@ -86,6 +86,9 @@
private static final String LOG_TAG = "TextClassificationManagerService";
+ // TODO: consider using device config to control it.
+ private static final boolean DEBUG = false;
+
private static final ITextClassifierCallback NO_OP_CALLBACK = new ITextClassifierCallback() {
@Override
public void onSuccess(Bundle result) {}
@@ -175,8 +178,6 @@
private final String mDefaultTextClassifierPackage;
@Nullable
private final String mSystemTextClassifierPackage;
- // TODO: consider using device config to control it.
- private boolean DEBUG = false;
private TextClassificationManagerService(Context context) {
mContext = Objects.requireNonNull(context);
diff --git a/services/core/java/com/android/server/tv/TvInputHardwareManager.java b/services/core/java/com/android/server/tv/TvInputHardwareManager.java
index 92e0845..f57a852 100755
--- a/services/core/java/com/android/server/tv/TvInputHardwareManager.java
+++ b/services/core/java/com/android/server/tv/TvInputHardwareManager.java
@@ -1075,17 +1075,22 @@
}
if (shouldRecreateAudioPatch) {
mCommittedVolume = volume;
- if (mAudioPatch != null) {
- mAudioManager.releaseAudioPatch(mAudioPatch);
- }
- mAudioManager.createAudioPatch(
+ // only recreate if something was updated or audioPath is null
+ if (mAudioPatch == null || sinkUpdated ||sourceUpdated ) {
+ if (mAudioPatch != null) {
+ mAudioManager.releaseAudioPatch(mAudioPatch);
+ audioPatchArray[0] = null;
+ }
+ mAudioManager.createAudioPatch(
audioPatchArray,
new AudioPortConfig[] { sourceConfig },
sinkConfigs.toArray(new AudioPortConfig[sinkConfigs.size()]));
- mAudioPatch = audioPatchArray[0];
- if (sourceGainConfig != null) {
- mAudioManager.setAudioPortGain(mAudioSource, sourceGainConfig);
+ mAudioPatch = audioPatchArray[0];
}
+ }
+
+ if (sourceGainConfig != null) {
+ mAudioManager.setAudioPortGain(mAudioSource, sourceGainConfig);
}
}
diff --git a/services/core/java/com/android/server/tv/interactive/TvIAppManagerService.java b/services/core/java/com/android/server/tv/interactive/TvIAppManagerService.java
index c4e5660..d09eceb 100644
--- a/services/core/java/com/android/server/tv/interactive/TvIAppManagerService.java
+++ b/services/core/java/com/android/server/tv/interactive/TvIAppManagerService.java
@@ -86,8 +86,7 @@
if (DEBUG) {
Slogf.d(TAG, "onStart");
}
- // TODO: make service name a constant in Context
- publishBinderService("tv_interactive_app", new BinderService());
+ publishBinderService(Context.TV_IAPP_SERVICE, new BinderService());
}
private SessionState getSessionState(IBinder sessionToken) {
diff --git a/services/core/java/com/android/server/wm/AccessibilityController.java b/services/core/java/com/android/server/wm/AccessibilityController.java
index fb337e2..3d83995 100644
--- a/services/core/java/com/android/server/wm/AccessibilityController.java
+++ b/services/core/java/com/android/server/wm/AccessibilityController.java
@@ -137,7 +137,7 @@
new SparseArray<>();
private SparseArray<IBinder> mFocusedWindow = new SparseArray<>();
private int mFocusedDisplay = -1;
-
+ private boolean mIsImeVisible = false;
// Set to true if initializing window population complete.
private boolean mAllObserversInitialized = true;
@@ -490,15 +490,19 @@
}
}
- void onImeSurfaceShownChanged(WindowState windowState, boolean shown) {
+ void updateImeVisibilityIfNeeded(int displayId, boolean shown) {
if (mAccessibilityTracing.isTracingEnabled(FLAGS_MAGNIFICATION_CALLBACK)) {
- mAccessibilityTracing.logTrace(TAG + ".onImeSurfaceShownChanged",
- FLAGS_MAGNIFICATION_CALLBACK, "windowState=" + windowState + ";shown=" + shown);
+ mAccessibilityTracing.logTrace(TAG + ".updateImeVisibilityIfNeeded",
+ FLAGS_MAGNIFICATION_CALLBACK, "displayId=" + displayId + ";shown=" + shown);
}
- final int displayId = windowState.getDisplayId();
+ if (mIsImeVisible == shown) {
+ return;
+ }
+
+ mIsImeVisible = shown;
final DisplayMagnifier displayMagnifier = mDisplayMagnifiers.get(displayId);
if (displayMagnifier != null) {
- displayMagnifier.onImeSurfaceShownChanged(shown);
+ displayMagnifier.notifyImeWindowVisibilityChanged(shown);
}
}
@@ -767,9 +771,9 @@
}
}
- void onImeSurfaceShownChanged(boolean shown) {
+ void notifyImeWindowVisibilityChanged(boolean shown) {
if (mAccessibilityTracing.isTracingEnabled(FLAGS_MAGNIFICATION_CALLBACK)) {
- mAccessibilityTracing.logTrace(LOG_TAG + ".onImeSurfaceShownChanged",
+ mAccessibilityTracing.logTrace(LOG_TAG + ".notifyImeWindowVisibilityChanged",
FLAGS_MAGNIFICATION_CALLBACK, "shown=" + shown);
}
mHandler.obtainMessage(MyHandler.MESSAGE_NOTIFY_IME_WINDOW_VISIBILITY_CHANGED,
@@ -2178,15 +2182,15 @@
int callingUid, StackTraceElement[] callingStack, long timeStamp,
String processName, String threadName, Set<String> ignoreStackEntries) {
SomeArgs args = SomeArgs.obtain();
- args.arg1 = timeStamp;
- args.arg2 = loggingTypes;
- args.arg3 = where;
- args.arg4 = processName;
- args.arg5 = threadName;
- args.arg6 = ignoreStackEntries;
- args.arg7 = callingParams;
- args.arg8 = callingStack;
- args.arg9 = a11yDump;
+ args.argl1 = timeStamp;
+ args.argl2 = loggingTypes;
+ args.arg1 = where;
+ args.arg2 = processName;
+ args.arg3 = threadName;
+ args.arg4 = ignoreStackEntries;
+ args.arg5 = callingParams;
+ args.arg6 = callingStack;
+ args.arg7 = a11yDump;
mHandler.obtainMessage(
LogHandler.MESSAGE_LOG_TRACE_ENTRY, callingUid, 0, args).sendToTarget();
@@ -2219,7 +2223,7 @@
long tokenOuter = os.start(ENTRY);
- long reportedTimeStampNanos = (long) args.arg1;
+ long reportedTimeStampNanos = args.argl1;
long currentElapsedRealtimeNanos = SystemClock.elapsedRealtimeNanos();
long timeDiffNanos =
currentElapsedRealtimeNanos - reportedTimeStampNanos;
@@ -2231,24 +2235,24 @@
os.write(ELAPSED_REALTIME_NANOS, reportedTimeStampNanos);
os.write(CALENDAR_TIME, fm.format(reportedTimeMillis).toString());
- long loggingTypes = (long) args.arg2;
+ long loggingTypes = args.argl2;
List<String> loggingTypeNames =
AccessibilityTrace.getNamesOfLoggingTypes(loggingTypes);
for (String type : loggingTypeNames) {
os.write(LOGGING_TYPE, type);
}
- os.write(WHERE, (String) args.arg3);
- os.write(PROCESS_NAME, (String) args.arg4);
- os.write(THREAD_ID_NAME, (String) args.arg5);
+ os.write(WHERE, (String) args.arg1);
+ os.write(PROCESS_NAME, (String) args.arg2);
+ os.write(THREAD_ID_NAME, (String) args.arg3);
os.write(CALLING_PKG, pmInternal.getNameForUid(message.arg1));
- os.write(CALLING_PARAMS, (String) args.arg7);
+ os.write(CALLING_PARAMS, (String) args.arg5);
String callingStack = toStackTraceString(
- (StackTraceElement[]) args.arg8, (Set<String>) args.arg6);
+ (StackTraceElement[]) args.arg6, (Set<String>) args.arg4);
os.write(CALLING_STACKS, callingStack);
- os.write(ACCESSIBILITY_SERVICE, (byte[]) args.arg9);
+ os.write(ACCESSIBILITY_SERVICE, (byte[]) args.arg7);
long tokenInner = os.start(WINDOW_MANAGER_SERVICE);
synchronized (mService.mGlobalLock) {
diff --git a/services/core/java/com/android/server/wm/ActivityRecord.java b/services/core/java/com/android/server/wm/ActivityRecord.java
index ab61a4b..7fea29c7 100644
--- a/services/core/java/com/android/server/wm/ActivityRecord.java
+++ b/services/core/java/com/android/server/wm/ActivityRecord.java
@@ -86,8 +86,6 @@
import static android.content.pm.ActivityInfo.SIZE_CHANGES_SUPPORTED_METADATA;
import static android.content.pm.ActivityInfo.SIZE_CHANGES_SUPPORTED_OVERRIDE;
import static android.content.pm.ActivityInfo.SIZE_CHANGES_UNSUPPORTED_OVERRIDE;
-import static android.content.pm.ActivityInfo.isFixedOrientationLandscape;
-import static android.content.pm.ActivityInfo.isFixedOrientationPortrait;
import static android.content.res.Configuration.ASSETS_SEQ_UNDEFINED;
import static android.content.res.Configuration.EMPTY;
import static android.content.res.Configuration.ORIENTATION_LANDSCAPE;
@@ -105,7 +103,6 @@
import static android.view.Surface.ROTATION_90;
import static android.view.SurfaceControl.getGlobalTransaction;
import static android.view.WindowManager.LayoutParams.FLAG_DISMISS_KEYGUARD;
-import static android.view.WindowManager.LayoutParams.FLAG_SHOW_WALLPAPER;
import static android.view.WindowManager.LayoutParams.FLAG_SHOW_WHEN_LOCKED;
import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION;
import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION_STARTING;
@@ -335,7 +332,6 @@
import com.android.server.am.PendingIntentRecord;
import com.android.server.contentcapture.ContentCaptureManagerInternal;
import com.android.server.display.color.ColorDisplayService;
-import com.android.server.policy.WindowManagerPolicy;
import com.android.server.uri.NeededUriGrants;
import com.android.server.uri.UriPermissionOwner;
import com.android.server.wm.ActivityMetricsLogger.TransitionInfoSnapshot;
@@ -453,9 +449,7 @@
private CharSequence nonLocalizedLabel; // the label information from the package mgr.
private int labelRes; // the label information from the package mgr.
private int icon; // resource identifier of activity's icon.
- private int logo; // resource identifier of activity's logo.
private int theme; // resource identifier of activity's theme.
- private int windowFlags; // custom window flags for preview window.
private Task task; // the task this is in.
private long createTime = System.currentTimeMillis();
long lastVisibleTime; // last time this activity became visible
@@ -737,7 +731,7 @@
// Note: these are de-referenced before the starting window animates away.
StartingData mStartingData;
WindowState mStartingWindow;
- WindowManagerPolicy.StartingSurface mStartingSurface;
+ StartingSurfaceController.StartingSurface mStartingSurface;
boolean startingDisplayed;
boolean startingMoved;
@@ -1141,10 +1135,11 @@
if (info.getMaxAspectRatio() != 0) {
pw.println(prefix + "maxAspectRatio=" + info.getMaxAspectRatio());
}
- if (info.getMinAspectRatio() != 0) {
- pw.println(prefix + "minAspectRatio=" + info.getMinAspectRatio());
+ final float minAspectRatio = getMinAspectRatio();
+ if (minAspectRatio != 0) {
+ pw.println(prefix + "minAspectRatio=" + minAspectRatio);
}
- if (info.getMinAspectRatio() != info.getManifestMinAspectRatio()) {
+ if (minAspectRatio != info.getManifestMinAspectRatio()) {
// Log the fact that we've overridden the min aspect ratio from the manifest
pw.println(prefix + "manifestMinAspectRatio="
+ info.getManifestMinAspectRatio());
@@ -1443,13 +1438,7 @@
}
final Task rootTask = getRootTask();
- // If we reparent, make sure to remove ourselves from the old animation registry.
- if (mAnimatingActivityRegistry != null) {
- mAnimatingActivityRegistry.notifyFinished(this);
- }
- mAnimatingActivityRegistry = rootTask != null
- ? rootTask.getAnimatingActivityRegistry()
- : null;
+ updateAnimatingActivityRegistry();
if (task == mLastParentBeforePip) {
// Activity's reparented back from pip, clear the links once established
@@ -1482,6 +1471,20 @@
}
}
+ void updateAnimatingActivityRegistry() {
+ final Task rootTask = getRootTask();
+ final AnimatingActivityRegistry registry = rootTask != null
+ ? rootTask.getAnimatingActivityRegistry()
+ : null;
+
+ // If we reparent, make sure to remove ourselves from the old animation registry.
+ if (mAnimatingActivityRegistry != null && mAnimatingActivityRegistry != registry) {
+ mAnimatingActivityRegistry.notifyFinished(this);
+ }
+
+ mAnimatingActivityRegistry = registry;
+ }
+
/**
* Sets {@link #mLastParentBeforePip} to the current parent Task, it's caller's job to ensure
* {@link #getTask()} is set before this is called.
@@ -1735,11 +1738,7 @@
labelRes = app.labelRes;
}
icon = aInfo.getIconResource();
- logo = aInfo.getLogoResource();
theme = aInfo.getThemeResource();
- if ((aInfo.flags & ActivityInfo.FLAG_HARDWARE_ACCELERATED) != 0) {
- windowFlags |= LayoutParams.FLAG_HARDWARE_ACCELERATED;
- }
if ((aInfo.flags & FLAG_MULTIPROCESS) != 0 && _caller != null
&& (aInfo.applicationInfo.uid == SYSTEM_UID
|| aInfo.applicationInfo.uid == _caller.mInfo.uid)) {
@@ -1972,33 +1971,10 @@
return true;
}
- private void applyStartingWindowTheme(String pkg, int theme) {
- if (theme != 0) {
- AttributeCache.Entry ent = AttributeCache.instance().get(pkg, theme,
- com.android.internal.R.styleable.Window,
- mWmService.mCurrentUserId);
- if (ent == null) {
- return;
- }
- final boolean windowShowWallpaper = ent.array.getBoolean(
- com.android.internal.R.styleable.Window_windowShowWallpaper, false);
- if (windowShowWallpaper && getDisplayContent().mWallpaperController
- .getWallpaperTarget() == null) {
- // If this theme is requesting a wallpaper, and the wallpaper
- // is not currently visible, then this effectively serves as
- // an opaque window and our starting window transition animation
- // can still work. We just need to make sure the starting window
- // is also showing the wallpaper.
- windowFlags |= FLAG_SHOW_WALLPAPER;
- }
- }
- }
-
@VisibleForTesting
- boolean addStartingWindow(String pkg, int resolvedTheme, CompatibilityInfo compatInfo,
- CharSequence nonLocalizedLabel, int labelRes, int icon, int logo, int windowFlags,
- ActivityRecord from, boolean newTask, boolean taskSwitch, boolean processRunning,
- boolean allowTaskSnapshot, boolean activityCreated, boolean useEmpty,
+ boolean addStartingWindow(String pkg, int resolvedTheme, ActivityRecord from, boolean newTask,
+ boolean taskSwitch, boolean processRunning, boolean allowTaskSnapshot,
+ boolean activityCreated, boolean useEmpty,
boolean activityAllDrawn) {
// If the display is frozen, we won't do anything until the actual window is
// displayed so there is no reason to put in the starting window.
@@ -2055,7 +2031,6 @@
if (resolvedTheme == 0 && theme != 0) {
return false;
}
- applyStartingWindowTheme(pkg, resolvedTheme);
if (from != null && transferStartingWindow(from)) {
return true;
@@ -2068,9 +2043,7 @@
}
ProtoLog.v(WM_DEBUG_STARTING_WINDOW, "Creating SplashScreenStartingData");
- mStartingData = new SplashScreenStartingData(mWmService, pkg,
- resolvedTheme, compatInfo, nonLocalizedLabel, labelRes, icon, logo, windowFlags,
- getMergedOverrideConfiguration(), typeParameter);
+ mStartingData = new SplashScreenStartingData(mWmService, resolvedTheme, typeParameter);
scheduleAddStartingWindow();
return true;
}
@@ -2092,17 +2065,7 @@
}
void scheduleAddStartingWindow() {
- if (StartingSurfaceController.DEBUG_ENABLE_SHELL_DRAWER) {
- mAddStartingWindow.run();
- } else {
- // Note: we really want to do sendMessageAtFrontOfQueue() because we
- // want to process the message ASAP, before any other queued
- // messages.
- if (!mWmService.mAnimationHandler.hasCallbacks(mAddStartingWindow)) {
- ProtoLog.v(WM_DEBUG_STARTING_WINDOW, "Enqueueing ADD_STARTING");
- mWmService.mAnimationHandler.postAtFrontOfQueue(mAddStartingWindow);
- }
- }
+ mAddStartingWindow.run();
}
private class AddStartingWindow implements Runnable {
@@ -2113,9 +2076,6 @@
final StartingData startingData;
synchronized (mWmService.mGlobalLock) {
// There can only be one adding request, silly caller!
- if (!StartingSurfaceController.DEBUG_ENABLE_SHELL_DRAWER) {
- mWmService.mAnimationHandler.removeCallbacks(this);
- }
if (mStartingData == null) {
// Animation has been canceled... do nothing.
@@ -2130,7 +2090,7 @@
ProtoLog.v(WM_DEBUG_STARTING_WINDOW, "Add starting %s: startingData=%s",
this, startingData);
- WindowManagerPolicy.StartingSurface surface = null;
+ StartingSurfaceController.StartingSurface surface = null;
try {
surface = startingData.createStartingSurface(ActivityRecord.this);
} catch (Exception e) {
@@ -2243,9 +2203,6 @@
}
private boolean transferSplashScreenIfNeeded() {
- if (!mWmService.mStartingSurfaceController.DEBUG_ENABLE_SHELL_DRAWER) {
- return false;
- }
if (!mHandleExitSplashScreen || mStartingSurface == null || mStartingWindow == null
|| mTransferringSplashScreenState == TRANSFER_SPLASH_SCREEN_FINISH) {
return false;
@@ -2386,7 +2343,7 @@
return;
}
- final WindowManagerPolicy.StartingSurface surface;
+ final StartingSurfaceController.StartingSurface surface;
final StartingData startingData = mStartingData;
if (mStartingData != null) {
surface = mStartingSurface;
@@ -2420,13 +2377,7 @@
}
};
- if (StartingSurfaceController.DEBUG_ENABLE_SHELL_DRAWER) {
- removeSurface.run();
- } else {
- // Use the same thread to remove the window as we used to add it, as otherwise we end up
- // with things in the view hierarchy being called from different threads.
- mWmService.mAnimationHandler.post(removeSurface);
- }
+ removeSurface.run();
}
/**
@@ -3039,9 +2990,6 @@
mAtmService.deferWindowLayout();
try {
- final Transition newTransition = (!mTransitionController.isCollecting()
- && mTransitionController.getTransitionPlayer() != null)
- ? mTransitionController.createTransition(TRANSIT_CLOSE) : null;
mTaskSupervisor.mNoHistoryActivities.remove(this);
makeFinishingLocked();
// Make a local reference to its task since this.task could be set to null once this
@@ -3073,10 +3021,7 @@
final boolean endTask = task.getTopNonFinishingActivity() == null
&& !task.isClearingToReuseTask();
- if (newTransition != null) {
- mTransitionController.requestStartTransition(newTransition,
- endTask ? task : null, null /* remote */);
- }
+ mTransitionController.requestCloseTransitionIfNeeded(endTask ? task : this);
if (isState(RESUMED)) {
if (endTask) {
mAtmService.getTaskChangeNotificationController().notifyTaskRemovalStarted(
@@ -3502,13 +3447,6 @@
if (stopped) {
abortAndClearOptionsAnimation();
}
- if (mTransitionController.isCollecting()) {
- // We don't want the finishing to change the transition ready state since there will not
- // be corresponding setReady for finishing.
- mTransitionController.collectExistenceChange(this);
- } else {
- mTransitionController.requestTransitionIfNeeded(TRANSIT_CLOSE, this);
- }
}
/**
@@ -3602,6 +3540,10 @@
if (mPendingRelaunchCount > 0) {
mPendingRelaunchCount--;
+ if (mPendingRelaunchCount == 0 && !isClientVisible()) {
+ // Don't count if the client won't report drawn.
+ mRelaunchStartTime = 0;
+ }
} else {
// Update keyguard flags upon finishing relaunch.
checkKeyguardFlagsChanged();
@@ -3686,6 +3628,7 @@
// to the restarted activity.
nowVisible = mVisibleRequested;
}
+ mTransitionController.requestCloseTransitionIfNeeded(this);
cleanUp(true /* cleanServices */, true /* setState */);
if (remove) {
if (mStartingData != null && mVisible && task != null) {
@@ -4104,19 +4047,40 @@
* conditions a) above.
* Multi-windowing mode will be exited if {@code true} is returned.
*/
- boolean canShowWhenLocked() {
- if (!inPinnedWindowingMode() && (mShowWhenLocked || containsShowWhenLockedWindow())) {
+ private static boolean canShowWhenLocked(ActivityRecord r) {
+ if (r == null || r.getTaskFragment() == null) {
+ return false;
+ }
+ if (!r.inPinnedWindowingMode() && (r.mShowWhenLocked || r.containsShowWhenLockedWindow())) {
return true;
- } else if (mInheritShownWhenLocked) {
- final ActivityRecord r = task.getActivityBelow(this);
- return r != null && !r.inPinnedWindowingMode() && (r.mShowWhenLocked
- || r.containsShowWhenLockedWindow());
+ } else if (r.mInheritShownWhenLocked) {
+ final ActivityRecord activity = r.getTaskFragment().getActivityBelow(r);
+ return activity != null && !activity.inPinnedWindowingMode()
+ && (activity.mShowWhenLocked || activity.containsShowWhenLockedWindow());
} else {
return false;
}
}
/**
+ * Determines if the activity can show while lock-screen is displayed. System displays
+ * activities while lock-screen is displayed only if all activities
+ * {@link #canShowWhenLocked(ActivityRecord)}.
+ * @see #canShowWhenLocked(ActivityRecord)
+ */
+ boolean canShowWhenLocked() {
+ final TaskFragment taskFragment = getTaskFragment();
+ if (taskFragment != null && taskFragment.getAdjacentTaskFragment() != null
+ && taskFragment.isEmbedded()) {
+ final TaskFragment adjacentTaskFragment = taskFragment.getAdjacentTaskFragment();
+ final ActivityRecord r = adjacentTaskFragment.getTopNonFinishingActivity();
+ return canShowWhenLocked(this) && canShowWhenLocked(r);
+ } else {
+ return canShowWhenLocked(this);
+ }
+ }
+
+ /**
* @return Whether we are allowed to show non-starting windows at the moment. We disallow
* showing windows during transitions in case we have windows that have wide-color-gamut
* color mode set to avoid jank in the middle of the transition.
@@ -4134,29 +4098,6 @@
true /* topToBottom */);
}
- WindowState getImeTargetBelowWindow(WindowState w) {
- final int index = mChildren.indexOf(w);
- if (index > 0) {
- return mChildren.get(index - 1)
- .getWindow(WindowState::canBeImeTarget);
- }
- return null;
- }
-
- WindowState getHighestAnimLayerWindow(WindowState currentTarget) {
- WindowState candidate = null;
- for (int i = mChildren.indexOf(currentTarget); i >= 0; i--) {
- final WindowState w = mChildren.get(i);
- if (w.mRemoved) {
- continue;
- }
- if (candidate == null) {
- candidate = w;
- }
- }
- return candidate;
- }
-
@Override
boolean forAllActivities(Predicate<ActivityRecord> callback, boolean traverseTopToBottom) {
return callback.test(this);
@@ -6543,9 +6484,6 @@
return;
}
- final CompatibilityInfo compatInfo =
- mAtmService.compatibilityInfoForPackageLocked(info.applicationInfo);
-
mSplashScreenStyleEmpty = shouldUseEmptySplashScreen(sourceRecord, startActivity);
final int splashScreenTheme = startActivity ? getSplashscreenTheme() : 0;
@@ -6560,7 +6498,6 @@
&& task.getActivity((r) -> !r.finishing && r != this) == null;
final boolean scheduled = addStartingWindow(packageName, resolvedTheme,
- compatInfo, nonLocalizedLabel, labelRes, icon, logo, windowFlags,
prev, newTask || newSingleActivity, taskSwitch, isProcessRunning(),
allowTaskSnapshot(), activityCreated, mSplashScreenStyleEmpty, allDrawn);
if (DEBUG_STARTING_WINDOW_VERBOSE && scheduled) {
@@ -6991,11 +6928,6 @@
clearThumbnail();
}
- @VisibleForTesting
- WindowContainerThumbnail getThumbnail() {
- return mThumbnail;
- }
-
private void clearThumbnail() {
if (mThumbnail == null) {
return;
@@ -7008,9 +6940,6 @@
return mTransit;
}
- int getTransitFlags() {
- return mTransitFlags;
- }
void registerRemoteAnimations(RemoteAnimationDefinition definition) {
mRemoteAnimationDefinition = definition;
@@ -7205,7 +7134,7 @@
return false;
}
}
- return !isResizeable() && (info.isFixedOrientation() || info.hasFixedAspectRatio())
+ return !isResizeable() && (info.isFixedOrientation() || hasFixedAspectRatio())
// The configuration of non-standard type should be enforced by system.
// {@link WindowConfiguration#ACTIVITY_TYPE_STANDARD} is set when this activity is
// added to a task, but this function is called when resolving the launch params, at
@@ -7876,13 +7805,14 @@
return false;
}
}
- if (info.getMinAspectRatio() > 0) {
+ final float minAspectRatio = getMinAspectRatio();
+ if (minAspectRatio > 0) {
// The activity should have at least the min aspect ratio, so this checks if the
// container still has available space to provide larger aspect ratio.
final float containerAspectRatio =
(0.5f + Math.max(containerAppWidth, containerAppHeight))
/ Math.min(containerAppWidth, containerAppHeight);
- if (containerAspectRatio <= info.getMinAspectRatio()) {
+ if (containerAspectRatio <= minAspectRatio) {
// The long side has reached the parent.
return false;
}
@@ -8062,20 +7992,6 @@
super.onResize();
}
- /** Returns true if the configuration is compatible with this activity. */
- boolean isConfigurationCompatible(Configuration config) {
- final int orientation = getRequestedOrientation();
- if (isFixedOrientationPortrait(orientation)
- && config.orientation != ORIENTATION_PORTRAIT) {
- return false;
- }
- if (isFixedOrientationLandscape(orientation)
- && config.orientation != ORIENTATION_LANDSCAPE) {
- return false;
- }
- return true;
- }
-
private boolean applyAspectRatio(Rect outBounds, Rect containingAppBounds,
Rect containingBounds) {
return applyAspectRatio(outBounds, containingAppBounds, containingBounds,
@@ -8093,8 +8009,7 @@
Rect containingBounds, float desiredAspectRatio, boolean fixedOrientationLetterboxed) {
final float maxAspectRatio = info.getMaxAspectRatio();
final Task rootTask = getRootTask();
- final float minAspectRatio = info.getMinAspectRatio();
-
+ final float minAspectRatio = getMinAspectRatio();
if (task == null || rootTask == null
|| (inMultiWindowMode() && !shouldCreateCompatDisplayInsets()
&& !fixedOrientationLetterboxed)
@@ -8198,6 +8113,20 @@
}
/**
+ * Returns the min aspect ratio of this activity.
+ */
+ private float getMinAspectRatio() {
+ return info.getMinAspectRatio(getRequestedOrientation());
+ }
+
+ /**
+ * Returns true if the activity has maximum or minimum aspect ratio.
+ */
+ private boolean hasFixedAspectRatio() {
+ return info.hasFixedAspectRatio(getRequestedOrientation());
+ }
+
+ /**
* Returns the aspect ratio of the given {@code rect}.
*/
static float computeAspectRatio(Rect rect) {
@@ -8926,7 +8855,7 @@
}
proto.write(PIP_AUTO_ENTER_ENABLED, pictureInPictureArgs.isAutoEnterEnabled());
proto.write(IN_SIZE_COMPAT_MODE, inSizeCompatMode());
- proto.write(MIN_ASPECT_RATIO, info.getMinAspectRatio());
+ proto.write(MIN_ASPECT_RATIO, getMinAspectRatio());
}
@Override
diff --git a/services/core/java/com/android/server/wm/ActivityTaskManagerService.java b/services/core/java/com/android/server/wm/ActivityTaskManagerService.java
index a1a357e..690397f 100644
--- a/services/core/java/com/android/server/wm/ActivityTaskManagerService.java
+++ b/services/core/java/com/android/server/wm/ActivityTaskManagerService.java
@@ -221,6 +221,7 @@
import android.util.TimeUtils;
import android.util.proto.ProtoOutputStream;
import android.view.IRecentsAnimationRunner;
+import android.view.IRemoteAnimationRunner;
import android.view.RemoteAnimationAdapter;
import android.view.RemoteAnimationDefinition;
import android.view.WindowManager;
@@ -455,6 +456,10 @@
VrController mVrController;
KeyguardController mKeyguardController;
private final ClientLifecycleManager mLifecycleManager;
+
+ @Nullable
+ private final BackGestureController mBackGestureController;
+
private TaskChangeNotificationController mTaskChangeNotificationController;
/** The controller for all operations related to locktask. */
private LockTaskController mLockTaskController;
@@ -496,9 +501,6 @@
*/
private Configuration mTempConfig = new Configuration();
- /** Temporary to avoid allocations. */
- final StringBuilder mStringBuilder = new StringBuilder(256);
-
/**
* Whether normal application switches are allowed; a call to {@link #stopAppSwitches()
* disables this.
@@ -814,6 +816,8 @@
mSystemThread = ActivityThread.currentActivityThread();
mUiContext = mSystemThread.getSystemUiContext();
mLifecycleManager = new ClientLifecycleManager();
+ mBackGestureController = BackGestureController.isEnabled() ? new BackGestureController()
+ : null;
mVisibleActivityProcessTracker = new VisibleActivityProcessTracker(this);
mInternal = new LocalService();
GL_ES_VERSION = SystemProperties.getInt("ro.opengles.version", GL_ES_VERSION_UNDEFINED);
@@ -1747,6 +1751,14 @@
}
}
+ @Override
+ public void startBackPreview(IRemoteAnimationRunner runner) {
+ if (mBackGestureController == null) {
+ return;
+ }
+ mBackGestureController.startBackPreview();
+ }
+
/**
* Public API to check if the client is allowed to start an activity on specified display.
*
@@ -3081,11 +3093,6 @@
throw new SecurityException(msg);
}
- @VisibleForTesting
- int checkGetTasksPermission(String permission, int pid, int uid) {
- return checkPermission(permission, pid, uid);
- }
-
static int checkPermission(String permission, int pid, int uid) {
if (permission == null) {
return PackageManager.PERMISSION_DENIED;
@@ -3105,10 +3112,10 @@
return true;
}
- boolean allowed = checkGetTasksPermission(android.Manifest.permission.REAL_GET_TASKS,
+ boolean allowed = checkPermission(android.Manifest.permission.REAL_GET_TASKS,
callingPid, callingUid) == PackageManager.PERMISSION_GRANTED;
if (!allowed) {
- if (checkGetTasksPermission(android.Manifest.permission.GET_TASKS,
+ if (checkPermission(android.Manifest.permission.GET_TASKS,
callingPid, callingUid) == PackageManager.PERMISSION_GRANTED) {
// Temporary compatibility: some existing apps on the system image may
// still be requesting the old permission and not switched to the new
diff --git a/services/core/java/com/android/server/wm/ActivityTaskSupervisor.java b/services/core/java/com/android/server/wm/ActivityTaskSupervisor.java
index 11b685e..94cd77a 100644
--- a/services/core/java/com/android/server/wm/ActivityTaskSupervisor.java
+++ b/services/core/java/com/android/server/wm/ActivityTaskSupervisor.java
@@ -44,7 +44,6 @@
import static android.os.Process.INVALID_UID;
import static android.os.Trace.TRACE_TAG_WINDOW_MANAGER;
import static android.view.Display.DEFAULT_DISPLAY;
-import static android.view.WindowManager.TRANSIT_CLOSE;
import static android.view.WindowManager.TRANSIT_TO_FRONT;
import static com.android.internal.protolog.ProtoLogGroup.WM_DEBUG_STATES;
@@ -1562,19 +1561,7 @@
// Prevent recursion.
return;
}
- if (task.isVisible()) {
- if (task.mTransitionController.isCollecting()) {
- // We don't want the finishing to change the transition ready state since there will
- // not be corresponding setReady for finishing.
- task.mTransitionController.collectExistenceChange(task);
- } else {
- task.mTransitionController.requestTransitionIfNeeded(TRANSIT_CLOSE, task);
- }
- } else {
- // Removing a non-visible task doesn't require a transition, but if there is one
- // collecting, this should be a member just in case.
- task.mTransitionController.collect(task);
- }
+ task.mTransitionController.requestCloseTransitionIfNeeded(task);
task.mInRemoveTask = true;
try {
task.performClearTask(reason);
diff --git a/services/core/java/com/android/server/wm/AppTransition.java b/services/core/java/com/android/server/wm/AppTransition.java
index 7817f54..03d6590 100644
--- a/services/core/java/com/android/server/wm/AppTransition.java
+++ b/services/core/java/com/android/server/wm/AppTransition.java
@@ -292,6 +292,10 @@
setAppTransitionState(APP_STATE_IDLE);
}
+ boolean isIdle() {
+ return mAppTransitionState == APP_STATE_IDLE;
+ }
+
boolean isTimeout() {
return mAppTransitionState == APP_STATE_TIMEOUT;
}
diff --git a/services/core/java/com/android/server/wm/BLASTSyncEngine.java b/services/core/java/com/android/server/wm/BLASTSyncEngine.java
index 4355b38..2a8ac39e 100644
--- a/services/core/java/com/android/server/wm/BLASTSyncEngine.java
+++ b/services/core/java/com/android/server/wm/BLASTSyncEngine.java
@@ -20,9 +20,11 @@
import android.annotation.NonNull;
import android.util.ArraySet;
+import android.util.Slog;
import android.util.SparseArray;
import android.view.SurfaceControl;
+import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.protolog.common.ProtoLog;
/**
@@ -65,6 +67,7 @@
class SyncGroup {
final int mSyncId;
final TransactionReadyListener mListener;
+ final Runnable mOnTimeout;
boolean mReady = false;
final ArraySet<WindowContainer> mRootMembers = new ArraySet<>();
private SurfaceControl.Transaction mOrphanTransaction = null;
@@ -72,6 +75,12 @@
private SyncGroup(TransactionReadyListener listener, int id) {
mSyncId = id;
mListener = listener;
+ mOnTimeout = () -> {
+ Slog.w(TAG, "Sync group " + mSyncId + " timeout");
+ synchronized (mWm.mGlobalLock) {
+ onTimeout();
+ }
+ };
}
/**
@@ -114,6 +123,7 @@
}
mListener.onTransactionReady(mSyncId, merged);
mActiveSyncs.remove(mSyncId);
+ mWm.mH.removeCallbacks(mOnTimeout);
}
private void setReady(boolean ready) {
@@ -136,6 +146,17 @@
void onCancelSync(WindowContainer wc) {
mRootMembers.remove(wc);
}
+
+ private void onTimeout() {
+ if (!mActiveSyncs.contains(mSyncId)) return;
+ for (int i = mRootMembers.size() - 1; i >= 0; --i) {
+ final WindowContainer<?> wc = mRootMembers.valueAt(i);
+ if (!wc.isSyncFinished()) {
+ Slog.i(TAG, "Unfinished container: " + wc);
+ }
+ }
+ finishNow();
+ }
}
private final WindowManagerService mWm;
@@ -147,13 +168,23 @@
}
int startSyncSet(TransactionReadyListener listener) {
+ return startSyncSet(listener, WindowState.BLAST_TIMEOUT_DURATION);
+ }
+
+ int startSyncSet(TransactionReadyListener listener, long timeoutMs) {
final int id = mNextSyncId++;
final SyncGroup s = new SyncGroup(listener, id);
mActiveSyncs.put(id, s);
ProtoLog.v(WM_DEBUG_SYNC_ENGINE, "SyncGroup %d: Started for listener: %s", id, listener);
+ scheduleTimeout(s, timeoutMs);
return id;
}
+ @VisibleForTesting
+ void scheduleTimeout(SyncGroup s, long timeoutMs) {
+ mWm.mH.postDelayed(s.mOnTimeout, timeoutMs);
+ }
+
void addToSyncSet(int id, WindowContainer wc) {
mActiveSyncs.get(id).addToSync(wc);
}
diff --git a/services/core/java/com/android/server/wm/BackGestureController.java b/services/core/java/com/android/server/wm/BackGestureController.java
new file mode 100644
index 0000000..f8f6254
--- /dev/null
+++ b/services/core/java/com/android/server/wm/BackGestureController.java
@@ -0,0 +1,37 @@
+/*
+ * Copyright (C) 2021 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;
+
+import android.os.SystemProperties;
+
+/**
+ * Controller to handle actions related to the back gesture on the server side.
+ */
+public class BackGestureController {
+
+ private static final String BACK_PREDICTABILITY_PROP = "persist.debug.back_predictability";
+
+ public static boolean isEnabled() {
+ return SystemProperties.getInt(BACK_PREDICTABILITY_PROP, 0) > 0;
+ }
+
+ /**
+ * Start a remote animation the back gesture.
+ */
+ public void startBackPreview() {
+ }
+}
diff --git a/services/core/java/com/android/server/wm/DisplayContent.java b/services/core/java/com/android/server/wm/DisplayContent.java
index 611de34..f3d46f0 100644
--- a/services/core/java/com/android/server/wm/DisplayContent.java
+++ b/services/core/java/com/android/server/wm/DisplayContent.java
@@ -114,10 +114,12 @@
import static com.android.server.wm.DisplayContentProto.INPUT_METHOD_INPUT_TARGET;
import static com.android.server.wm.DisplayContentProto.INPUT_METHOD_TARGET;
import static com.android.server.wm.DisplayContentProto.INSETS_SOURCE_PROVIDERS;
+import static com.android.server.wm.DisplayContentProto.IS_SLEEPING;
import static com.android.server.wm.DisplayContentProto.OPENING_APPS;
import static com.android.server.wm.DisplayContentProto.RESUMED_ACTIVITY;
import static com.android.server.wm.DisplayContentProto.ROOT_DISPLAY_AREA;
import static com.android.server.wm.DisplayContentProto.SCREEN_ROTATION_ANIMATION;
+import static com.android.server.wm.DisplayContentProto.SLEEP_TOKENS;
import static com.android.server.wm.SurfaceAnimator.ANIMATION_TYPE_ALL;
import static com.android.server.wm.SurfaceAnimator.ANIMATION_TYPE_APP_TRANSITION;
import static com.android.server.wm.SurfaceAnimator.ANIMATION_TYPE_RECENTS;
@@ -467,9 +469,6 @@
@VisibleForTesting
boolean isDefaultDisplay;
- /** Window tokens that are in the process of exiting, but still on screen for animations. */
- final ArrayList<WindowToken> mExitingTokens = new ArrayList<>();
-
/** Detect user tapping outside of current focused task bounds .*/
@VisibleForTesting
final TaskTapPointerEventListener mTapDetector;
@@ -556,9 +555,6 @@
/** Windows removed since {@link #mCurrentFocus} was set to null. Used for ANR blaming. */
final ArrayList<WindowState> mWinRemovedSinceNullFocus = new ArrayList<>();
- /** Windows whose client's insets states are not up-to-date. */
- final ArrayList<WindowState> mWinInsetsChanged = new ArrayList<>();
-
private ScreenRotationAnimation mScreenRotationAnimation;
/**
@@ -638,9 +634,6 @@
/** The surface parent of the IME container. */
private SurfaceControl mInputMethodSurfaceParent;
- /** If {@code true} hold off on modifying the animation layer of {@link #mImeLayeringTarget} */
- boolean mImeLayeringTargetWaitingAnim;
-
/** The screenshot IME surface to place on the task while transitioning to the next task. */
SurfaceControl mImeScreenshot;
@@ -805,13 +798,16 @@
};
private final Consumer<WindowState> mPerformLayout = w -> {
+ if (w.mLayoutAttached || w.skipLayout()) {
+ return;
+ }
+
// Don't do layout of a window if it is not visible, or soon won't be visible, to avoid
// wasting time and funky changes while a window is animating away.
final boolean gone = w.isGoneForLayout();
- if (DEBUG_LAYOUT && !w.mLayoutAttached) {
+ if (DEBUG_LAYOUT) {
Slog.v(TAG, "1ST PASS " + w + ": gone=" + gone + " mHaveFrame=" + w.mHaveFrame
- + " mLayoutAttached=" + w.mLayoutAttached
+ " config reported=" + w.isLastConfigReportedToClient());
final ActivityRecord activity = w.mActivityRecord;
if (gone) Slog.v(TAG, " GONE: mViewVisibility=" + w.mViewVisibility
@@ -827,7 +823,7 @@
// If this view is GONE, then skip it -- keep the current frame, and let the caller know
// so they can ignore it if they want. (We do the normal layout for INVISIBLE windows,
// since that means "perform layout as normal, just don't display").
- if ((!gone || !w.mHaveFrame || w.mLayoutNeeded) && !w.mLayoutAttached) {
+ if (!gone || !w.mHaveFrame || w.mLayoutNeeded) {
if (mTmpInitial) {
w.resetContentChanged();
}
@@ -854,34 +850,34 @@
}
if (DEBUG_LAYOUT) Slog.v(TAG, " LAYOUT: mFrame=" + w.getFrame()
- + " mContainingFrame=" + w.getContainingFrame()
+ + " mParentFrame=" + w.getParentFrame()
+ " mDisplayFrame=" + w.getDisplayFrame());
}
};
private final Consumer<WindowState> mPerformLayoutAttached = w -> {
- if (w.mLayoutAttached) {
- if (DEBUG_LAYOUT) Slog.v(TAG, "2ND PASS " + w + " mHaveFrame=" + w.mHaveFrame
- + " mViewVisibility=" + w.mViewVisibility
- + " mRelayoutCalled=" + w.mRelayoutCalled);
- // If this view is GONE, then skip it -- keep the current frame, and let the caller
- // know so they can ignore it if they want. (We do the normal layout for INVISIBLE
- // windows, since that means "perform layout as normal, just don't display").
- if ((w.mViewVisibility != GONE && w.mRelayoutCalled) || !w.mHaveFrame
- || w.mLayoutNeeded) {
- if (mTmpInitial) {
- //Slog.i(TAG, "Window " + this + " clearing mContentChanged - initial");
- w.resetContentChanged();
- }
- w.mSurfacePlacementNeeded = true;
- w.mLayoutNeeded = false;
- w.prelayout();
- getDisplayPolicy().layoutWindowLw(w, w.getParentWindow(), mDisplayFrames);
- w.mLayoutSeq = mLayoutSeq;
- if (DEBUG_LAYOUT) Slog.v(TAG, " LAYOUT: mFrame=" + w.getFrame()
- + " mContainingFrame=" + w.getContainingFrame()
- + " mDisplayFrame=" + w.getDisplayFrame());
+ if (!w.mLayoutAttached || w.skipLayout()) {
+ return;
+ }
+ if (DEBUG_LAYOUT) Slog.v(TAG, "2ND PASS " + w + " mHaveFrame=" + w.mHaveFrame
+ + " mViewVisibility=" + w.mViewVisibility
+ + " mRelayoutCalled=" + w.mRelayoutCalled);
+ // If this view is GONE, then skip it -- keep the current frame, and let the caller
+ // know so they can ignore it if they want. (We do the normal layout for INVISIBLE
+ // windows, since that means "perform layout as normal, just don't display").
+ if ((w.mViewVisibility != GONE && w.mRelayoutCalled) || !w.mHaveFrame
+ || w.mLayoutNeeded) {
+ if (mTmpInitial) {
+ w.resetContentChanged();
}
+ w.mSurfacePlacementNeeded = true;
+ w.mLayoutNeeded = false;
+ w.prelayout();
+ getDisplayPolicy().layoutWindowLw(w, w.getParentWindow(), mDisplayFrames);
+ w.mLayoutSeq = mLayoutSeq;
+ if (DEBUG_LAYOUT) Slog.v(TAG, " LAYOUT: mFrame=" + w.getFrame()
+ + " mParentFrame=" + w.getParentFrame()
+ + " mDisplayFrame=" + w.getDisplayFrame());
}
};
@@ -1913,6 +1909,13 @@
if (mRemoteInsetsControlTarget != null) {
mRemoteInsetsControlTarget.notifyInsetsChanged();
}
+ // In Accessibility side, we need to know what magnification mode is activated while IME
+ // is opened for logging metrics.
+ if (mWmService.mAccessibilityController.hasCallbacks()) {
+ final boolean isImeShow = mImeControlTarget != null
+ && mImeControlTarget.getRequestedVisibility(ITYPE_IME);
+ mWmService.mAccessibilityController.updateImeVisibilityIfNeeded(mDisplayId, isImeShow);
+ }
}
/**
@@ -3264,6 +3267,11 @@
proto.write(FOCUSED_ROOT_TASK_ID, INVALID_TASK_ID);
}
proto.write(DISPLAY_READY, isReady());
+ proto.write(IS_SLEEPING, isSleeping());
+ for (int i = 0; i < mAllSleepTokens.size(); ++i) {
+ mAllSleepTokens.get(i).writeTagToProto(proto, SLEEP_TOKENS);
+ }
+
if (mImeLayeringTarget != null) {
mImeLayeringTarget.dumpDebug(proto, INPUT_METHOD_TARGET, logLevel);
}
@@ -3359,17 +3367,6 @@
});
pw.println();
- if (!mExitingTokens.isEmpty()) {
- pw.println();
- pw.println(" Exiting tokens:");
- for (int i = mExitingTokens.size() - 1; i >= 0; i--) {
- final WindowToken token = mExitingTokens.get(i);
- pw.print(" Exiting #"); pw.print(i);
- pw.print(' '); pw.print(token);
- pw.println(':');
- token.dump(pw, " ", dumpAll);
- }
- }
final ScreenRotationAnimation rotationAnimation = getRotationAnimation();
if (rotationAnimation != null) {
@@ -3425,7 +3422,9 @@
@Override
public String toString() {
- return "Display " + mDisplayId + " info=" + mDisplayInfo + " rootTasks=" + mChildren;
+ return "Display{#" + mDisplayId + " state=" + Display.stateToString(mDisplayInfo.state)
+ + " size=" + mDisplayInfo.logicalWidth + "x" + mDisplayInfo.logicalHeight
+ + " " + Surface.rotationToString(mDisplayInfo.rotation) + "}";
}
String getName() {
@@ -4113,6 +4112,8 @@
target.mActivityRecord.mImeInsetsFrozenUntilStartInput = false;
}
setImeInputTarget(target);
+ mInsetsStateController.updateAboveInsetsState(mInputMethodWindow, mInsetsStateController
+ .getRawInsetsState().getSourceOrDefaultVisibility(ITYPE_IME));
updateImeControlTarget();
}
}
@@ -4619,21 +4620,6 @@
return ret;
}
- void setExitingTokensHasVisible(boolean hasVisible) {
- for (int i = mExitingTokens.size() - 1; i >= 0; i--) {
- mExitingTokens.get(i).hasVisible = hasVisible;
- }
- }
-
- void removeExistingTokensIfPossible() {
- for (int i = mExitingTokens.size() - 1; i >= 0; i--) {
- final WindowToken token = mExitingTokens.get(i);
- if (!token.hasVisible) {
- mExitingTokens.remove(i);
- }
- }
- }
-
@Override
void onDescendantOverrideConfigurationChanged() {
setLayoutNeeded();
@@ -4991,12 +4977,6 @@
}
}
- void assignRootTaskOrdering() {
- forAllTaskDisplayAreas(taskDisplayArea -> {
- taskDisplayArea.assignRootTaskOrdering(getPendingTransaction());
- });
- }
-
/**
* Increment the deferral count to determine whether to update the IME target.
*/
diff --git a/services/core/java/com/android/server/wm/DisplayPolicy.java b/services/core/java/com/android/server/wm/DisplayPolicy.java
index c23d541..180ee61 100644
--- a/services/core/java/com/android/server/wm/DisplayPolicy.java
+++ b/services/core/java/com/android/server/wm/DisplayPolicy.java
@@ -43,12 +43,12 @@
import static android.view.WindowInsetsController.APPEARANCE_OPAQUE_STATUS_BARS;
import static android.view.WindowInsetsController.APPEARANCE_SEMI_TRANSPARENT_NAVIGATION_BARS;
import static android.view.WindowInsetsController.APPEARANCE_SEMI_TRANSPARENT_STATUS_BARS;
+import static android.view.WindowLayout.UNSPECIFIED_LENGTH;
import static android.view.WindowManager.LayoutParams.FIRST_APPLICATION_WINDOW;
import static android.view.WindowManager.LayoutParams.FIRST_SYSTEM_WINDOW;
import static android.view.WindowManager.LayoutParams.FLAG_ALLOW_LOCK_WHILE_SCREEN_ON;
import static android.view.WindowManager.LayoutParams.FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS;
import static android.view.WindowManager.LayoutParams.FLAG_FORCE_NOT_FULLSCREEN;
-import static android.view.WindowManager.LayoutParams.FLAG_LAYOUT_NO_LIMITS;
import static android.view.WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE;
import static android.view.WindowManager.LayoutParams.FLAG_SLIPPERY;
import static android.view.WindowManager.LayoutParams.LAYOUT_IN_DISPLAY_CUTOUT_MODE_ALWAYS;
@@ -65,7 +65,6 @@
import static android.view.WindowManager.LayoutParams.TYPE_STATUS_BAR_ADDITIONAL;
import static android.view.WindowManager.LayoutParams.TYPE_STATUS_BAR_PANEL;
import static android.view.WindowManager.LayoutParams.TYPE_STATUS_BAR_SUB_PANEL;
-import static android.view.WindowManager.LayoutParams.TYPE_SYSTEM_ERROR;
import static android.view.WindowManager.LayoutParams.TYPE_SYSTEM_OVERLAY;
import static android.view.WindowManager.LayoutParams.TYPE_TOAST;
import static android.view.WindowManager.LayoutParams.TYPE_VOICE_INTERACTION;
@@ -115,6 +114,7 @@
import android.graphics.PixelFormat;
import android.graphics.Rect;
import android.graphics.Region;
+import android.gui.DropInputMode;
import android.hardware.power.Boost;
import android.os.Handler;
import android.os.IBinder;
@@ -150,6 +150,7 @@
import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.policy.GestureNavigationSettingsObserver;
import com.android.internal.policy.ScreenDecorationsUtils;
+import com.android.internal.policy.SystemBarUtils;
import com.android.internal.protolog.common.ProtoLog;
import com.android.internal.util.ScreenshotHelper;
import com.android.internal.util.function.TriConsumer;
@@ -163,7 +164,6 @@
import com.android.server.policy.WindowManagerPolicy.WindowManagerFuncs;
import com.android.server.statusbar.StatusBarManagerInternal;
import com.android.server.wallpaper.WallpaperManagerInternal;
-import com.android.server.wm.InputMonitor.EventReceiverInputConsumer;
import java.io.PrintWriter;
import java.util.ArrayList;
@@ -394,7 +394,6 @@
// -------- PolicyHandler --------
private static final int MSG_REQUEST_TRANSIENT_BARS = 2;
- private static final int MSG_DISPOSE_INPUT_CONSUMER = 3;
private static final int MSG_ENABLE_POINTER_LOCATION = 4;
private static final int MSG_DISABLE_POINTER_LOCATION = 5;
@@ -423,9 +422,6 @@
}
}
break;
- case MSG_DISPOSE_INPUT_CONSUMER:
- disposeInputConsumer((EventReceiverInputConsumer) msg.obj);
- break;
case MSG_ENABLE_POINTER_LOCATION:
enablePointerLocation();
break;
@@ -961,6 +957,20 @@
}
/**
+ * Add additional policy if needed to ensure the window or its children should not receive any
+ * input.
+ */
+ public void setDropInputModePolicy(WindowState win, LayoutParams attrs) {
+ if (attrs.type == TYPE_TOAST
+ && (attrs.privateFlags & PRIVATE_FLAG_TRUSTED_OVERLAY) == 0) {
+ // Toasts should not receive input. These windows should not have any children, so
+ // force this hierarchy of windows to drop all input.
+ mService.mTransactionFactory.get()
+ .setDropInputMode(win.getSurfaceControl(), DropInputMode.ALL).apply();
+ }
+ }
+
+ /**
* Check if a window can be added to the system.
*
* Currently enforces that two window types are singletons per display:
@@ -1325,6 +1335,11 @@
return Math.max(statusBarHeight, displayFrames.mDisplayCutoutSafe.top);
}
+ @VisibleForTesting
+ int getStatusBarHeightForRotation(@Surface.Rotation int rotation) {
+ return SystemBarUtils.getStatusBarHeightForRotation(mUiContext, rotation);
+ }
+
WindowState getStatusBar() {
return mStatusBar != null ? mStatusBar : mStatusBarAlt;
}
@@ -1594,8 +1609,6 @@
// For layout, the status bar is always at the top with our fixed height.
int statusBarBottom = displayFrames.mUnrestricted.top
+ mStatusBarHeightForRotation[displayFrames.mRotation];
- // Make sure the status bar covers the entire cutout height
- statusBarBottom = Math.max(statusBarBottom, displayFrames.mDisplayCutoutSafe.top);
if (displayFrames.mDisplayCutoutSafe.top > displayFrames.mUnrestricted.top) {
// Make sure that the zone we're avoiding for the cutout is at least as tall as the
@@ -1700,10 +1713,6 @@
layoutStatusBar(displayFrames, mBarContentFrames.get(TYPE_STATUS_BAR));
return;
}
- if (win.mActivityRecord != null && win.mActivityRecord.mWaitForEnteringPinnedMode) {
- // Skip layout of the window when in transition to pip mode.
- return;
- }
final WindowManager.LayoutParams attrs = win.getLayoutingAttrs(displayFrames.mRotation);
final int type = attrs.type;
@@ -1715,37 +1724,50 @@
final Rect pf = windowFrames.mParentFrame;
final Rect df = windowFrames.mDisplayFrame;
+ final Rect f = windowFrames.mFrame;
final Rect attachedWindowFrame = attached != null ? attached.getFrame() : null;
sTmpLastParentFrame.set(pf);
- // Override the bounds in window token has many side effects. Directly use the display
- // frame set for the simulated layout for this case.
- final Rect winBounds = windowFrames.mIsSimulatingDecorWindow ? df : win.getBounds();
+ final Rect winBounds;
+ final int requestedWidth;
+ final int requestedHeight;
+ if (windowFrames.mIsSimulatingDecorWindow) {
+ // Override the bounds in window token has many side effects. Directly use the display
+ // frame set for the simulated layout.
+ winBounds = df;
+
+ // The view hierarchy has not been measured in the simulated layout. Use
+ // UNSPECIFIED_LENGTH as the requested width and height so that WindowLayout will choose
+ // the proper values in this case.
+ requestedWidth = UNSPECIFIED_LENGTH;
+ requestedHeight = UNSPECIFIED_LENGTH;
+ } else {
+ winBounds = win.getBounds();
+ requestedWidth = win.mRequestedWidth;
+ requestedHeight = win.mRequestedHeight;
+ }
final boolean clippedByDisplayCutout = mWindowLayout.computeWindowFrames(attrs,
- win.getInsetsState(), displayFrames.mDisplayCutoutSafe, winBounds,
- win.getRequestedVisibilities(), attachedWindowFrame, df, pf);
+ win.getInsetsState(), displayFrames.mDisplayCutoutSafe,
+ winBounds, win.getWindowingMode(), requestedWidth, requestedHeight,
+ win.getRequestedVisibilities(), attachedWindowFrame, win.mGlobalScale,
+ df, pf, f);
windowFrames.setParentFrameWasClippedByDisplayCutout(clippedByDisplayCutout);
- // TYPE_SYSTEM_ERROR is above the NavigationBar so it can't be allowed to extend over it.
- // Also, we don't allow windows in multi-window mode to extend out of the screen.
- if ((fl & FLAG_LAYOUT_NO_LIMITS) != 0 && type != TYPE_SYSTEM_ERROR
- && !win.inMultiWindowMode()) {
- df.left = df.top = -10000;
- df.right = df.bottom = 10000;
- }
-
if (DEBUG_LAYOUT) Slog.v(TAG, "Compute frame " + attrs.getTitle()
+ ": sim=#" + Integer.toHexString(sim)
+ " attach=" + attached + " type=" + type
- + String.format(" flags=0x%08x", fl)
- + " pf=" + pf.toShortString() + " df=" + df.toShortString());
+ + " flags=" + ViewDebug.flagsToString(LayoutParams.class, "flags", fl)
+ + " pf=" + pf.toShortString() + " df=" + df.toShortString()
+ + " f=" + f.toShortString());
if (!sTmpLastParentFrame.equals(pf)) {
windowFrames.setContentChanged(true);
}
- win.computeFrameAndUpdateSourceFrame(displayFrames);
+ if (!windowFrames.mIsSimulatingDecorWindow) {
+ win.setFrame();
+ }
}
WindowState getTopFullscreenOpaqueWindow() {
@@ -2041,10 +2063,11 @@
if (hasStatusBar()) {
mStatusBarHeightForRotation[portraitRotation] =
mStatusBarHeightForRotation[upsideDownRotation] =
- res.getDimensionPixelSize(R.dimen.status_bar_height_portrait);
+ getStatusBarHeightForRotation(portraitRotation);
mStatusBarHeightForRotation[landscapeRotation] =
- mStatusBarHeightForRotation[seascapeRotation] =
- res.getDimensionPixelSize(R.dimen.status_bar_height_landscape);
+ getStatusBarHeightForRotation(landscapeRotation);
+ mStatusBarHeightForRotation[seascapeRotation] =
+ getStatusBarHeightForRotation(seascapeRotation);
mDisplayCutoutTouchableRegionSize = res.getDimensionPixelSize(
R.dimen.display_cutout_touchable_region_size);
} else {
@@ -2545,12 +2568,6 @@
mImmersiveModeConfirmation.confirmCurrentPrompt();
}
- private void disposeInputConsumer(EventReceiverInputConsumer inputConsumer) {
- if (inputConsumer != null) {
- inputConsumer.dispose();
- }
- }
-
boolean isKeyguardShowing() {
return mService.mPolicy.isKeyguardShowing();
}
diff --git a/services/core/java/com/android/server/wm/InputMonitor.java b/services/core/java/com/android/server/wm/InputMonitor.java
index fa4d27c..d17c109 100644
--- a/services/core/java/com/android/server/wm/InputMonitor.java
+++ b/services/core/java/com/android/server/wm/InputMonitor.java
@@ -54,14 +54,12 @@
import android.graphics.Region;
import android.os.Handler;
import android.os.IBinder;
-import android.os.Looper;
import android.os.Trace;
import android.os.UserHandle;
import android.util.ArrayMap;
import android.util.EventLog;
import android.util.Slog;
import android.view.InputChannel;
-import android.view.InputEventReceiver;
import android.view.InputWindowHandle;
import android.view.SurfaceControl;
@@ -112,44 +110,6 @@
private WeakReference<ActivityRecord> mActiveRecentsActivity = null;
private WeakReference<ActivityRecord> mActiveRecentsLayerRef = null;
- /**
- * Representation of a input consumer that the policy has added to the window manager to consume
- * input events going to windows below it.
- */
- static final class EventReceiverInputConsumer extends InputConsumerImpl {
- private InputMonitor mInputMonitor;
- private final InputEventReceiver mInputEventReceiver;
-
- EventReceiverInputConsumer(WindowManagerService service, InputMonitor monitor,
- Looper looper, String name,
- InputEventReceiver.Factory inputEventReceiverFactory,
- int clientPid, UserHandle clientUser, int displayId) {
- super(service, null /* token */, name, null /* inputChannel */, clientPid, clientUser,
- displayId);
- mInputMonitor = monitor;
- mInputEventReceiver = inputEventReceiverFactory.createInputEventReceiver(
- mClientChannel, looper);
- }
-
- /** Removes the input consumer from the window manager. */
- void dismiss() {
- synchronized (mService.mGlobalLock) {
- mInputMonitor.mInputConsumers.remove(mName);
- hide(mInputMonitor.mInputTransaction);
- mInputMonitor.updateInputWindowsLw(true /* force */);
- }
- }
-
- /** Disposes the input consumer and input receiver from the associated thread. */
- void dispose() {
- synchronized (mService.mGlobalLock) {
- disposeChannelsLw(mInputMonitor.mInputTransaction);
- mInputEventReceiver.dispose();
- mInputMonitor.updateInputWindowsLw(true /* force */);
- }
- }
- }
-
private class UpdateInputWindows implements Runnable {
@Override
public void run() {
diff --git a/services/core/java/com/android/server/wm/InsetsStateController.java b/services/core/java/com/android/server/wm/InsetsStateController.java
index b46b2f7..3f573fa 100644
--- a/services/core/java/com/android/server/wm/InsetsStateController.java
+++ b/services/core/java/com/android/server/wm/InsetsStateController.java
@@ -291,19 +291,10 @@
for (int i = mProviders.size() - 1; i >= 0; i--) {
mProviders.valueAt(i).onPostLayout();
}
- final ArrayList<WindowState> winInsetsChanged = mDisplayContent.mWinInsetsChanged;
if (!mLastState.equals(mState)) {
mLastState.set(mState, true /* copySources */);
notifyInsetsChanged();
- } else {
- // The global insets state has not changed but there might be windows whose conditions
- // (e.g., z-order) have changed. They can affect the insets states that we dispatch to
- // the clients.
- for (int i = winInsetsChanged.size() - 1; i >= 0; i--) {
- mDispatchInsetsChanged.accept(winInsetsChanged.get(i));
- }
}
- winInsetsChanged.clear();
Trace.traceEnd(TRACE_TAG_WINDOW_MANAGER);
}
diff --git a/services/core/java/com/android/server/wm/RootWindowContainer.java b/services/core/java/com/android/server/wm/RootWindowContainer.java
index 1277e35..e10ae37 100644
--- a/services/core/java/com/android/server/wm/RootWindowContainer.java
+++ b/services/core/java/com/android/server/wm/RootWindowContainer.java
@@ -839,12 +839,6 @@
UPDATE_FOCUS_WILL_PLACE_SURFACES, false /*updateInputWindows*/);
}
- // Initialize state of exiting tokens.
- for (int displayNdx = 0; displayNdx < mChildren.size(); ++displayNdx) {
- final DisplayContent displayContent = mChildren.get(displayNdx);
- displayContent.setExitingTokensHasVisible(false);
- }
-
mHoldScreen = null;
mScreenBrightnessOverride = PowerManager.BRIGHTNESS_INVALID_FLOAT;
mUserActivityTimeout = -1;
@@ -951,12 +945,6 @@
mWmService.mDestroySurface.clear();
}
- // Time to remove any exiting tokens?
- for (int displayNdx = mChildren.size() - 1; displayNdx >= 0; --displayNdx) {
- final DisplayContent displayContent = mChildren.get(displayNdx);
- displayContent.removeExistingTokensIfPossible();
- }
-
for (int displayNdx = 0; displayNdx < mChildren.size(); ++displayNdx) {
final DisplayContent displayContent = mChildren.get(displayNdx);
if (displayContent.pendingLayoutChanges != 0) {
@@ -2651,6 +2639,7 @@
token = new SleepToken(tag, displayId);
mSleepTokens.put(tokenKey, token);
display.mAllSleepTokens.add(token);
+ ProtoLog.d(WM_DEBUG_STATES, "Create sleep token: tag=%s, displayId=%d", tag, displayId);
} else {
throw new RuntimeException("Create the same sleep token twice: " + token);
}
@@ -2669,6 +2658,8 @@
return;
}
+ ProtoLog.d(WM_DEBUG_STATES, "Remove sleep token: tag=%s, displayId=%d", token.mTag,
+ token.mDisplayId);
display.mAllSleepTokens.remove(token);
if (display.mAllSleepTokens.isEmpty()) {
mService.updateSleepIfNeededLocked();
@@ -3676,6 +3667,10 @@
return "{\"" + mTag + "\", display " + mDisplayId
+ ", acquire at " + TimeUtils.formatUptime(mAcquireTime) + "}";
}
+
+ void writeTagToProto(ProtoOutputStream proto, long fieldId) {
+ proto.write(fieldId, mTag);
+ }
}
private class RankTaskLayersRunnable implements Runnable {
diff --git a/services/core/java/com/android/server/wm/Session.java b/services/core/java/com/android/server/wm/Session.java
index 6b7f92a..b8b9bcc 100644
--- a/services/core/java/com/android/server/wm/Session.java
+++ b/services/core/java/com/android/server/wm/Session.java
@@ -16,7 +16,6 @@
package com.android.server.wm;
-import static android.Manifest.permission.DEVICE_POWER;
import static android.Manifest.permission.HIDE_NON_SYSTEM_OVERLAY_WINDOWS;
import static android.Manifest.permission.HIDE_OVERLAY_WINDOWS;
import static android.Manifest.permission.INTERNAL_SYSTEM_WINDOW;
@@ -107,7 +106,6 @@
final boolean mCanCreateSystemApplicationOverlay;
final boolean mCanHideNonSystemOverlayWindows;
- final boolean mCanAcquireSleepToken;
private AlertWindowNotification mAlertWindowNotification;
private boolean mShowingAlertWindowNotificationAllowed;
private boolean mClientDead = false;
@@ -134,8 +132,6 @@
== PERMISSION_GRANTED;
mCanStartTasksFromRecents = service.mContext.checkCallingOrSelfPermission(
START_TASKS_FROM_RECENTS) == PERMISSION_GRANTED;
- mCanAcquireSleepToken = service.mContext.checkCallingOrSelfPermission(DEVICE_POWER)
- == PERMISSION_GRANTED;
mShowingAlertWindowNotificationAllowed = mService.mShowAlertWindowNotifications;
mDragDropController = mService.mDragDropController;
StringBuilder sb = new StringBuilder();
diff --git a/services/core/java/com/android/server/wm/SnapshotStartingData.java b/services/core/java/com/android/server/wm/SnapshotStartingData.java
index b6cf91a..727fa52 100644
--- a/services/core/java/com/android/server/wm/SnapshotStartingData.java
+++ b/services/core/java/com/android/server/wm/SnapshotStartingData.java
@@ -18,7 +18,7 @@
import android.window.TaskSnapshot;
-import com.android.server.policy.WindowManagerPolicy.StartingSurface;
+import com.android.server.wm.StartingSurfaceController.StartingSurface;
/**
* Represents starting data for snapshot starting windows.
diff --git a/services/core/java/com/android/server/wm/SplashScreenStartingData.java b/services/core/java/com/android/server/wm/SplashScreenStartingData.java
index c659c05..d8d16e1 100644
--- a/services/core/java/com/android/server/wm/SplashScreenStartingData.java
+++ b/services/core/java/com/android/server/wm/SplashScreenStartingData.java
@@ -16,47 +16,25 @@
package com.android.server.wm;
-import android.content.res.CompatibilityInfo;
-import android.content.res.Configuration;
-
-import com.android.server.policy.WindowManagerPolicy.StartingSurface;
+import com.android.server.wm.StartingSurfaceController.StartingSurface;
/**
* Represents starting data for splash screens, i.e. "traditional" starting windows.
*/
class SplashScreenStartingData extends StartingData {
- private final String mPkg;
private final int mTheme;
- private final CompatibilityInfo mCompatInfo;
- private final CharSequence mNonLocalizedLabel;
- private final int mLabelRes;
- private final int mIcon;
- private final int mLogo;
- private final int mWindowFlags;
- private final Configuration mMergedOverrideConfiguration;
- SplashScreenStartingData(WindowManagerService service, String pkg, int theme,
- CompatibilityInfo compatInfo, CharSequence nonLocalizedLabel, int labelRes, int icon,
- int logo, int windowFlags, Configuration mergedOverrideConfiguration, int typeParams) {
+ SplashScreenStartingData(WindowManagerService service, int theme,
+ int typeParams) {
super(service, typeParams);
- mPkg = pkg;
mTheme = theme;
- mCompatInfo = compatInfo;
- mNonLocalizedLabel = nonLocalizedLabel;
- mLabelRes = labelRes;
- mIcon = icon;
- mLogo = logo;
- mWindowFlags = windowFlags;
- mMergedOverrideConfiguration = mergedOverrideConfiguration;
}
@Override
StartingSurface createStartingSurface(ActivityRecord activity) {
return mService.mStartingSurfaceController.createSplashScreenStartingSurface(
- activity, mPkg, mTheme, mCompatInfo, mNonLocalizedLabel, mLabelRes, mIcon,
- mLogo, mWindowFlags, mMergedOverrideConfiguration,
- activity.getDisplayContent().getDisplayId());
+ activity, mTheme);
}
@Override
diff --git a/services/core/java/com/android/server/wm/StartingData.java b/services/core/java/com/android/server/wm/StartingData.java
index 8b1befb..fbee343 100644
--- a/services/core/java/com/android/server/wm/StartingData.java
+++ b/services/core/java/com/android/server/wm/StartingData.java
@@ -16,7 +16,7 @@
package com.android.server.wm;
-import com.android.server.policy.WindowManagerPolicy.StartingSurface;
+import com.android.server.wm.StartingSurfaceController.StartingSurface;
/**
* Represents the model about how a starting window should be constructed.
diff --git a/services/core/java/com/android/server/wm/StartingSurfaceController.java b/services/core/java/com/android/server/wm/StartingSurfaceController.java
index 8b2a425..5fe4076 100644
--- a/services/core/java/com/android/server/wm/StartingSurfaceController.java
+++ b/services/core/java/com/android/server/wm/StartingSurfaceController.java
@@ -31,14 +31,9 @@
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.content.pm.ApplicationInfo;
-import android.content.res.CompatibilityInfo;
-import android.content.res.Configuration;
-import android.os.SystemProperties;
import android.util.Slog;
import android.window.TaskSnapshot;
-import com.android.server.policy.WindowManagerPolicy.StartingSurface;
-
import java.util.function.Supplier;
/**
@@ -47,9 +42,6 @@
public class StartingSurfaceController {
private static final String TAG = TAG_WITH_CLASS_NAME
? StartingSurfaceController.class.getSimpleName() : TAG_WM;
- /** Set to {@code true} to enable shell starting surface drawer. */
- static final boolean DEBUG_ENABLE_SHELL_DRAWER =
- SystemProperties.getBoolean("persist.debug.shell_starting_surface", true);
private final WindowManagerService mService;
private final SplashScreenExceptionList mSplashScreenExceptionsList;
@@ -58,20 +50,13 @@
mSplashScreenExceptionsList = new SplashScreenExceptionList(wm.mContext.getMainExecutor());
}
- StartingSurface createSplashScreenStartingSurface(ActivityRecord activity, String packageName,
- int theme, CompatibilityInfo compatInfo, CharSequence nonLocalizedLabel, int labelRes,
- int icon, int logo, int windowFlags, Configuration overrideConfig, int displayId) {
- if (!DEBUG_ENABLE_SHELL_DRAWER) {
- return mService.mPolicy.addSplashScreen(activity.token, activity.mUserId, packageName,
- theme, compatInfo, nonLocalizedLabel, labelRes, icon, logo, windowFlags,
- overrideConfig, displayId);
- }
+ StartingSurface createSplashScreenStartingSurface(ActivityRecord activity, int theme) {
synchronized (mService.mGlobalLock) {
final Task task = activity.getTask();
if (task != null && mService.mAtmService.mTaskOrganizerController.addStartingWindow(
task, activity, theme, null /* taskSnapshot */)) {
- return new ShellStartingSurface(task);
+ return new StartingSurface(task);
}
}
return null;
@@ -151,24 +136,25 @@
activity.mDisplayContent.handleTopActivityLaunchingInDifferentOrientation(
topFullscreenActivity, false /* checkOpening */);
}
- if (DEBUG_ENABLE_SHELL_DRAWER) {
mService.mAtmService.mTaskOrganizerController.addStartingWindow(task,
activity, 0 /* launchTheme */, taskSnapshot);
- return new ShellStartingSurface(task);
- }
+ return new StartingSurface(task);
}
- return mService.mTaskSnapshotController.createStartingSurface(activity, taskSnapshot);
}
- private final class ShellStartingSurface implements StartingSurface {
+ final class StartingSurface {
private final Task mTask;
- ShellStartingSurface(Task task) {
+ StartingSurface(Task task) {
mTask = task;
}
- @Override
+ /**
+ * Removes the starting window surface. Do not hold the window manager lock when calling
+ * this method!
+ * @param animate Whether need to play the default exit animation for starting window.
+ */
public void remove(boolean animate) {
synchronized (mService.mGlobalLock) {
mService.mAtmService.mTaskOrganizerController.removeStartingWindow(mTask, animate);
diff --git a/services/core/java/com/android/server/wm/Task.java b/services/core/java/com/android/server/wm/Task.java
index 6987cdb..9767c8b 100644
--- a/services/core/java/com/android/server/wm/Task.java
+++ b/services/core/java/com/android/server/wm/Task.java
@@ -471,12 +471,6 @@
// to layout without loading all the task snapshots
final PersistedTaskSnapshotData mLastTaskSnapshotData;
- // If set to true, the task will report that it is not in the floating
- // state regardless of it's root task affiliation. As the floating state drives
- // production of content insets this can be used to preserve them across
- // root task moves and we in fact do so when moving from full screen to pinned.
- private boolean mPreserveNonFloatingState = false;
-
private Dimmer mDimmer = new Dimmer(this);
private final Rect mTmpDimBoundsRect = new Rect();
@@ -1224,6 +1218,9 @@
adjustBoundsForDisplayChangeIfNeeded(getDisplayContent());
mRootWindowContainer.updateUIDsPresentOnDisplay();
+
+ // Ensure all animations are finished at same time in split-screen mode.
+ forAllActivities(ActivityRecord::updateAnimatingActivityRegistry);
}
@Override
@@ -2582,11 +2579,6 @@
reparent(rootTask, position);
rootTask.positionChildAt(position, this, moveParents);
-
- // If we are moving from the fullscreen root task to the root pinned task then we want to
- // preserve our insets so that there will not be a jump in the area covered by system
- // decorations. We rely on the pinned animation to later unset this value.
- mPreserveNonFloatingState = rootTask.inPinnedWindowingMode();
}
public int setBounds(Rect bounds, boolean forceResize) {
@@ -2899,16 +2891,6 @@
mForceShowForAllUsers = forceShowForAllUsers;
}
- /**
- * When we are in a floating root task (Freeform, Pinned, ...) we calculate
- * insets differently. However if we are animating to the fullscreen root task
- * we need to begin calculating insets as if we were fullscreen, otherwise
- * we will have a jump at the end.
- */
- boolean isFloating() {
- return getWindowConfiguration().tasksAreFloating() && !mPreserveNonFloatingState;
- }
-
/** Returns the top-most activity that occludes the given one, or {@code null} if none. */
@Nullable
ActivityRecord getOccludingActivityAbove(ActivityRecord activity) {
@@ -3246,10 +3228,6 @@
return "Task=" + mTaskId;
}
- void clearPreserveNonFloatingState() {
- mPreserveNonFloatingState = false;
- }
-
@Override
Dimmer getDimmer() {
// If the window is in multi-window mode, we want to dim at the Task level to ensure the dim
diff --git a/services/core/java/com/android/server/wm/TaskDisplayArea.java b/services/core/java/com/android/server/wm/TaskDisplayArea.java
index 7e784ae..d4035b5 100644
--- a/services/core/java/com/android/server/wm/TaskDisplayArea.java
+++ b/services/core/java/com/android/server/wm/TaskDisplayArea.java
@@ -42,8 +42,6 @@
import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_ROOT_TASK;
import static com.android.server.wm.WindowManagerDebugConfig.TAG_WM;
-import static java.lang.Integer.MIN_VALUE;
-
import android.annotation.ColorInt;
import android.annotation.Nullable;
import android.app.ActivityOptions;
@@ -798,12 +796,9 @@
int layer = 0;
// Place root home tasks to the bottom.
layer = adjustRootTaskLayer(t, mTmpHomeChildren, layer);
- adjustRootTaskLayer(t, mTmpNormalChildren, layer);
-
- // Always on top tasks layer should higher than split divider layer so set it as start.
- t.setLayer(mSplitScreenDividerAnchor, SPLIT_DIVIDER_LAYER);
- layer = SPLIT_DIVIDER_LAYER + 1;
+ layer = adjustRootTaskLayer(t, mTmpNormalChildren, layer);
adjustRootTaskLayer(t, mTmpAlwaysOnTopChildren, layer);
+ t.setLayer(mSplitScreenDividerAnchor, SPLIT_DIVIDER_LAYER);
}
/**
@@ -818,19 +813,33 @@
ArrayList<WindowContainer> children, int startLayer) {
mTmpNeedsZBoostIndexes.clear();
final int childCount = children.size();
+ boolean hasAdjacentTask = false;
for (int i = 0; i < childCount; i++) {
final WindowContainer child = children.get(i);
final TaskDisplayArea childTda = child.asTaskDisplayArea();
-
- boolean childNeedsZBoost = childTda != null
+ final boolean childNeedsZBoost = childTda != null
? childTda.childrenNeedZBoost()
: child.needsZBoost();
- if (!childNeedsZBoost) {
- child.assignLayer(t, startLayer++);
- } else {
+ if (childNeedsZBoost) {
mTmpNeedsZBoostIndexes.add(i);
+ continue;
}
+
+ final Task childTask = child.asTask();
+ final boolean inAdjacentTask = childTask != null
+ && child.inMultiWindowMode()
+ && childTask.getRootTask().getAdjacentTaskFragment() != null;
+
+ if (inAdjacentTask || child.inSplitScreenWindowingMode()) {
+ hasAdjacentTask = true;
+ } else if (hasAdjacentTask && startLayer < SPLIT_DIVIDER_LAYER) {
+ // Task on top of adjacent tasks should be higher than split divider layer so
+ // set it as start.
+ startLayer = SPLIT_DIVIDER_LAYER + 1;
+ }
+
+ child.assignLayer(t, startLayer++);
}
final int zBoostSize = mTmpNeedsZBoostIndexes.size();
@@ -896,15 +905,11 @@
float r = ((color >> 16) & 0xff) / 255.0f;
float g = ((color >> 8) & 0xff) / 255.0f;
float b = ((color >> 0) & 0xff) / 255.0f;
- float a = ((color >> 24) & 0xff) / 255.0f;
mColorLayerCounter++;
- getPendingTransaction().setLayer(mColorBackgroundLayer, MIN_VALUE)
+ getPendingTransaction()
.setColor(mColorBackgroundLayer, new float[]{r, g, b})
- .setAlpha(mColorBackgroundLayer, a)
- .setWindowCrop(mColorBackgroundLayer, getSurfaceWidth(), getSurfaceHeight())
- .setPosition(mColorBackgroundLayer, 0, 0)
.show(mColorBackgroundLayer);
scheduleAnimation();
diff --git a/services/core/java/com/android/server/wm/TaskLaunchParamsModifier.java b/services/core/java/com/android/server/wm/TaskLaunchParamsModifier.java
index d543c1f..b8ceb4a 100644
--- a/services/core/java/com/android/server/wm/TaskLaunchParamsModifier.java
+++ b/services/core/java/com/android/server/wm/TaskLaunchParamsModifier.java
@@ -818,7 +818,7 @@
final int layoutMinHeight = (layout == null) ? -1 : layout.minHeight;
// Aspect ratio requirements.
- final float minAspectRatio = info.getMinAspectRatio();
+ final float minAspectRatio = info.getMinAspectRatio(orientation);
final float maxAspectRatio = info.getMaxAspectRatio();
final int width = Math.min(defaultWidth, Math.max(phoneWidth, layoutMinWidth));
diff --git a/services/core/java/com/android/server/wm/TaskSnapshotController.java b/services/core/java/com/android/server/wm/TaskSnapshotController.java
index 96c935a..6aa707c 100644
--- a/services/core/java/com/android/server/wm/TaskSnapshotController.java
+++ b/services/core/java/com/android/server/wm/TaskSnapshotController.java
@@ -16,14 +16,29 @@
package com.android.server.wm;
+import static android.view.WindowInsetsController.APPEARANCE_LIGHT_NAVIGATION_BARS;
+import static android.view.WindowInsetsController.APPEARANCE_LIGHT_STATUS_BARS;
+import static android.view.WindowManager.LayoutParams.FLAG_TRANSLUCENT_NAVIGATION;
+import static android.view.WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS;
+import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_FORCE_DRAW_BAR_BACKGROUNDS;
+
+import static com.android.internal.policy.DecorView.NAVIGATION_BAR_COLOR_VIEW_ATTRIBUTES;
+import static com.android.internal.policy.DecorView.STATUS_BAR_COLOR_VIEW_ATTRIBUTES;
+import static com.android.internal.policy.DecorView.getNavigationBarRect;
import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_SCREENSHOT;
import static com.android.server.wm.WindowManagerDebugConfig.TAG_WITH_CLASS_NAME;
import static com.android.server.wm.WindowManagerDebugConfig.TAG_WM;
import android.annotation.NonNull;
import android.annotation.Nullable;
+import android.app.ActivityManager;
+import android.app.ActivityThread;
+import android.content.Context;
import android.content.pm.PackageManager;
import android.graphics.Bitmap;
+import android.graphics.Canvas;
+import android.graphics.Color;
+import android.graphics.Paint;
import android.graphics.PixelFormat;
import android.graphics.Point;
import android.graphics.RecordingCanvas;
@@ -44,11 +59,11 @@
import android.view.WindowManager.LayoutParams;
import android.window.TaskSnapshot;
+import com.android.internal.R;
import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.graphics.ColorUtils;
+import com.android.internal.policy.DecorView;
import com.android.server.policy.WindowManagerPolicy.ScreenOffListener;
-import com.android.server.policy.WindowManagerPolicy.StartingSurface;
-import com.android.server.wm.TaskSnapshotSurface.SystemBarBackgroundPainter;
import com.android.server.wm.utils.InsetUtils;
import com.google.android.collect.Sets;
@@ -242,15 +257,6 @@
}
/**
- * Creates a starting surface for {@param token} with {@param snapshot}. DO NOT HOLD THE WINDOW
- * MANAGER LOCK WHEN CALLING THIS METHOD!
- */
- StartingSurface createStartingSurface(ActivityRecord activity,
- TaskSnapshot snapshot) {
- return TaskSnapshotSurface.create(mService, activity, snapshot);
- }
-
- /**
* Find the window for a given task to take a snapshot. Top child of the task is usually the one
* we're looking for, but during app transitions, trampoline activities can appear in the
* children, which should be ignored.
@@ -375,12 +381,6 @@
}
@Nullable
- SurfaceControl.ScreenshotHardwareBuffer createTaskSnapshot(@NonNull Task task,
- float scaleFraction, TaskSnapshot.Builder builder) {
- return createTaskSnapshot(task, scaleFraction, PixelFormat.RGBA_8888, null, builder);
- }
-
- @Nullable
private SurfaceControl.ScreenshotHardwareBuffer createImeSnapshot(@NonNull Task task,
int pixelFormat) {
if (task.getSurfaceControl() == null) {
@@ -392,7 +392,7 @@
final WindowState imeWindow = task.getDisplayContent().mInputMethodWindow;
SurfaceControl.ScreenshotHardwareBuffer imeBuffer = null;
if (imeWindow != null && imeWindow.isWinVisibleLw()) {
- final Rect bounds = imeWindow.getContainingFrame();
+ final Rect bounds = imeWindow.getParentFrame();
bounds.offsetTo(0, 0);
imeBuffer = SurfaceControl.captureLayersExcluding(imeWindow.getSurfaceControl(),
bounds, 1.0f, pixelFormat, null);
@@ -573,7 +573,7 @@
final RecordingCanvas c = node.start(width, height);
c.drawColor(color);
decorPainter.setInsets(systemBarInsets);
- decorPainter.drawDecors(c, null /* statusBarExcludeFrame */);
+ decorPainter.drawDecors(c /* statusBarExcludeFrame */);
node.end(c);
final Bitmap hwBitmap = ThreadedRenderer.createHardwareBitmap(node, width, height);
if (hwBitmap == null) {
@@ -704,4 +704,92 @@
pw.println(prefix + "mTaskSnapshotEnabled=" + mTaskSnapshotEnabled);
mCache.dump(pw, prefix);
}
+
+ /**
+ * Helper class to draw the background of the system bars in regions the task snapshot isn't
+ * filling the window.
+ */
+ static class SystemBarBackgroundPainter {
+
+ private final Paint mStatusBarPaint = new Paint();
+ private final Paint mNavigationBarPaint = new Paint();
+ private final int mStatusBarColor;
+ private final int mNavigationBarColor;
+ private final int mWindowFlags;
+ private final int mWindowPrivateFlags;
+ private final float mScale;
+ private final InsetsState mInsetsState;
+ private final Rect mSystemBarInsets = new Rect();
+
+ SystemBarBackgroundPainter(int windowFlags, int windowPrivateFlags, int appearance,
+ ActivityManager.TaskDescription taskDescription, float scale,
+ InsetsState insetsState) {
+ mWindowFlags = windowFlags;
+ mWindowPrivateFlags = windowPrivateFlags;
+ mScale = scale;
+ final Context context = ActivityThread.currentActivityThread().getSystemUiContext();
+ final int semiTransparent = context.getColor(
+ R.color.system_bar_background_semi_transparent);
+ mStatusBarColor = DecorView.calculateBarColor(windowFlags, FLAG_TRANSLUCENT_STATUS,
+ semiTransparent, taskDescription.getStatusBarColor(), appearance,
+ APPEARANCE_LIGHT_STATUS_BARS,
+ taskDescription.getEnsureStatusBarContrastWhenTransparent());
+ mNavigationBarColor = DecorView.calculateBarColor(windowFlags,
+ FLAG_TRANSLUCENT_NAVIGATION, semiTransparent,
+ taskDescription.getNavigationBarColor(), appearance,
+ APPEARANCE_LIGHT_NAVIGATION_BARS,
+ taskDescription.getEnsureNavigationBarContrastWhenTransparent()
+ && context.getResources().getBoolean(R.bool.config_navBarNeedsScrim));
+ mStatusBarPaint.setColor(mStatusBarColor);
+ mNavigationBarPaint.setColor(mNavigationBarColor);
+ mInsetsState = insetsState;
+ }
+
+ void setInsets(Rect systemBarInsets) {
+ mSystemBarInsets.set(systemBarInsets);
+ }
+
+ int getStatusBarColorViewHeight() {
+ final boolean forceBarBackground =
+ (mWindowPrivateFlags & PRIVATE_FLAG_FORCE_DRAW_BAR_BACKGROUNDS) != 0;
+ if (STATUS_BAR_COLOR_VIEW_ATTRIBUTES.isVisible(
+ mInsetsState, mStatusBarColor, mWindowFlags, forceBarBackground)) {
+ return (int) (mSystemBarInsets.top * mScale);
+ } else {
+ return 0;
+ }
+ }
+
+ private boolean isNavigationBarColorViewVisible() {
+ final boolean forceBarBackground =
+ (mWindowPrivateFlags & PRIVATE_FLAG_FORCE_DRAW_BAR_BACKGROUNDS) != 0;
+ return NAVIGATION_BAR_COLOR_VIEW_ATTRIBUTES.isVisible(
+ mInsetsState, mNavigationBarColor, mWindowFlags, forceBarBackground);
+ }
+
+ void drawDecors(Canvas c) {
+ drawStatusBarBackground(c, getStatusBarColorViewHeight());
+ drawNavigationBarBackground(c);
+ }
+
+ @VisibleForTesting
+ void drawStatusBarBackground(Canvas c,
+ int statusBarHeight) {
+ if (statusBarHeight > 0 && Color.alpha(mStatusBarColor) != 0) {
+ final int rightInset = (int) (mSystemBarInsets.right * mScale);
+ c.drawRect(0, 0, c.getWidth() - rightInset, statusBarHeight, mStatusBarPaint);
+ }
+ }
+
+ @VisibleForTesting
+ void drawNavigationBarBackground(Canvas c) {
+ final Rect navigationBarRect = new Rect();
+ getNavigationBarRect(c.getWidth(), c.getHeight(), mSystemBarInsets, navigationBarRect,
+ mScale);
+ final boolean visible = isNavigationBarColorViewVisible();
+ if (visible && Color.alpha(mNavigationBarColor) != 0 && !navigationBarRect.isEmpty()) {
+ c.drawRect(navigationBarRect, mNavigationBarPaint);
+ }
+ }
+ }
}
diff --git a/services/core/java/com/android/server/wm/TaskSnapshotSurface.java b/services/core/java/com/android/server/wm/TaskSnapshotSurface.java
deleted file mode 100644
index 059eb87..0000000
--- a/services/core/java/com/android/server/wm/TaskSnapshotSurface.java
+++ /dev/null
@@ -1,620 +0,0 @@
-/*
- * Copyright (C) 2016 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;
-
-import static android.app.WindowConfiguration.ACTIVITY_TYPE_HOME;
-import static android.graphics.Color.WHITE;
-import static android.graphics.Color.alpha;
-import static android.view.WindowInsetsController.APPEARANCE_LIGHT_NAVIGATION_BARS;
-import static android.view.WindowInsetsController.APPEARANCE_LIGHT_STATUS_BARS;
-import static android.view.WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM;
-import static android.view.WindowManager.LayoutParams.FLAG_HARDWARE_ACCELERATED;
-import static android.view.WindowManager.LayoutParams.FLAG_IGNORE_CHEEK_PRESSES;
-import static android.view.WindowManager.LayoutParams.FLAG_LOCAL_FOCUS_MODE;
-import static android.view.WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE;
-import static android.view.WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE;
-import static android.view.WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL;
-import static android.view.WindowManager.LayoutParams.FLAG_SCALED;
-import static android.view.WindowManager.LayoutParams.FLAG_SECURE;
-import static android.view.WindowManager.LayoutParams.FLAG_SLIPPERY;
-import static android.view.WindowManager.LayoutParams.FLAG_SPLIT_TOUCH;
-import static android.view.WindowManager.LayoutParams.FLAG_TRANSLUCENT_NAVIGATION;
-import static android.view.WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS;
-import static android.view.WindowManager.LayoutParams.FLAG_WATCH_OUTSIDE_TOUCH;
-import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_FORCE_DRAW_BAR_BACKGROUNDS;
-import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_TRUSTED_OVERLAY;
-import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_USE_BLAST;
-import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION_STARTING;
-
-import static com.android.internal.policy.DecorView.NAVIGATION_BAR_COLOR_VIEW_ATTRIBUTES;
-import static com.android.internal.policy.DecorView.STATUS_BAR_COLOR_VIEW_ATTRIBUTES;
-import static com.android.internal.policy.DecorView.getNavigationBarRect;
-import static com.android.internal.protolog.ProtoLogGroup.WM_DEBUG_STARTING_WINDOW;
-import static com.android.server.wm.TaskSnapshotController.getSystemBarInsets;
-import static com.android.server.wm.WindowManagerDebugConfig.TAG_WITH_CLASS_NAME;
-import static com.android.server.wm.WindowManagerDebugConfig.TAG_WM;
-
-import android.annotation.Nullable;
-import android.app.ActivityManager.TaskDescription;
-import android.app.ActivityThread;
-import android.content.Context;
-import android.graphics.Canvas;
-import android.graphics.Color;
-import android.graphics.GraphicBuffer;
-import android.graphics.Matrix;
-import android.graphics.Paint;
-import android.graphics.PixelFormat;
-import android.graphics.Point;
-import android.graphics.Rect;
-import android.graphics.RectF;
-import android.hardware.HardwareBuffer;
-import android.os.Handler;
-import android.os.Looper;
-import android.os.Message;
-import android.os.RemoteException;
-import android.os.SystemClock;
-import android.util.MergedConfiguration;
-import android.util.Slog;
-import android.view.IWindowSession;
-import android.view.InsetsSourceControl;
-import android.view.InsetsState;
-import android.view.InsetsVisibilities;
-import android.view.SurfaceControl;
-import android.view.SurfaceSession;
-import android.view.View;
-import android.view.ViewGroup.LayoutParams;
-import android.view.WindowManager;
-import android.view.WindowManagerGlobal;
-import android.window.ClientWindowFrames;
-import android.window.TaskSnapshot;
-
-import com.android.internal.R;
-import com.android.internal.annotations.VisibleForTesting;
-import com.android.internal.policy.DecorView;
-import com.android.internal.protolog.common.ProtoLog;
-import com.android.internal.view.BaseIWindow;
-import com.android.server.policy.WindowManagerPolicy.StartingSurface;
-
-/**
- * This class represents a starting window that shows a snapshot.
- * <p>
- * DO NOT HOLD THE WINDOW MANAGER LOCK WHEN CALLING METHODS OF THIS CLASS!
- */
-class TaskSnapshotSurface implements StartingSurface {
-
- private static final long SIZE_MISMATCH_MINIMUM_TIME_MS = 450;
-
- /**
- * When creating the starting window, we use the exact same layout flags such that we end up
- * with a window with the exact same dimensions etc. However, these flags are not used in layout
- * and might cause other side effects so we exclude them.
- */
- static final int FLAG_INHERIT_EXCLUDES = FLAG_NOT_FOCUSABLE
- | FLAG_NOT_TOUCHABLE
- | FLAG_NOT_TOUCH_MODAL
- | FLAG_ALT_FOCUSABLE_IM
- | FLAG_NOT_FOCUSABLE
- | FLAG_HARDWARE_ACCELERATED
- | FLAG_IGNORE_CHEEK_PRESSES
- | FLAG_LOCAL_FOCUS_MODE
- | FLAG_SLIPPERY
- | FLAG_WATCH_OUTSIDE_TOUCH
- | FLAG_SPLIT_TOUCH
- | FLAG_SCALED
- | FLAG_SECURE;
-
- private static final int PRIVATE_FLAG_INHERITS = PRIVATE_FLAG_FORCE_DRAW_BAR_BACKGROUNDS;
-
- private static final String TAG = TAG_WITH_CLASS_NAME ? "SnapshotStartingWindow" : TAG_WM;
- private static final int MSG_REPORT_DRAW = 0;
- private static final String TITLE_FORMAT = "SnapshotStartingWindow for taskId=%s";
-
- //tmp vars for unused relayout params
- private static final Point sTmpSurfaceSize = new Point();
-
- private final Window mWindow;
- private final SurfaceControl mSurfaceControl;
- private final IWindowSession mSession;
- private final WindowManagerService mService;
- private final int mDisplayId;
- private final Rect mTaskBounds;
- private final Rect mFrame = new Rect();
- private final Rect mSystemBarInsets = new Rect();
- private TaskSnapshot mSnapshot;
- private final RectF mTmpSnapshotSize = new RectF();
- private final RectF mTmpDstFrame = new RectF();
- private final CharSequence mTitle;
- private boolean mHasDrawn;
- private long mShownTime;
- private final Handler mHandler;
- private boolean mSizeMismatch;
- private final Paint mBackgroundPaint = new Paint();
- private final int mActivityType;
- private final int mStatusBarColor;
- @VisibleForTesting final SystemBarBackgroundPainter mSystemBarBackgroundPainter;
- private final int mOrientationOnCreation;
- private final SurfaceControl.Transaction mTransaction;
- private final Matrix mSnapshotMatrix = new Matrix();
- private final float[] mTmpFloat9 = new float[9];
-
- static TaskSnapshotSurface create(WindowManagerService service, ActivityRecord activity,
- TaskSnapshot snapshot) {
- return create(service, activity, snapshot, WindowManagerGlobal.getWindowSession());
- }
-
- @VisibleForTesting
- static TaskSnapshotSurface create(WindowManagerService service, ActivityRecord activity,
- TaskSnapshot snapshot, IWindowSession session) {
-
- final WindowManager.LayoutParams layoutParams = new WindowManager.LayoutParams();
- final Window window = new Window();
- window.setSession(session);
- final SurfaceControl surfaceControl = new SurfaceControl();
- final ClientWindowFrames tmpFrames = new ClientWindowFrames();
- final Rect taskBounds;
- final InsetsState mTmpInsetsState = new InsetsState();
- final InsetsVisibilities mRequestedVisibilities = new InsetsVisibilities();
- final InsetsSourceControl[] mTempControls = new InsetsSourceControl[0];
- final MergedConfiguration tmpMergedConfiguration = new MergedConfiguration();
- final TaskDescription taskDescription = new TaskDescription();
- taskDescription.setBackgroundColor(WHITE);
- final WindowState topFullscreenOpaqueWindow;
- final int appearance;
- final int windowFlags;
- final int windowPrivateFlags;
- final int currentOrientation;
- final int activityType;
- final InsetsState insetsState;
- synchronized (service.mGlobalLock) {
- final WindowState mainWindow = activity.findMainWindow();
- final Task task = activity.getTask();
- final ActivityRecord topFullscreenActivity =
- activity.getTask().getTopFullscreenActivity();
- // Already check the nullity in StartingSurfaceController#createTaskSnapshotSurface
- topFullscreenOpaqueWindow = topFullscreenActivity.getTopFullscreenOpaqueWindow();
- WindowManager.LayoutParams attrs = topFullscreenOpaqueWindow.mAttrs;
- appearance = attrs.insetsFlags.appearance;
- windowFlags = attrs.flags;
- windowPrivateFlags = attrs.privateFlags;
-
- layoutParams.packageName = mainWindow.getAttrs().packageName;
- layoutParams.windowAnimations = mainWindow.getAttrs().windowAnimations;
- layoutParams.dimAmount = mainWindow.getAttrs().dimAmount;
- layoutParams.type = TYPE_APPLICATION_STARTING;
- layoutParams.format = snapshot.getHardwareBuffer().getFormat();
- layoutParams.flags = (windowFlags & ~FLAG_INHERIT_EXCLUDES)
- | FLAG_NOT_FOCUSABLE
- | FLAG_NOT_TOUCHABLE;
- // Setting as trusted overlay to let touches pass through. This is safe because this
- // window is controlled by the system.
- layoutParams.privateFlags = (windowPrivateFlags & PRIVATE_FLAG_INHERITS)
- | PRIVATE_FLAG_TRUSTED_OVERLAY | PRIVATE_FLAG_USE_BLAST;
- layoutParams.token = activity.token;
- layoutParams.width = LayoutParams.MATCH_PARENT;
- layoutParams.height = LayoutParams.MATCH_PARENT;
- layoutParams.insetsFlags.appearance = appearance;
- layoutParams.insetsFlags.behavior = attrs.insetsFlags.behavior;
- layoutParams.layoutInDisplayCutoutMode = attrs.layoutInDisplayCutoutMode;
- layoutParams.setFitInsetsTypes(attrs.getFitInsetsTypes());
- layoutParams.setFitInsetsSides(attrs.getFitInsetsSides());
- layoutParams.setFitInsetsIgnoringVisibility(attrs.isFitInsetsIgnoringVisibility());
-
- layoutParams.setTitle(String.format(TITLE_FORMAT, task.mTaskId));
-
- final TaskDescription td = task.getTaskDescription();
- if (td != null) {
- taskDescription.copyFromPreserveHiddenFields(td);
- }
- taskBounds = new Rect();
- task.getBounds(taskBounds);
- currentOrientation = topFullscreenOpaqueWindow.getConfiguration().orientation;
- activityType = activity.getActivityType();
- insetsState = topFullscreenOpaqueWindow.getInsetsStateWithVisibilityOverride();
-
- }
- int displayId = activity.getDisplayContent().getDisplayId();
- try {
- final int res = session.addToDisplay(window, layoutParams, View.GONE, displayId,
- mRequestedVisibilities, null /* outInputChannel */, mTmpInsetsState,
- mTempControls);
- if (res < 0) {
- Slog.w(TAG, "Failed to add snapshot starting window res=" + res);
- return null;
- }
- } catch (RemoteException e) {
- // Local call.
- }
- final TaskSnapshotSurface snapshotSurface = new TaskSnapshotSurface(service, displayId,
- window, surfaceControl, snapshot, layoutParams.getTitle(), taskDescription,
- appearance, windowFlags, windowPrivateFlags, taskBounds, currentOrientation,
- activityType, insetsState);
- window.setOuter(snapshotSurface);
- try {
- session.relayout(window, layoutParams, -1, -1, View.VISIBLE, 0, -1,
- tmpFrames, tmpMergedConfiguration, surfaceControl, mTmpInsetsState,
- mTempControls, sTmpSurfaceSize);
- } catch (RemoteException e) {
- // Local call.
- }
-
- final Rect systemBarInsets = getSystemBarInsets(tmpFrames.frame, insetsState);
- snapshotSurface.setFrames(tmpFrames.frame, systemBarInsets);
- snapshotSurface.drawSnapshot();
- return snapshotSurface;
- }
-
- @VisibleForTesting
- TaskSnapshotSurface(WindowManagerService service, int displayId, Window window,
- SurfaceControl surfaceControl, TaskSnapshot snapshot, CharSequence title,
- TaskDescription taskDescription, int appearance, int windowFlags,
- int windowPrivateFlags, Rect taskBounds, int currentOrientation, int activityType,
- InsetsState insetsState) {
- mService = service;
- mDisplayId = displayId;
- mHandler = new Handler(mService.mH.getLooper());
- mSession = WindowManagerGlobal.getWindowSession();
- mWindow = window;
- mSurfaceControl = surfaceControl;
- mSnapshot = snapshot;
- mTitle = title;
- int backgroundColor = taskDescription.getBackgroundColor();
- mBackgroundPaint.setColor(backgroundColor != 0 ? backgroundColor : WHITE);
- mTaskBounds = taskBounds;
- mSystemBarBackgroundPainter = new SystemBarBackgroundPainter(windowFlags,
- windowPrivateFlags, appearance, taskDescription, 1f, insetsState);
- mStatusBarColor = taskDescription.getStatusBarColor();
- mOrientationOnCreation = currentOrientation;
- mActivityType = activityType;
- mTransaction = mService.mTransactionFactory.get();
- }
-
- @Override
- public void remove(boolean animate) {
- synchronized (mService.mGlobalLock) {
- final long now = SystemClock.uptimeMillis();
- if (mSizeMismatch && now - mShownTime < SIZE_MISMATCH_MINIMUM_TIME_MS
- // Show the latest content as soon as possible for unlocking to home.
- && mActivityType != ACTIVITY_TYPE_HOME) {
- mHandler.postAtTime(() -> remove(false /* prepareAnimation */),
- mShownTime + SIZE_MISMATCH_MINIMUM_TIME_MS);
- ProtoLog.v(WM_DEBUG_STARTING_WINDOW,
- "Defer removing snapshot surface in %dms", (now - mShownTime));
-
- return;
- }
- }
- try {
- ProtoLog.v(WM_DEBUG_STARTING_WINDOW, "Removing snapshot surface");
- mSession.remove(mWindow);
- } catch (RemoteException e) {
- // Local call.
- }
- }
-
- @VisibleForTesting
- void setFrames(Rect frame, Rect systemBarInsets) {
- mFrame.set(frame);
- mSystemBarInsets.set(systemBarInsets);
- final HardwareBuffer snapshot = mSnapshot.getHardwareBuffer();
- mSizeMismatch = (mFrame.width() != snapshot.getWidth()
- || mFrame.height() != snapshot.getHeight());
- mSystemBarBackgroundPainter.setInsets(systemBarInsets);
- }
-
- private void drawSnapshot() {
- ProtoLog.v(WM_DEBUG_STARTING_WINDOW, "Drawing snapshot surface sizeMismatch=%b",
- mSizeMismatch);
- if (mSizeMismatch) {
- // The dimensions of the buffer and the window don't match, so attaching the buffer
- // will fail. Better create a child window with the exact dimensions and fill the parent
- // window with the background color!
- drawSizeMismatchSnapshot();
- } else {
- drawSizeMatchSnapshot();
- }
- synchronized (mService.mGlobalLock) {
- mShownTime = SystemClock.uptimeMillis();
- mHasDrawn = true;
- }
- reportDrawn();
-
- // In case window manager leaks us, make sure we don't retain the snapshot.
- mSnapshot = null;
- }
-
- private void drawSizeMatchSnapshot() {
- GraphicBuffer graphicBuffer = GraphicBuffer.createFromHardwareBuffer(
- mSnapshot.getHardwareBuffer());
- mTransaction.setBuffer(mSurfaceControl, graphicBuffer)
- .setColorSpace(mSurfaceControl, mSnapshot.getColorSpace())
- .apply();
- }
-
- private void drawSizeMismatchSnapshot() {
- final HardwareBuffer buffer = mSnapshot.getHardwareBuffer();
- final SurfaceSession session = new SurfaceSession();
- // We consider nearly matched dimensions as there can be rounding errors and the user won't
- // notice very minute differences from scaling one dimension more than the other
- final boolean aspectRatioMismatch = Math.abs(
- ((float) buffer.getWidth() / buffer.getHeight())
- - ((float) mFrame.width() / mFrame.height())) > 0.01f;
-
- // Keep a reference to it such that it doesn't get destroyed when finalized.
- final String name = mTitle + " - task-snapshot-surface";
- SurfaceControl childSurfaceControl = mService.mSurfaceControlFactory.apply(session)
- .setName(name)
- .setBLASTLayer()
- .setFormat(buffer.getFormat())
- .setParent(mSurfaceControl)
- .setCallsite("TaskSnapshotSurface.drawSizeMismatchSnapshot")
- .build();
-
- final Rect frame;
- // We can just show the surface here as it will still be hidden as the parent is
- // still hidden.
- mTransaction.show(childSurfaceControl);
- if (aspectRatioMismatch) {
- // Clip off ugly navigation bar.
- final Rect crop = calculateSnapshotCrop();
- frame = calculateSnapshotFrame(crop);
- mTransaction.setWindowCrop(childSurfaceControl, crop);
- mTransaction.setPosition(childSurfaceControl, frame.left, frame.top);
- mTmpSnapshotSize.set(crop);
- mTmpDstFrame.set(frame);
- } else {
- frame = null;
- mTmpSnapshotSize.set(0, 0, buffer.getWidth(), buffer.getHeight());
- mTmpDstFrame.set(mFrame);
- mTmpDstFrame.offsetTo(0, 0);
- }
-
- // Scale the mismatch dimensions to fill the task bounds
- mSnapshotMatrix.setRectToRect(mTmpSnapshotSize, mTmpDstFrame, Matrix.ScaleToFit.FILL);
- mTransaction.setMatrix(childSurfaceControl, mSnapshotMatrix, mTmpFloat9);
-
- GraphicBuffer graphicBuffer = GraphicBuffer.createFromHardwareBuffer(
- mSnapshot.getHardwareBuffer());
- mTransaction.setColorSpace(childSurfaceControl, mSnapshot.getColorSpace());
- mTransaction.setBuffer(childSurfaceControl, graphicBuffer);
- // This is the way to tell the input system to exclude this surface from occlusion
- // detection since we don't have a window for it. We do this because this window is
- // generated by the system as well as its content (the snapshot of the app).
- InputMonitor.setTrustedOverlayInputInfo(childSurfaceControl, mTransaction, mDisplayId,
- name);
-
- if (aspectRatioMismatch) {
- GraphicBuffer background = GraphicBuffer.create(mFrame.width(), mFrame.height(),
- PixelFormat.RGBA_8888,
- GraphicBuffer.USAGE_HW_TEXTURE | GraphicBuffer.USAGE_HW_COMPOSER
- | GraphicBuffer.USAGE_SW_WRITE_RARELY);
- final Canvas c = background.lockCanvas();
- drawBackgroundAndBars(c, frame);
- background.unlockCanvasAndPost(c);
- mTransaction.setBuffer(mSurfaceControl, background);
- }
- mTransaction.apply();
- }
-
- /**
- * Calculates the snapshot crop in snapshot coordinate space.
- *
- * @return crop rect in snapshot coordinate space.
- */
- @VisibleForTesting
- Rect calculateSnapshotCrop() {
- final Rect rect = new Rect();
- final HardwareBuffer snapshot = mSnapshot.getHardwareBuffer();
- rect.set(0, 0, snapshot.getWidth(), snapshot.getHeight());
- final Rect insets = mSnapshot.getContentInsets();
-
- final float scaleX = (float) snapshot.getWidth() / mSnapshot.getTaskSize().x;
- final float scaleY = (float) snapshot.getHeight() / mSnapshot.getTaskSize().y;
-
- // Let's remove all system decorations except the status bar, but only if the task is at the
- // very top of the screen.
- final boolean isTop = mTaskBounds.top == 0 && mFrame.top == 0;
- rect.inset((int) (insets.left * scaleX),
- isTop ? 0 : (int) (insets.top * scaleY),
- (int) (insets.right * scaleX),
- (int) (insets.bottom * scaleY));
- return rect;
- }
-
- /**
- * Calculates the snapshot frame in window coordinate space from crop.
- *
- * @param crop rect that is in snapshot coordinate space.
- */
- @VisibleForTesting
- Rect calculateSnapshotFrame(Rect crop) {
- final HardwareBuffer snapshot = mSnapshot.getHardwareBuffer();
- final float scaleX = (float) snapshot.getWidth() / mSnapshot.getTaskSize().x;
- final float scaleY = (float) snapshot.getHeight() / mSnapshot.getTaskSize().y;
-
- // Rescale the frame from snapshot to window coordinate space
- final Rect frame = new Rect(0, 0,
- (int) (crop.width() / scaleX + 0.5f),
- (int) (crop.height() / scaleY + 0.5f)
- );
-
- // However, we also need to make space for the navigation bar on the left side.
- frame.offset(mSystemBarInsets.left, 0);
- return frame;
- }
-
- @VisibleForTesting
- void drawBackgroundAndBars(Canvas c, Rect frame) {
- final int statusBarHeight = mSystemBarBackgroundPainter.getStatusBarColorViewHeight();
- final boolean fillHorizontally = c.getWidth() > frame.right;
- final boolean fillVertically = c.getHeight() > frame.bottom;
- if (fillHorizontally) {
- c.drawRect(frame.right, alpha(mStatusBarColor) == 0xFF ? statusBarHeight : 0,
- c.getWidth(), fillVertically
- ? frame.bottom
- : c.getHeight(),
- mBackgroundPaint);
- }
- if (fillVertically) {
- c.drawRect(0, frame.bottom, c.getWidth(), c.getHeight(), mBackgroundPaint);
- }
- mSystemBarBackgroundPainter.drawDecors(c, frame);
- }
-
- private void reportDrawn() {
- try {
- mSession.finishDrawing(mWindow, null /* postDrawTransaction */);
- } catch (RemoteException e) {
- // Local call.
- }
- }
-
- private static Handler sHandler = new Handler(Looper.getMainLooper()) {
-
- @Override
- public void handleMessage(Message msg) {
- switch (msg.what) {
- case MSG_REPORT_DRAW:
- final boolean hasDrawn;
- final TaskSnapshotSurface surface = (TaskSnapshotSurface) msg.obj;
- synchronized (surface.mService.mGlobalLock) {
- hasDrawn = surface.mHasDrawn;
- }
- if (hasDrawn) {
- surface.reportDrawn();
- }
- break;
- }
- }
- };
-
- @VisibleForTesting
- static class Window extends BaseIWindow {
-
- private TaskSnapshotSurface mOuter;
-
- public void setOuter(TaskSnapshotSurface outer) {
- mOuter = outer;
- }
-
- @Override
- public void resized(ClientWindowFrames frames, boolean reportDraw,
- MergedConfiguration mergedConfiguration, boolean forceLayout,
- boolean alwaysConsumeSystemBars, int displayId) {
- if (mergedConfiguration != null && mOuter != null
- && mOuter.mOrientationOnCreation
- != mergedConfiguration.getMergedConfiguration().orientation) {
-
- // The orientation of the screen is changing. We better remove the snapshot ASAP as
- // we are going to wait on the new window in any case to unfreeze the screen, and
- // the starting window is not needed anymore.
- sHandler.post(() -> mOuter.remove(false /* prepareAnimation */));
- }
- if (reportDraw) {
- sHandler.obtainMessage(MSG_REPORT_DRAW, mOuter).sendToTarget();
- }
- }
- }
-
- /**
- * Helper class to draw the background of the system bars in regions the task snapshot isn't
- * filling the window.
- */
- static class SystemBarBackgroundPainter {
-
- private final Paint mStatusBarPaint = new Paint();
- private final Paint mNavigationBarPaint = new Paint();
- private final int mStatusBarColor;
- private final int mNavigationBarColor;
- private final int mWindowFlags;
- private final int mWindowPrivateFlags;
- private final float mScale;
- private final InsetsState mInsetsState;
- private final Rect mSystemBarInsets = new Rect();
-
- SystemBarBackgroundPainter(int windowFlags, int windowPrivateFlags, int appearance,
- TaskDescription taskDescription, float scale, InsetsState insetsState) {
- mWindowFlags = windowFlags;
- mWindowPrivateFlags = windowPrivateFlags;
- mScale = scale;
- final Context context = ActivityThread.currentActivityThread().getSystemUiContext();
- final int semiTransparent = context.getColor(
- R.color.system_bar_background_semi_transparent);
- mStatusBarColor = DecorView.calculateBarColor(windowFlags, FLAG_TRANSLUCENT_STATUS,
- semiTransparent, taskDescription.getStatusBarColor(), appearance,
- APPEARANCE_LIGHT_STATUS_BARS,
- taskDescription.getEnsureStatusBarContrastWhenTransparent());
- mNavigationBarColor = DecorView.calculateBarColor(windowFlags,
- FLAG_TRANSLUCENT_NAVIGATION, semiTransparent,
- taskDescription.getNavigationBarColor(), appearance,
- APPEARANCE_LIGHT_NAVIGATION_BARS,
- taskDescription.getEnsureNavigationBarContrastWhenTransparent()
- && context.getResources().getBoolean(R.bool.config_navBarNeedsScrim));
- mStatusBarPaint.setColor(mStatusBarColor);
- mNavigationBarPaint.setColor(mNavigationBarColor);
- mInsetsState = insetsState;
- }
-
- void setInsets(Rect systemBarInsets) {
- mSystemBarInsets.set(systemBarInsets);
- }
-
- int getStatusBarColorViewHeight() {
- final boolean forceBarBackground =
- (mWindowPrivateFlags & PRIVATE_FLAG_FORCE_DRAW_BAR_BACKGROUNDS) != 0;
- if (STATUS_BAR_COLOR_VIEW_ATTRIBUTES.isVisible(
- mInsetsState, mStatusBarColor, mWindowFlags, forceBarBackground)) {
- return (int) (mSystemBarInsets.top * mScale);
- } else {
- return 0;
- }
- }
-
- private boolean isNavigationBarColorViewVisible() {
- final boolean forceBarBackground =
- (mWindowPrivateFlags & PRIVATE_FLAG_FORCE_DRAW_BAR_BACKGROUNDS) != 0;
- return NAVIGATION_BAR_COLOR_VIEW_ATTRIBUTES.isVisible(
- mInsetsState, mNavigationBarColor, mWindowFlags, forceBarBackground);
- }
-
- void drawDecors(Canvas c, @Nullable Rect alreadyDrawnFrame) {
- drawStatusBarBackground(c, alreadyDrawnFrame, getStatusBarColorViewHeight());
- drawNavigationBarBackground(c);
- }
-
- @VisibleForTesting
- void drawStatusBarBackground(Canvas c, @Nullable Rect alreadyDrawnFrame,
- int statusBarHeight) {
- if (statusBarHeight > 0 && Color.alpha(mStatusBarColor) != 0
- && (alreadyDrawnFrame == null || c.getWidth() > alreadyDrawnFrame.right)) {
- final int rightInset = (int) (mSystemBarInsets.right * mScale);
- final int left = alreadyDrawnFrame != null ? alreadyDrawnFrame.right : 0;
- c.drawRect(left, 0, c.getWidth() - rightInset, statusBarHeight, mStatusBarPaint);
- }
- }
-
- @VisibleForTesting
- void drawNavigationBarBackground(Canvas c) {
- final Rect navigationBarRect = new Rect();
- getNavigationBarRect(c.getWidth(), c.getHeight(), mSystemBarInsets, navigationBarRect,
- mScale);
- final boolean visible = isNavigationBarColorViewVisible();
- if (visible && Color.alpha(mNavigationBarColor) != 0 && !navigationBarRect.isEmpty()) {
- c.drawRect(navigationBarRect, mNavigationBarPaint);
- }
- }
- }
-}
diff --git a/services/core/java/com/android/server/wm/Transition.java b/services/core/java/com/android/server/wm/Transition.java
index 9fc45b9..4db8ef4 100644
--- a/services/core/java/com/android/server/wm/Transition.java
+++ b/services/core/java/com/android/server/wm/Transition.java
@@ -165,13 +165,13 @@
private boolean mNavBarAttachedToApp = false;
private int mRecentsDisplayId = INVALID_DISPLAY;
- Transition(@TransitionType int type, @TransitionFlags int flags,
+ Transition(@TransitionType int type, @TransitionFlags int flags, long timeoutMs,
TransitionController controller, BLASTSyncEngine syncEngine) {
mType = type;
mFlags = flags;
mController = controller;
mSyncEngine = syncEngine;
- mSyncId = mSyncEngine.startSyncSet(this);
+ mSyncId = mSyncEngine.startSyncSet(this, timeoutMs);
}
void addFlag(int flag) {
@@ -338,6 +338,11 @@
applyReady();
}
+ @VisibleForTesting
+ boolean allReady() {
+ return mReadyTracker.allReady();
+ }
+
/**
* Build a transaction that "resets" all the re-parenting and layer changes. This is
* intended to be applied at the end of the transition but before the finish callback. This
diff --git a/services/core/java/com/android/server/wm/TransitionController.java b/services/core/java/com/android/server/wm/TransitionController.java
index bf4cf5f..a21e4f2 100644
--- a/services/core/java/com/android/server/wm/TransitionController.java
+++ b/services/core/java/com/android/server/wm/TransitionController.java
@@ -17,6 +17,7 @@
package com.android.server.wm;
import static android.app.WindowConfiguration.ACTIVITY_TYPE_HOME;
+import static android.view.WindowManager.TRANSIT_CHANGE;
import static android.view.WindowManager.TRANSIT_CLOSE;
import static android.view.WindowManager.TRANSIT_FLAG_IS_RECENTS;
import static android.view.WindowManager.TRANSIT_FLAG_KEYGUARD_GOING_AWAY;
@@ -34,7 +35,6 @@
import android.util.Slog;
import android.util.proto.ProtoOutputStream;
import android.view.WindowManager;
-import android.window.IRemoteTransition;
import android.window.ITransitionMetricsReporter;
import android.window.ITransitionPlayer;
import android.window.RemoteTransition;
@@ -55,6 +55,11 @@
class TransitionController {
private static final String TAG = "TransitionController";
+ /** The same as legacy APP_TRANSITION_TIMEOUT_MS. */
+ private static final int DEFAULT_TIMEOUT_MS = 5000;
+ /** Less duration for CHANGE type because it does not involve app startup. */
+ private static final int CHANGE_TIMEOUT_MS = 2000;
+
// State constants to line-up with legacy app-transition proto expectations.
private static final int LEGACY_STATE_IDLE = 0;
private static final int LEGACY_STATE_READY = 1;
@@ -121,7 +126,10 @@
if (mCollectingTransition != null) {
throw new IllegalStateException("Simultaneous transitions not supported yet.");
}
- mCollectingTransition = new Transition(type, flags, this, mAtm.mWindowManager.mSyncEngine);
+ // Distinguish change type because the response time is usually expected to be not too long.
+ final long timeoutMs = type == TRANSIT_CHANGE ? CHANGE_TIMEOUT_MS : DEFAULT_TIMEOUT_MS;
+ mCollectingTransition = new Transition(type, flags, timeoutMs, this,
+ mAtm.mWindowManager.mSyncEngine);
ProtoLog.v(ProtoLogGroup.WM_DEBUG_WINDOW_TRANSITIONS, "Creating Transition: %s",
mCollectingTransition);
dispatchLegacyAppTransitionPending();
@@ -217,7 +225,7 @@
}
/**
- * @see #requestTransitionIfNeeded(int, int, WindowContainer, IRemoteTransition)
+ * @see #requestTransitionIfNeeded(int, int, WindowContainer, WindowContainer, RemoteTransition)
*/
@Nullable
Transition requestTransitionIfNeeded(@WindowManager.TransitionType int type,
@@ -226,7 +234,7 @@
}
/**
- * @see #requestTransitionIfNeeded(int, int, WindowContainer, IRemoteTransition)
+ * @see #requestTransitionIfNeeded(int, int, WindowContainer, WindowContainer, RemoteTransition)
*/
@Nullable
Transition requestTransitionIfNeeded(@WindowManager.TransitionType int type,
@@ -297,6 +305,22 @@
return transition;
}
+ /** Requests transition for a window container which will be removed or invisible. */
+ void requestCloseTransitionIfNeeded(@NonNull WindowContainer<?> wc) {
+ if (mTransitionPlayer == null) return;
+ if (wc.isVisibleRequested()) {
+ if (!isCollecting()) {
+ requestStartTransition(createTransition(TRANSIT_CLOSE, 0 /* flags */),
+ wc.asTask(), null /* remoteTransition */);
+ }
+ collectExistenceChange(wc);
+ } else {
+ // Removing a non-visible window doesn't require a transition, but if there is one
+ // collecting, this should be a member just in case.
+ collect(wc);
+ }
+ }
+
/** @see Transition#collect */
void collect(@NonNull WindowContainer wc) {
if (mCollectingTransition == null) return;
diff --git a/services/core/java/com/android/server/wm/WallpaperController.java b/services/core/java/com/android/server/wm/WallpaperController.java
index d93b649..08b1a2f 100644
--- a/services/core/java/com/android/server/wm/WallpaperController.java
+++ b/services/core/java/com/android/server/wm/WallpaperController.java
@@ -97,12 +97,6 @@
// Time we wait after a timeout before trying to wait again.
private static final long WALLPAPER_TIMEOUT_RECOVERY = 10000;
- // Set to the wallpaper window we would like to hide once the transition animations are done.
- // This is useful in cases where we don't want the wallpaper to be hidden when the close app
- // is a wallpaper target and is done animating out, but the opening app isn't a wallpaper
- // target and isn't done animating in.
- WindowState mDeferredHideWallpaper = null;
-
// We give a wallpaper up to 500ms to finish drawing before playing app transitions.
private static final long WALLPAPER_DRAW_PENDING_TIMEOUT_DURATION = 500;
private static final int WALLPAPER_DRAW_NORMAL = 0;
@@ -165,7 +159,8 @@
boolean needsShowWhenLockedWallpaper = false;
if ((w.mAttrs.flags & FLAG_SHOW_WHEN_LOCKED) != 0
&& mService.mPolicy.isKeyguardLocked()
- && mService.mPolicy.isKeyguardOccluded()) {
+ && (mService.mPolicy.isKeyguardOccluded()
+ || mService.mPolicy.isKeyguardUnoccluding())) {
// The lowest show when locked window decides whether we need to put the wallpaper
// behind.
needsShowWhenLockedWallpaper = !isFullscreen(w.mAttrs)
diff --git a/services/core/java/com/android/server/wm/WindowContainer.java b/services/core/java/com/android/server/wm/WindowContainer.java
index cae5b14..b4e07d3 100644
--- a/services/core/java/com/android/server/wm/WindowContainer.java
+++ b/services/core/java/com/android/server/wm/WindowContainer.java
@@ -32,10 +32,6 @@
import static android.view.SurfaceControl.Transaction;
import static android.view.WindowManager.LayoutParams.INVALID_WINDOW_TYPE;
import static android.view.WindowManager.TRANSIT_CHANGE;
-import static android.view.WindowManager.TRANSIT_OLD_TASK_CLOSE;
-import static android.view.WindowManager.TRANSIT_OLD_TASK_OPEN;
-import static android.view.WindowManager.TRANSIT_OLD_TASK_TO_BACK;
-import static android.view.WindowManager.TRANSIT_OLD_TASK_TO_FRONT;
import static com.android.internal.protolog.ProtoLogGroup.WM_DEBUG_APP_TRANSITIONS;
import static com.android.internal.protolog.ProtoLogGroup.WM_DEBUG_APP_TRANSITIONS_ANIM;
@@ -43,6 +39,7 @@
import static com.android.internal.protolog.ProtoLogGroup.WM_DEBUG_SYNC_ENGINE;
import static com.android.server.policy.WindowManagerPolicy.FINISH_LAYOUT_REDO_WALLPAPER;
import static com.android.server.wm.AppTransition.MAX_APP_TRANSITION_DURATION;
+import static com.android.server.wm.AppTransition.isTaskTransitOld;
import static com.android.server.wm.DisplayContent.IME_TARGET_LAYERING;
import static com.android.server.wm.IdentifierProto.HASH_CODE;
import static com.android.server.wm.IdentifierProto.TITLE;
@@ -70,7 +67,6 @@
import android.annotation.IntDef;
import android.annotation.NonNull;
import android.annotation.Nullable;
-import android.app.ActivityThread;
import android.content.Context;
import android.content.pm.ActivityInfo;
import android.content.res.Configuration;
@@ -91,6 +87,7 @@
import android.view.SurfaceControl;
import android.view.SurfaceControl.Builder;
import android.view.SurfaceSession;
+import android.view.TaskTransitionSpec;
import android.view.WindowManager;
import android.view.WindowManager.TransitionOldType;
import android.view.animation.Animation;
@@ -906,7 +903,7 @@
* container.
*/
boolean canCustomizeAppTransition() {
- return !WindowManagerService.sDisableCustomTaskAnimationProperty;
+ return false;
}
/**
@@ -2809,33 +2806,15 @@
mSurfaceAnimationSources.addAll(sources);
}
- TaskDisplayArea taskDisplayArea = getTaskDisplayArea();
- boolean isSettingBackgroundColor = taskDisplayArea != null
- && isTransitionWithBackgroundColor(transit);
+ AnimationRunnerBuilder animationRunnerBuilder = new AnimationRunnerBuilder();
- if (isSettingBackgroundColor) {
- Context uiContext = ActivityThread.currentActivityThread().getSystemUiContext();
- @ColorInt int backgroundColor = uiContext.getColor(R.color.overview_background);
-
- taskDisplayArea.setBackgroundColor(backgroundColor);
+ if (isTaskTransitOld(transit)) {
+ animationRunnerBuilder.setTaskBackgroundColor(getTaskAnimationBackgroundColor());
}
- // Atomic counter to make sure the clearColor callback is only called one.
- // It will be called twice in the case we cancel the animation without restart
- // (in that case it will run as the cancel and finished callbacks).
- final AtomicInteger callbackCounter = new AtomicInteger(0);
- final Runnable clearBackgroundColorHandler = () -> {
- if (callbackCounter.getAndIncrement() == 0) {
- taskDisplayArea.clearBackgroundColor();
- }
- };
-
- final Runnable cleanUpCallback = isSettingBackgroundColor
- ? clearBackgroundColorHandler : () -> {};
-
- startAnimation(getPendingTransaction(), adapter, !isVisible(),
- ANIMATION_TYPE_APP_TRANSITION, (type, anim) -> cleanUpCallback.run(),
- cleanUpCallback, thumbnailAdapter);
+ animationRunnerBuilder.build()
+ .startAnimation(getPendingTransaction(), adapter, !isVisible(),
+ ANIMATION_TYPE_APP_TRANSITION, thumbnailAdapter);
if (adapter.getShowWallpaper()) {
getDisplayContent().pendingLayoutChanges |= FINISH_LAYOUT_REDO_WALLPAPER;
@@ -2843,11 +2822,16 @@
}
}
- private boolean isTransitionWithBackgroundColor(@TransitionOldType int transit) {
- return transit == TRANSIT_OLD_TASK_OPEN
- || transit == TRANSIT_OLD_TASK_CLOSE
- || transit == TRANSIT_OLD_TASK_TO_FRONT
- || transit == TRANSIT_OLD_TASK_TO_BACK;
+ private @ColorInt int getTaskAnimationBackgroundColor() {
+ Context uiContext = mDisplayContent.getDisplayPolicy().getSystemUiContext();
+ TaskTransitionSpec customSpec = mWmService.mTaskTransitionSpec;
+ @ColorInt int defaultFallbackColor = uiContext.getColor(R.color.overview_background);
+
+ if (customSpec != null && customSpec.backgroundColor != 0) {
+ return customSpec.backgroundColor;
+ }
+
+ return defaultFallbackColor;
}
final SurfaceAnimationRunner getSurfaceAnimationRunner() {
@@ -3535,4 +3519,53 @@
getPendingTransaction().setSecure(mSurfaceControl, !canScreenshot);
return true;
}
+
+ private class AnimationRunnerBuilder {
+ /**
+ * Runs when the surface stops animating
+ */
+ private final List<Runnable> mOnAnimationFinished = new LinkedList<>();
+ /**
+ * Runs when the animation is cancelled but the surface is still animating
+ */
+ private final List<Runnable> mOnAnimationCancelled = new LinkedList<>();
+
+ private void setTaskBackgroundColor(@ColorInt int backgroundColor) {
+ TaskDisplayArea taskDisplayArea = getTaskDisplayArea();
+
+ if (taskDisplayArea != null) {
+ taskDisplayArea.setBackgroundColor(backgroundColor);
+
+ // Atomic counter to make sure the clearColor callback is only called one.
+ // It will be called twice in the case we cancel the animation without restart
+ // (in that case it will run as the cancel and finished callbacks).
+ final AtomicInteger callbackCounter = new AtomicInteger(0);
+ final Runnable clearBackgroundColorHandler = () -> {
+ if (callbackCounter.getAndIncrement() == 0) {
+ taskDisplayArea.clearBackgroundColor();
+ }
+ };
+
+ // We want to make sure this is called both when the surface stops animating and
+ // also when an animation is cancelled (i.e. animation is replaced by another
+ // animation but and so the surface is still animating)
+ mOnAnimationFinished.add(clearBackgroundColorHandler);
+ mOnAnimationCancelled.add(clearBackgroundColorHandler);
+ }
+ }
+
+ private IAnimationStarter build() {
+ return (Transaction t, AnimationAdapter adapter, boolean hidden,
+ @AnimationType int type, @Nullable AnimationAdapter snapshotAnim) -> {
+ startAnimation(getPendingTransaction(), adapter, !isVisible(), type,
+ (animType, anim) -> mOnAnimationFinished.forEach(Runnable::run),
+ () -> mOnAnimationCancelled.forEach(Runnable::run), snapshotAnim);
+ };
+ }
+ }
+
+ private interface IAnimationStarter {
+ void startAnimation(Transaction t, AnimationAdapter anim, boolean hidden,
+ @AnimationType int type, @Nullable AnimationAdapter snapshotAnim);
+ }
}
diff --git a/services/core/java/com/android/server/wm/WindowFrames.java b/services/core/java/com/android/server/wm/WindowFrames.java
index baea854..c3d3c82 100644
--- a/services/core/java/com/android/server/wm/WindowFrames.java
+++ b/services/core/java/com/android/server/wm/WindowFrames.java
@@ -17,7 +17,6 @@
package com.android.server.wm;
import static com.android.server.wm.WindowFramesProto.COMPAT_FRAME;
-import static com.android.server.wm.WindowFramesProto.CONTAINING_FRAME;
import static com.android.server.wm.WindowFramesProto.DISPLAY_FRAME;
import static com.android.server.wm.WindowFramesProto.FRAME;
import static com.android.server.wm.WindowFramesProto.PARENT_FRAME;
@@ -37,32 +36,16 @@
private static final StringBuilder sTmpSB = new StringBuilder();
/**
- * In most cases, this is the area of the entire screen.
- *
- * TODO(b/111611553): The name is unclear and most likely should be swapped with
- * {@link #mDisplayFrame}
- * TODO(b/111611553): In some cases, it also includes top insets, like for IME. Determine
- * whether this is still necessary to do.
+ * The frame to be referenced while applying gravity and MATCH_PARENT.
*/
public final Rect mParentFrame = new Rect();
/**
- * The entire screen area of the {@link Task} this window is in. Usually equal to the
- * screen area of the device.
- *
- * TODO(b/111611553): The name is unclear and most likely should be swapped with
- * {@link #mParentFrame}
+ * The bounds that the window should fit.
*/
public final Rect mDisplayFrame = new Rect();
/**
- * Similar to {@link #mDisplayFrame}
- *
- * TODO: Why is this different than mDisplayFrame
- */
- final Rect mContainingFrame = new Rect();
-
- /**
* "Real" frame that the application sees, in display coordinate space.
*/
final Rect mFrame = new Rect();
@@ -124,10 +107,6 @@
return (mLastFrame.width() != mFrame.width()) || (mLastFrame.height() != mFrame.height());
}
- void offsetFrames(int layoutXDiff, int layoutYDiff) {
- mFrame.offset(layoutXDiff, layoutYDiff);
- }
-
/**
* Updates info about whether the size of the window has changed since last reported.
*
@@ -188,16 +167,13 @@
final long token = proto.start(fieldId);
mParentFrame.dumpDebug(proto, PARENT_FRAME);
mDisplayFrame.dumpDebug(proto, DISPLAY_FRAME);
- mContainingFrame.dumpDebug(proto, CONTAINING_FRAME);
mFrame.dumpDebug(proto, FRAME);
mCompatFrame.dumpDebug(proto, COMPAT_FRAME);
proto.end(token);
}
public void dump(PrintWriter pw, String prefix) {
- pw.println(prefix + "Frames: containing="
- + mContainingFrame.toShortString(sTmpSB)
- + " parent=" + mParentFrame.toShortString(sTmpSB)
+ pw.println(prefix + "Frames: parent=" + mParentFrame.toShortString(sTmpSB)
+ " display=" + mDisplayFrame.toShortString(sTmpSB));
pw.println(prefix + "mFrame=" + mFrame.toShortString(sTmpSB)
+ " last=" + mLastFrame.toShortString(sTmpSB));
diff --git a/services/core/java/com/android/server/wm/WindowManagerService.java b/services/core/java/com/android/server/wm/WindowManagerService.java
index 9acc408..60c660f 100644
--- a/services/core/java/com/android/server/wm/WindowManagerService.java
+++ b/services/core/java/com/android/server/wm/WindowManagerService.java
@@ -169,10 +169,8 @@
import android.database.ContentObserver;
import android.graphics.Bitmap;
import android.graphics.Insets;
-import android.graphics.Matrix;
import android.graphics.Point;
import android.graphics.Rect;
-import android.graphics.RectF;
import android.graphics.Region;
import android.hardware.configstore.V1_0.OptionalBool;
import android.hardware.configstore.V1_1.DisplayOrientation;
@@ -343,8 +341,6 @@
implements Watchdog.Monitor, WindowManagerPolicy.WindowManagerFuncs {
private static final String TAG = TAG_WITH_CLASS_NAME ? "WindowManagerService" : TAG_WM;
- private static final String WM_USE_BLAST_ADAPTER_FLAG = "wm_use_blast_adapter";
-
static final int LAYOUT_REPEAT_THRESHOLD = 4;
static final boolean PROFILE_ORIENTATION = false;
@@ -399,21 +395,6 @@
static final int LOGTAG_INPUT_FOCUS = 62001;
/**
- * Restrict ability of activities overriding transition animation in a way such that
- * an activity can do it only when the transition happens within a same task.
- *
- * @see android.app.Activity#overridePendingTransition(int, int)
- */
- private static final String DISABLE_CUSTOM_TASK_ANIMATION_PROPERTY =
- "persist.wm.disable_custom_task_animation";
-
- /**
- * @see #DISABLE_CUSTOM_TASK_ANIMATION_PROPERTY
- */
- static boolean sDisableCustomTaskAnimationProperty =
- SystemProperties.getBoolean(DISABLE_CUSTOM_TASK_ANIMATION_PROPERTY, true);
-
- /**
* Use WMShell for app transition.
*/
public static final String ENABLE_SHELL_TRANSITIONS = "persist.debug.shell_transit";
@@ -646,13 +627,7 @@
StrictModeFlash mStrictModeFlash;
EmulatorDisplayOverlay mEmulatorDisplayOverlay;
- final float[] mTmpFloats = new float[9];
final Rect mTmpRect = new Rect();
- final Rect mTmpRect2 = new Rect();
- final Rect mTmpRect3 = new Rect();
- final RectF mTmpRectF = new RectF();
-
- final Matrix mTmpTransform = new Matrix();
boolean mDisplayReady;
boolean mSafeMode;
@@ -1059,8 +1034,6 @@
public void focusChanged();
}
- final Configuration mTempConfiguration = new Configuration();
-
final HighRefreshRateDenylist mHighRefreshRateDenylist;
// Maintainer of a collection of all possible DisplayInfo for all configurations of the
@@ -1156,11 +1129,6 @@
void onAppFreezeTimeout();
}
- private static WindowManagerService sInstance;
- static WindowManagerService getInstance() {
- return sInstance;
- }
-
public static WindowManagerService main(final Context context, final InputManagerService im,
final boolean showBootMsgs, final boolean onlyCore, WindowManagerPolicy policy,
ActivityTaskManagerService atm) {
@@ -1180,11 +1148,12 @@
displayWindowSettingsProvider, Supplier<SurfaceControl.Transaction> transactionFactory,
Supplier<Surface> surfaceFactory,
Function<SurfaceSession, SurfaceControl.Builder> surfaceControlFactory) {
+ final WindowManagerService[] wms = new WindowManagerService[1];
DisplayThread.getHandler().runWithScissors(() ->
- sInstance = new WindowManagerService(context, im, showBootMsgs, onlyCore, policy,
+ wms[0] = new WindowManagerService(context, im, showBootMsgs, onlyCore, policy,
atm, displayWindowSettingsProvider, transactionFactory, surfaceFactory,
surfaceControlFactory), 0);
- return sInstance;
+ return wms[0];
}
private void initPolicy() {
@@ -1783,6 +1752,7 @@
win.mToken.addWindow(win);
displayPolicy.addWindowLw(win, attrs);
+ displayPolicy.setDropInputModePolicy(win, win.mAttrs);
if (type == TYPE_APPLICATION_STARTING && activity != null) {
activity.attachStartingWindow(win);
ProtoLog.v(WM_DEBUG_STARTING_WINDOW, "addWindow: %s startingWindow=%s",
@@ -2515,9 +2485,11 @@
}
win.mInRelayout = false;
- if (mUseBLASTSync && win.useBLASTSync() && viewVisibility != View.GONE) {
+ if (mUseBLASTSync && win.useBLASTSync() && viewVisibility != View.GONE
+ && win.mNextRelayoutUseSync) {
win.prepareDrawHandlers();
win.markRedrawForSyncReported();
+ win.mNextRelayoutUseSync = false;
result |= RELAYOUT_RES_BLAST_SYNC;
}
@@ -3014,15 +2986,6 @@
aspectRatio);
}
- void getRootTaskBounds(int windowingMode, int activityType, Rect bounds) {
- final Task rootTask = mRoot.getRootTask(windowingMode, activityType);
- if (rootTask != null) {
- rootTask.getBounds(bounds);
- return;
- }
- bounds.setEmpty();
- }
-
/**
* Notifies window manager that {@link DisplayPolicy#isShowingDreamLw} has changed.
*/
@@ -3080,6 +3043,11 @@
syncInputTransactions(true /* waitForAnimations */);
}
+ @Override
+ public boolean isAppTransitionStateIdle() {
+ return getDefaultDisplayContentLocked().mAppTransition.isIdle();
+ }
+
/**
* Notifies activity manager that some Keyguard flags have changed and that it needs to
* reevaluate the visibilities of the activities.
@@ -5390,6 +5358,7 @@
case WINDOW_STATE_BLAST_SYNC_TIMEOUT: {
synchronized (mGlobalLock) {
final WindowState ws = (WindowState) msg.obj;
+ Slog.i(TAG, "Blast sync timeout: " + ws);
ws.immediatelyNotifyBlastSync();
}
break;
@@ -6988,12 +6957,6 @@
}
}
- void intersectDisplayInsetBounds(Rect display, Rect insets, Rect inOutBounds) {
- mTmpRect3.set(display);
- mTmpRect3.inset(insets);
- inOutBounds.intersect(mTmpRect3);
- }
-
MousePositionTracker mMousePositionTracker = new MousePositionTracker();
private static class MousePositionTracker implements PointerEventListener {
diff --git a/services/core/java/com/android/server/wm/WindowState.java b/services/core/java/com/android/server/wm/WindowState.java
index 47aafc2..3a98a37 100644
--- a/services/core/java/com/android/server/wm/WindowState.java
+++ b/services/core/java/com/android/server/wm/WindowState.java
@@ -38,10 +38,9 @@
import static android.view.ViewTreeObserver.InternalInsetsInfo.TOUCHABLE_INSETS_FRAME;
import static android.view.ViewTreeObserver.InternalInsetsInfo.TOUCHABLE_INSETS_REGION;
import static android.view.ViewTreeObserver.InternalInsetsInfo.TOUCHABLE_INSETS_VISIBLE;
-import static android.view.WindowInsets.Type.displayCutout;
-import static android.view.WindowInsets.Type.ime;
import static android.view.WindowInsets.Type.systemBars;
import static android.view.WindowInsetsController.BEHAVIOR_SHOW_TRANSIENT_BARS_BY_SWIPE;
+import static android.view.WindowLayout.UNSPECIFIED_LENGTH;
import static android.view.WindowManager.LayoutParams.FIRST_SUB_WINDOW;
import static android.view.WindowManager.LayoutParams.FIRST_SYSTEM_WINDOW;
import static android.view.WindowManager.LayoutParams.FLAG_ALLOW_LOCK_WHILE_SCREEN_ON;
@@ -49,7 +48,6 @@
import static android.view.WindowManager.LayoutParams.FLAG_BLUR_BEHIND;
import static android.view.WindowManager.LayoutParams.FLAG_DIM_BEHIND;
import static android.view.WindowManager.LayoutParams.FLAG_DISMISS_KEYGUARD;
-import static android.view.WindowManager.LayoutParams.FLAG_LAYOUT_NO_LIMITS;
import static android.view.WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE;
import static android.view.WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL;
import static android.view.WindowManager.LayoutParams.FLAG_SCALED;
@@ -60,7 +58,6 @@
import static android.view.WindowManager.LayoutParams.LAYOUT_IN_DISPLAY_CUTOUT_MODE_ALWAYS;
import static android.view.WindowManager.LayoutParams.MATCH_PARENT;
import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_COMPATIBLE_WINDOW;
-import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_LAYOUT_CHILD_WINDOW_IN_PARENT_FRAME;
import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_NOT_MAGNIFIABLE;
import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_NO_MOVE_ANIMATION;
import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_TRUSTED_OVERLAY;
@@ -224,7 +221,6 @@
import android.util.proto.ProtoOutputStream;
import android.view.Display;
import android.view.DisplayInfo;
-import android.view.Gravity;
import android.view.IWindow;
import android.view.IWindowFocusObserver;
import android.view.IWindowId;
@@ -367,6 +363,7 @@
private boolean mDragResizingChangeReported = true;
private int mResizeMode;
private boolean mRedrawForSyncReported;
+ boolean mNextRelayoutUseSync;
/**
* {@code true} when the client was still drawing for sync when the sync-set was finished or
@@ -473,9 +470,6 @@
/** The frames used to compute a temporal layout appearance. */
private WindowFrames mSimulatedWindowFrames;
- /** Usually the same as {@link #getBounds()}. */
- private final Rect mInsetFrame = new Rect();
-
/**
* List of rects where system gestures should be ignored.
*
@@ -657,7 +651,6 @@
private PowerManager.WakeLock mDrawLock;
private final Rect mTmpRect = new Rect();
- private final Rect mTmpRect2 = new Rect();
private final Point mTmpPoint = new Point();
private final Transaction mTmpTransaction;
@@ -1138,10 +1131,10 @@
mWinAnimator = new WindowStateAnimator(this);
mWinAnimator.mAlpha = a.alpha;
- mRequestedWidth = 0;
- mRequestedHeight = 0;
- mLastRequestedWidth = 0;
- mLastRequestedHeight = 0;
+ mRequestedWidth = UNSPECIFIED_LENGTH;
+ mRequestedHeight = UNSPECIFIED_LENGTH;
+ mLastRequestedWidth = UNSPECIFIED_LENGTH;
+ mLastRequestedHeight = UNSPECIFIED_LENGTH;
mLayer = 0;
mOverrideScale = mWmService.mAtmService.mCompatModePackages.getCompatScale(
mAttrs.packageName, s.mUid);
@@ -1235,145 +1228,26 @@
return mOwnerCanAddInternalSystemWindow;
}
- /**
- * Returns {@code true} if the window owner has the permission to acquire a sleep token when
- * it's visible. That is, they have the permission
- * {@link androidManifest.permission#DEVICE_POWER}.
- */
- boolean canAcquireSleepToken() {
- return mSession.mCanAcquireSleepToken;
- }
-
- /**
- * Subtracts the insets calculated by intersecting {@param layoutFrame} with {@param insetFrame}
- * from {@param frame}. In other words, it applies the insets that would result if
- * {@param frame} would be shifted to {@param layoutFrame} and then applying the insets from
- * {@param insetFrame}. Also it respects {@param displayFrame} in case window has minimum
- * width/height applied and insets should be overridden.
- */
- private void subtractInsets(Rect frame, Rect layoutFrame, Rect insetFrame, Rect displayFrame) {
- final int left = Math.max(0, insetFrame.left - Math.max(layoutFrame.left, displayFrame.left));
- final int top = Math.max(0, insetFrame.top - Math.max(layoutFrame.top, displayFrame.top));
- final int right = Math.max(0, Math.min(layoutFrame.right, displayFrame.right) - insetFrame.right);
- final int bottom = Math.max(0, Math.min(layoutFrame.bottom, displayFrame.bottom) - insetFrame.bottom);
- frame.inset(left, top, right, bottom);
- }
-
- void computeFrameAndUpdateSourceFrame(DisplayFrames displayFrames) {
- computeFrame(displayFrames);
- // Update the source frame to provide insets to other windows during layout. If the
- // simulated frames exist, then this is not computing a stable result so just skip.
- if (mControllableInsetProvider != null && mSimulatedWindowFrames == null) {
- mControllableInsetProvider.updateSourceFrame();
- }
- }
-
- /**
- * Perform standard frame computation. The result can be obtained with getFrame() if so desired.
- */
- void computeFrame(DisplayFrames displayFrames) {
+ boolean skipLayout() {
if (mWillReplaceWindow && (mAnimatingExit || !mReplacingRemoveRequested)) {
// This window is being replaced and either already got information that it's being
// removed or we are still waiting for some information. Because of this we don't
// want to apply any more changes to it, so it remains in this state until new window
// appears.
- return;
+ return true;
}
+ // Skip layout of the window when in transition to pip mode.
+ return mActivityRecord != null && mActivityRecord.mWaitForEnteringPinnedMode;
+ }
+
+ // TODO(b/161810301): Make the frame be passed from the client side.
+ void setFrame() {
+ // TODO(b/161810301): Set the window frame here. We don't have to do it now because
+ // DisplayPolicy has already done it for the window.
+
mHaveFrame = true;
- final Task task = getTask();
- final boolean isFullscreenAndFillsArea = !inMultiWindowMode() && matchesDisplayAreaBounds();
- final boolean windowsAreFloating = task != null && task.isFloating();
- final DisplayContent dc = getDisplayContent();
- final DisplayInfo displayInfo = getDisplayInfo();
- final WindowFrames windowFrames = getLayoutingWindowFrames();
-
- mInsetFrame.set(getBounds());
-
- // Denotes the actual frame used to calculate the insets and to perform the layout. When
- // resizing in docked mode, we'd like to freeze the layout, so we also need to freeze the
- // insets temporarily. By the notion of a task having a different layout frame, we can
- // achieve that while still moving the task around.
- final Rect layoutContainingFrame;
- final Rect layoutDisplayFrame;
-
- // The offset from the layout containing frame to the actual containing frame.
- final int layoutXDiff;
- final int layoutYDiff;
- final WindowState imeWin = mWmService.mRoot.getCurrentInputMethodWindow();
- final InsetsControlTarget imeTarget = dc.getImeTarget(IME_TARGET_LAYERING);
- final boolean isInputMethodAdjustTarget = windowsAreFloating
- ? imeTarget != null && task == imeTarget.getWindow().getTask()
- : isImeLayeringTarget();
- final boolean isImeTarget =
- imeWin != null && imeWin.isVisibleNow() && isInputMethodAdjustTarget;
- if (isFullscreenAndFillsArea || layoutInParentFrame()) {
- // We use the parent frame as the containing frame for fullscreen and child windows
- windowFrames.mContainingFrame.set(windowFrames.mParentFrame);
- layoutDisplayFrame = windowFrames.mDisplayFrame;
- layoutContainingFrame = windowFrames.mParentFrame;
- layoutXDiff = 0;
- layoutYDiff = 0;
- } else {
- windowFrames.mContainingFrame.set(getBounds());
- // IME is up and obscuring this window. Adjust the window position so it is visible.
- if (isImeTarget) {
- if (inFreeformWindowingMode()) {
- // Push the freeform window up to make room for the IME. However, don't push
- // it up past the bottom of the top bar.
- final InsetsState state = dc.getInsetsStateController().getRawInsetsState();
- final Rect visibleFrame = mTmpRect;
- visibleFrame.set(state.getDisplayFrame());
- visibleFrame.inset(state.calculateInsets(visibleFrame,
- systemBars() | ime() | displayCutout(), false /* ignoreVisibility */));
- final int bottomOverlap =
- windowFrames.mContainingFrame.bottom - visibleFrame.bottom;
- if (bottomOverlap > 0) {
- final int distanceToTop = Math.max(windowFrames.mContainingFrame.top
- - visibleFrame.top, 0);
- int offs = Math.min(bottomOverlap, distanceToTop);
- windowFrames.mContainingFrame.offset(0, -offs);
- mInsetFrame.offset(0, -offs);
- }
- } else if (!inPinnedWindowingMode() && windowFrames.mContainingFrame.bottom
- > windowFrames.mParentFrame.bottom) {
- // But in docked we want to behave like fullscreen and behave as if the task
- // were given smaller bounds for the purposes of layout. Skip adjustments for
- // the root pinned task, they are handled separately in the
- // PinnedTaskController.
- windowFrames.mContainingFrame.bottom = windowFrames.mParentFrame.bottom;
- }
- }
-
- if (windowsAreFloating) {
- // In floating modes (e.g. freeform, pinned) we have only to set the rectangle
- // if it wasn't set already. No need to intersect it with the (visible)
- // "content frame" since it is allowed to be outside the visible desktop.
- if (windowFrames.mContainingFrame.isEmpty()) {
- windowFrames.mContainingFrame.set(windowFrames.mDisplayFrame);
- }
- }
-
- layoutDisplayFrame = mTmpRect2;
- layoutDisplayFrame.set(windowFrames.mDisplayFrame);
- windowFrames.mDisplayFrame.set(windowFrames.mContainingFrame);
- layoutXDiff = mInsetFrame.left - windowFrames.mContainingFrame.left;
- layoutYDiff = mInsetFrame.top - windowFrames.mContainingFrame.top;
- layoutContainingFrame = mInsetFrame;
- mTmpRect.set(0, 0, displayInfo.logicalWidth, displayInfo.logicalHeight);
- subtractInsets(windowFrames.mDisplayFrame, layoutContainingFrame, layoutDisplayFrame,
- mTmpRect);
- if (!layoutInParentFrame()) {
- subtractInsets(windowFrames.mContainingFrame, layoutContainingFrame,
- windowFrames.mParentFrame, mTmpRect);
- subtractInsets(mInsetFrame, layoutContainingFrame, windowFrames.mParentFrame,
- mTmpRect);
- }
- layoutDisplayFrame.intersect(layoutContainingFrame);
- }
-
- final int pw = windowFrames.mContainingFrame.width();
- final int ph = windowFrames.mContainingFrame.height();
+ final WindowFrames windowFrames = mWindowFrames;
if (mRequestedWidth != mLastRequestedWidth || mRequestedHeight != mLastRequestedHeight) {
mLastRequestedWidth = mRequestedWidth;
@@ -1381,21 +1255,6 @@
windowFrames.setContentChanged(true);
}
- final int fw = windowFrames.mFrame.width();
- final int fh = windowFrames.mFrame.height();
-
- applyGravityAndUpdateFrame(windowFrames, layoutContainingFrame, layoutDisplayFrame,
- displayFrames);
-
- if (mAttrs.type == TYPE_DOCK_DIVIDER) {
- if (!windowFrames.mFrame.equals(windowFrames.mLastFrame)) {
- mMovedByResize = true;
- }
- }
-
- // Offset the actual frame by the amount layout frame is off.
- windowFrames.offsetFrames(-layoutXDiff, -layoutYDiff);
-
windowFrames.mCompatFrame.set(windowFrames.mFrame);
if (hasCompatScale()) {
// Also the scaled frame that we report to the app needs to be
@@ -1403,14 +1262,9 @@
windowFrames.mCompatFrame.scale(mInvGlobalScale);
}
- if (mIsWallpaper && (fw != windowFrames.mFrame.width()
- || fh != windowFrames.mFrame.height())) {
- dc.mWallpaperController.updateWallpaperOffset(this, false /* sync */);
- }
-
// Calculate relative frame
windowFrames.mRelFrame.set(windowFrames.mFrame);
- WindowContainer parent = getParent();
+ WindowContainer<?> parent = getParent();
int parentLeft = 0;
int parentTop = 0;
if (mIsChildWindow) {
@@ -1425,12 +1279,37 @@
windowFrames.mFrame.top - parentTop);
if (DEBUG_LAYOUT || DEBUG) {
+ final int pw = windowFrames.mParentFrame.width();
+ final int ph = windowFrames.mParentFrame.height();
Slog.v(TAG, "Resolving (mRequestedWidth="
- + mRequestedWidth + ", mRequestedheight="
- + mRequestedHeight + ") to" + " (pw=" + pw + ", ph=" + ph
- + "): frame=" + windowFrames.mFrame.toShortString()
- + " " + mAttrs.getTitle());
+ + mRequestedWidth + ", mRequestedheight="
+ + mRequestedHeight + ") to" + " (pw=" + pw + ", ph=" + ph
+ + "): frame=" + windowFrames.mFrame.toShortString()
+ + " " + mAttrs.getTitle());
}
+
+ if (mAttrs.type == TYPE_DOCK_DIVIDER) {
+ if (!windowFrames.mFrame.equals(windowFrames.mLastFrame)) {
+ mMovedByResize = true;
+ }
+ }
+
+ if (mIsWallpaper) {
+ final Rect lastFrame = windowFrames.mLastFrame;
+ final Rect frame = windowFrames.mFrame;
+ if (lastFrame.width() != frame.width() || lastFrame.height() != frame.height()) {
+ mDisplayContent.mWallpaperController.updateWallpaperOffset(this, false /* sync */);
+ }
+ }
+
+ // Update the source frame to provide insets to other windows during layout.
+ if (mControllableInsetProvider != null) {
+ mControllableInsetProvider.updateSourceFrame();
+ }
+ }
+
+ // TODO(b/161810301): Remove this after INSETS_LAYOUT_GENERALIZATION is removed.
+ void computeFrameAndUpdateSourceFrame(DisplayFrames displayFrames) {
}
@Override
@@ -1463,10 +1342,6 @@
return mWindowFrames.mParentFrame;
}
- Rect getContainingFrame() {
- return mWindowFrames.mContainingFrame;
- }
-
void getCompatFrameSize(Rect outFrame) {
outFrame.set(0, 0, mWindowFrames.mCompatFrame.width(), mWindowFrames.mCompatFrame.height());
}
@@ -1493,21 +1368,11 @@
return mDisableFlags;
}
- /** Gets the layer at which this window's surface will be Z-ordered. */
- int getSurfaceLayer() {
- return mLayer;
- }
-
@Override
public int getBaseType() {
return getTopParentWindow().mAttrs.type;
}
- /** Returns true if this window is participating in voice interaction. */
- boolean isVoiceInteraction() {
- return mActivityRecord != null && mActivityRecord.mVoiceInteraction;
- }
-
boolean setReportResizeHints() {
return mWindowFrames.setReportResizeHints();
}
@@ -1834,14 +1699,6 @@
&& (mActivityRecord.firstWindowDrawn || mActivityRecord.startingDisplayed);
}
- boolean isIdentityMatrix(float dsdx, float dtdx, float dsdy, float dtdy) {
- if (dsdx < .99999f || dsdx > 1.00001f) return false;
- if (dtdy < .99999f || dtdy > 1.00001f) return false;
- if (dtdx < -.000001f || dtdx > .000001f) return false;
- if (dsdy < -.000001f || dsdy > .000001f) return false;
- return true;
- }
-
void prelayout() {
if (hasCompatScale()) {
if (mOverrideScale != 1f) {
@@ -3441,15 +3298,6 @@
return mAnimatingExit || (mActivityRecord != null && mActivityRecord.isClosingOrEnteringPip());
}
- void addWinAnimatorToList(ArrayList<WindowStateAnimator> animators) {
- animators.add(mWinAnimator);
-
- for (int i = mChildren.size() - 1; i >= 0; --i) {
- final WindowState c = mChildren.get(i);
- c.addWinAnimatorToList(animators);
- }
- }
-
void sendAppVisibilityToClients() {
super.sendAppVisibilityToClients();
@@ -3573,9 +3421,6 @@
if (mAttrs.type >= FIRST_SYSTEM_WINDOW && mAttrs.type != TYPE_TOAST) {
mWmService.mAtmService.mActiveUids.onNonAppSurfaceVisibilityChanged(mOwnerUid, shown);
}
- if (mIsImWindow && mWmService.mAccessibilityController.hasCallbacks()) {
- mWmService.mAccessibilityController.onImeSurfaceShownChanged(this, shown);
- }
}
private void logExclusionRestrictions(int side) {
@@ -4023,11 +3868,6 @@
return getDisplayContent().mCurrentFocus == this;
}
- /** Is this window in a container that takes up the entire screen space? */
- private boolean inAppWindowThatMatchesParentBounds() {
- return mActivityRecord == null || (mActivityRecord.matchParentBounds() && !inMultiWindowMode());
- }
-
/**
* @return true if activity bounds are letterboxed or letterboxed for diplay cutout.
*
@@ -4402,107 +4242,10 @@
return mStringNameCache;
}
- private void applyGravityAndUpdateFrame(WindowFrames windowFrames, Rect containingFrame,
- Rect displayFrame, DisplayFrames displayFrames) {
- final int pw = containingFrame.width();
- final int ph = containingFrame.height();
- final Task task = getTask();
- final boolean inNonFullscreenContainer = !inAppWindowThatMatchesParentBounds();
- final WindowManager.LayoutParams attrs = getLayoutingAttrs(displayFrames.mRotation);
- final boolean noLimits = (attrs.flags & FLAG_LAYOUT_NO_LIMITS) != 0;
-
- // We need to fit it to the display if either
- // a) The window is in a fullscreen container, or we don't have a task (we assume fullscreen
- // for the taskless windows)
- // b) If it's a secondary app window, we also need to fit it to the display unless
- // FLAG_LAYOUT_NO_LIMITS is set. This is so we place Popups, dialogs, and similar windows on
- // screen, but SurfaceViews want to be always at a specific location so we don't fit it to
- // the display.
- final boolean fitToDisplay = (task == null || !inNonFullscreenContainer)
- || ((attrs.type != TYPE_BASE_APPLICATION) && !noLimits);
- float x, y;
- int w,h;
-
- final boolean hasCompatScale = hasCompatScale();
- if ((attrs.flags & FLAG_SCALED) != 0 || mAttrs != attrs) {
- // For the window with different layout attrs for different rotations, we need to avoid
- // using requested size. Otherwise, when finishing a simulated rotation, the information
- // coming from WindowManagerServices to the ViewRootImpl may not contain the correct
- // value for the new rotation, and there will be a quick flash of wrong layout when the
- // simulated activity faded out.
- if (attrs.width < 0) {
- w = pw;
- } else if (hasCompatScale) {
- w = (int) (attrs.width * mGlobalScale + .5f);
- } else {
- w = attrs.width;
- }
- if (attrs.height < 0) {
- h = ph;
- } else if (hasCompatScale) {
- h = (int) (attrs.height * mGlobalScale + .5f);
- } else {
- h = attrs.height;
- }
- } else {
- if (attrs.width == MATCH_PARENT) {
- w = pw;
- } else if (hasCompatScale) {
- w = (int) (mRequestedWidth * mGlobalScale + .5f);
- } else {
- w = mRequestedWidth;
- }
- if (attrs.height == MATCH_PARENT) {
- h = ph;
- } else if (hasCompatScale) {
- h = (int) (mRequestedHeight * mGlobalScale + .5f);
- } else {
- h = mRequestedHeight;
- }
- }
-
- if (hasCompatScale) {
- x = attrs.x * mGlobalScale;
- y = attrs.y * mGlobalScale;
- } else {
- x = attrs.x;
- y = attrs.y;
- }
-
- if (inNonFullscreenContainer && !layoutInParentFrame()) {
- // Make sure window fits in containing frame since it is in a non-fullscreen task as
- // required by {@link Gravity#apply} call.
- w = Math.min(w, pw);
- h = Math.min(h, ph);
- }
-
- // Set mFrame
- Gravity.apply(attrs.gravity, w, h, containingFrame,
- (int) (x + attrs.horizontalMargin * pw),
- (int) (y + attrs.verticalMargin * ph), windowFrames.mFrame);
- // Now make sure the window fits in the overall display frame.
- if (fitToDisplay) {
- Gravity.applyDisplay(attrs.gravity, displayFrame, windowFrames.mFrame);
- }
-
- // We need to make sure we update the CompatFrame as it is used for
- // cropping decisions, etc, on systems where we lack a decor layer.
- windowFrames.mCompatFrame.set(windowFrames.mFrame);
- if (hasCompatScale) {
- // See comparable block in computeFrameLw.
- windowFrames.mCompatFrame.scale(mInvGlobalScale);
- }
- }
-
boolean isChildWindow() {
return mIsChildWindow;
}
- boolean layoutInParentFrame() {
- return mIsChildWindow
- && (mAttrs.privateFlags & PRIVATE_FLAG_LAYOUT_CHILD_WINDOW_IN_PARENT_FRAME) != 0;
- }
-
/**
* Returns true if any window added by an application process that if of type
* {@link android.view.WindowManager.LayoutParams#TYPE_TOAST} or that requires that requires
@@ -4876,20 +4619,27 @@
private boolean applyImeWindowsIfNeeded(ToBooleanFunction<WindowState> callback,
boolean traverseTopToBottom) {
- // If this window is the current IME target, so we need to process the IME windows
- // directly above it. The exception is if we are in split screen
- // in which case we process the IME at the DisplayContent level to
- // ensure it is above the docked divider.
- // (i.e. Like {@link DisplayContent.ImeContainer#skipImeWindowsDuringTraversal}, the IME
- // window will be ignored to traverse when the IME target is still in split-screen mode).
- if (isImeLayeringTarget()
- && (!mDisplayContent.getDefaultTaskDisplayArea().isSplitScreenModeActivated()
- || getTask() == null)) {
- if (mDisplayContent.forAllImeWindows(callback, traverseTopToBottom)) {
- return true;
- }
+ // No need to apply to IME window if the window is not the current IME layering target.
+ if (!isImeLayeringTarget()) {
+ return false;
}
- return false;
+ // If we are in split screen which case we process the IME at the DisplayContent level to
+ // ensure it is above the docked divider.
+ // i.e. Like {@link DisplayContent.ImeContainer#skipImeWindowsDuringTraversal}, the IME
+ // window will be ignored to traverse when the IME target is still in split-screen mode.
+ if (mDisplayContent.getDefaultTaskDisplayArea().isSplitScreenModeActivated()
+ && getTask() != null) {
+ return false;
+ }
+ // Note that we don't process IME window if the IME input target is not on the screen.
+ // In case some unexpected IME visibility cases happen like starting the remote
+ // animation on the keyguard but seeing the IME window that originally on the app
+ // which behinds the keyguard.
+ final WindowState imeInputTarget = getImeInputTarget();
+ if (imeInputTarget != null && !(imeInputTarget.isDrawn() || imeInputTarget.isVisible())) {
+ return false;
+ }
+ return mDisplayContent.forAllImeWindows(callback, traverseTopToBottom);
}
private boolean applyInOrderWithImeWindows(ToBooleanFunction<WindowState> callback,
@@ -5877,7 +5627,7 @@
// animation target (which will be different than the task bounds)
outFrame.set(getTask().getParent().getBounds());
} else {
- outFrame.set(getContainingFrame());
+ outFrame.set(getParentFrame());
}
outSurfaceInsets.set(getAttrs().surfaceInsets);
final InsetsState state = getInsetsStateWithVisibilityOverride();
@@ -5907,11 +5657,8 @@
// to draw even if the children draw first or don't need to sync, so we start
// in WAITING state rather than READY.
mSyncState = SYNC_STATE_WAITING_FOR_DRAW;
+ mNextRelayoutUseSync = true;
requestRedrawForSync();
-
- mWmService.mH.removeMessages(WINDOW_STATE_BLAST_SYNC_TIMEOUT, this);
- mWmService.mH.sendNewMessageDelayed(WINDOW_STATE_BLAST_SYNC_TIMEOUT, this,
- BLAST_TIMEOUT_DURATION);
return true;
}
@@ -6092,6 +5839,7 @@
*/
void applyWithNextDraw(Consumer<SurfaceControl.Transaction> consumer) {
mPendingDrawHandlers.add(consumer);
+ mNextRelayoutUseSync = true;
requestRedrawForSync();
mWmService.mH.sendNewMessageDelayed(WINDOW_STATE_BLAST_SYNC_TIMEOUT, this,
diff --git a/services/core/java/com/android/server/wm/WindowStateAnimator.java b/services/core/java/com/android/server/wm/WindowStateAnimator.java
index 423b3a0..b147455 100644
--- a/services/core/java/com/android/server/wm/WindowStateAnimator.java
+++ b/services/core/java/com/android/server/wm/WindowStateAnimator.java
@@ -118,9 +118,6 @@
* window is first added or shown, cleared when the callback has been made. */
boolean mEnteringAnimation;
- /** The pixel format of the underlying SurfaceControl */
- int mSurfaceFormat;
-
/** This is set when there is no Surface */
static final int NO_SURFACE = 0;
/** This is set after the Surface has been created but before the window has been drawn. During
@@ -347,8 +344,6 @@
mSurfaceController.setColorSpaceAgnostic((attrs.privateFlags
& WindowManager.LayoutParams.PRIVATE_FLAG_COLOR_SPACE_AGNOSTIC) != 0);
- mSurfaceFormat = format;
-
w.setHasSurface(true);
// The surface instance is changed. Make sure the input info can be applied to the
// new surface, e.g. relaunch activity.
@@ -514,8 +509,6 @@
return;
}
- boolean displayed = false;
-
computeShownFrameLocked();
setSurfaceBoundariesLocked(t);
@@ -535,7 +528,6 @@
}
} else if (mLastAlpha != mShownAlpha
|| mLastHidden) {
- displayed = true;
mLastAlpha = mShownAlpha;
ProtoLog.i(WM_SHOW_TRANSACTIONS,
"SURFACE controller=%s alpha=%f HScale=%f, VScale=%f: %s",
@@ -566,14 +558,10 @@
}
}
}
- if (hasSurface()) {
- w.mToken.hasVisible = true;
- }
} else {
if (DEBUG_ANIM && mWin.isAnimating(TRANSITION | PARENTS)) {
Slog.v(TAG, "prepareSurface: No changes in animation for " + this);
}
- displayed = true;
}
if (w.getOrientationChanging()) {
@@ -589,31 +577,6 @@
ProtoLog.v(WM_DEBUG_ORIENTATION, "Orientation change complete in %s", w);
}
}
-
- if (displayed) {
- w.mToken.hasVisible = true;
- }
- }
-
- /**
- * Try to change the pixel format without recreating the surface. This
- * will be common in the case of changing from PixelFormat.OPAQUE to
- * PixelFormat.TRANSLUCENT in the hardware-accelerated case as both
- * requested formats resolve to the same underlying SurfaceControl format
- * @return True if format was succesfully changed, false otherwise
- */
- boolean tryChangeFormatInPlaceLocked() {
- if (mSurfaceController == null) {
- return false;
- }
- final LayoutParams attrs = mWin.getAttrs();
- final boolean isHwAccelerated = (attrs.flags & FLAG_HARDWARE_ACCELERATED) != 0;
- final int format = isHwAccelerated ? PixelFormat.TRANSLUCENT : attrs.format;
- if (format == mSurfaceFormat) {
- setOpaqueLocked(!PixelFormat.formatHasAlpha(attrs.format));
- return true;
- }
- return false;
}
void setOpaqueLocked(boolean isOpaque) {
diff --git a/services/core/java/com/android/server/wm/WindowToken.java b/services/core/java/com/android/server/wm/WindowToken.java
index ad351f0..34b63ac 100644
--- a/services/core/java/com/android/server/wm/WindowToken.java
+++ b/services/core/java/com/android/server/wm/WindowToken.java
@@ -26,8 +26,6 @@
import static com.android.internal.protolog.ProtoLogGroup.WM_DEBUG_APP_TRANSITIONS;
import static com.android.internal.protolog.ProtoLogGroup.WM_DEBUG_FOCUS;
import static com.android.internal.protolog.ProtoLogGroup.WM_DEBUG_WINDOW_MOVEMENT;
-import static com.android.server.wm.SurfaceAnimator.ANIMATION_TYPE_WINDOW_ANIMATION;
-import static com.android.server.wm.WindowContainer.AnimationFlags.CHILDREN;
import static com.android.server.wm.WindowContainer.AnimationFlags.PARENTS;
import static com.android.server.wm.WindowContainer.AnimationFlags.TRANSITION;
import static com.android.server.wm.WindowContainerChildProto.WINDOW_TOKEN;
@@ -102,9 +100,6 @@
// Is key dispatching paused for this token?
boolean paused = false;
- // Temporary for finding which tokens no longer have visible windows.
- boolean hasVisible;
-
// Set to true when this token is in a pending transaction where it
// will be shown.
boolean waitingToShow;
@@ -240,6 +235,7 @@
}
}
+ /** Starts exit animation or hides windows if needed. It is only used for non-activity token. */
void setExiting(boolean animateExit) {
if (isEmpty()) {
super.removeImmediately();
@@ -255,27 +251,15 @@
final int count = mChildren.size();
boolean changed = false;
- final boolean delayed = isAnimating(TRANSITION | PARENTS)
- || (isAnimating(CHILDREN, ANIMATION_TYPE_WINDOW_ANIMATION) && animateExit);
-
for (int i = 0; i < count; i++) {
final WindowState win = mChildren.get(i);
changed |= win.onSetAppExiting(animateExit);
}
- final ActivityRecord app = asActivityRecord();
- if (app != null) {
- app.setVisible(false);
- }
-
if (changed) {
mWmService.mWindowPlacerLocked.performSurfacePlacement();
mWmService.updateFocusedWindowLocked(UPDATE_FOCUS_NORMAL, false /*updateInputWindows*/);
}
-
- if (delayed) {
- mDisplayContent.mExitingTokens.add(this);
- }
}
/**
@@ -381,11 +365,6 @@
}
@Override
- public void onConfigurationChanged(Configuration newParentConfig) {
- super.onConfigurationChanged(newParentConfig);
- }
-
- @Override
void assignLayer(SurfaceControl.Transaction t, int layer) {
if (windowType == TYPE_DOCK_DIVIDER) {
// See {@link DisplayContent#mSplitScreenDividerAnchor}
@@ -723,7 +702,6 @@
super.dump(pw, prefix, dumpAll);
pw.print(prefix); pw.print("windows="); pw.println(mChildren);
pw.print(prefix); pw.print("windowType="); pw.print(windowType);
- pw.print(" hasVisible="); pw.print(hasVisible);
if (waitingToShow) {
pw.print(" waitingToShow=true");
}
diff --git a/services/core/jni/Android.bp b/services/core/jni/Android.bp
index 4e4a5c3..eb2c8a6 100644
--- a/services/core/jni/Android.bp
+++ b/services/core/jni/Android.bp
@@ -114,6 +114,8 @@
"libutils",
"libui",
"libvibratorservice",
+ "PlatformProperties",
+ "InputFlingerProperties",
"libinput",
"libinputflinger",
"libinputflinger_base",
diff --git a/services/core/jni/com_android_server_input_InputManagerService.cpp b/services/core/jni/com_android_server_input_InputManagerService.cpp
index 94b1ad1..790acbf 100644
--- a/services/core/jni/com_android_server_input_InputManagerService.cpp
+++ b/services/core/jni/com_android_server_input_InputManagerService.cpp
@@ -26,30 +26,14 @@
// Log debug messages about InputDispatcherPolicy
#define DEBUG_INPUT_DISPATCHER_POLICY 0
+#include <InputFlingerProperties.sysprop.h>
#include <android-base/parseint.h>
#include <android-base/stringprintf.h>
#include <android/os/IInputConstants.h>
+#include <android/sysprop/InputProperties.sysprop.h>
+#include <android_os_MessageQueue.h>
#include <android_runtime/AndroidRuntime.h>
#include <android_runtime/Log.h>
-#include <limits.h>
-#include <atomic>
-#include <cinttypes>
-
-#include <utils/Log.h>
-#include <utils/Looper.h>
-#include <utils/threads.h>
-#include <utils/Trace.h>
-
-#include <binder/IServiceManager.h>
-
-#include <input/PointerController.h>
-#include <input/SpriteController.h>
-#include <ui/Region.h>
-
-#include <batteryservice/include/batteryservice/BatteryServiceConstants.h>
-#include <inputflinger/InputManager.h>
-
-#include <android_os_MessageQueue.h>
#include <android_view_InputChannel.h>
#include <android_view_InputDevice.h>
#include <android_view_KeyEvent.h>
@@ -57,11 +41,25 @@
#include <android_view_PointerIcon.h>
#include <android_view_VerifiedKeyEvent.h>
#include <android_view_VerifiedMotionEvent.h>
-
+#include <batteryservice/include/batteryservice/BatteryServiceConstants.h>
+#include <binder/IServiceManager.h>
+#include <input/PointerController.h>
+#include <input/SpriteController.h>
+#include <inputflinger/InputManager.h>
+#include <limits.h>
#include <nativehelper/ScopedLocalFrame.h>
#include <nativehelper/ScopedLocalRef.h>
#include <nativehelper/ScopedPrimitiveArray.h>
#include <nativehelper/ScopedUtfChars.h>
+#include <ui/Region.h>
+#include <utils/Log.h>
+#include <utils/Looper.h>
+#include <utils/Trace.h>
+#include <utils/threads.h>
+
+#include <atomic>
+#include <cinttypes>
+#include <vector>
#include "android_hardware_display_DisplayViewport.h"
#include "android_hardware_input_InputApplicationHandle.h"
@@ -69,8 +67,6 @@
#include "android_util_Binder.h"
#include "com_android_server_power_PowerManagerService.h"
-#include <vector>
-
#define INDENT " "
using android::base::ParseUint;
@@ -2089,11 +2085,24 @@
InputReaderConfiguration::CHANGE_DEVICE_ALIAS);
}
-static jstring nativeDump(JNIEnv* env, jclass /* clazz */, jlong ptr) {
- NativeInputManager* im = reinterpret_cast<NativeInputManager*>(ptr);
+static std::string dumpInputProperties() {
+ std::string out = "Input properties:\n";
+ const bool perWindowInputRotation =
+ sysprop::InputFlingerProperties::per_window_input_rotation().value_or(false);
+ out += StringPrintf(" per_window_input_rotation = %s\n", toString(perWindowInputRotation));
+ const std::string strategy =
+ sysprop::InputProperties::velocitytracker_strategy().value_or("default");
+ out += " persist.input.velocitytracker.strategy = " + strategy + "\n";
+ out += "\n";
+ return out;
+}
- std::string dump;
+static jstring nativeDump(JNIEnv* env, jclass /* clazz */, jlong ptr) {
+ std::string dump = dumpInputProperties();
+
+ NativeInputManager* im = reinterpret_cast<NativeInputManager*>(ptr);
im->dump(dump);
+
return env->NewStringUTF(dump.c_str());
}
diff --git a/services/java/com/android/server/SystemServer.java b/services/java/com/android/server/SystemServer.java
index f351a8c..8c414b9 100644
--- a/services/java/com/android/server/SystemServer.java
+++ b/services/java/com/android/server/SystemServer.java
@@ -192,6 +192,7 @@
import com.android.server.trust.TrustManagerService;
import com.android.server.tv.TvInputManagerService;
import com.android.server.tv.TvRemoteService;
+import com.android.server.tv.interactive.TvIAppManagerService;
import com.android.server.tv.tunerresourcemanager.TunerResourceManagerService;
import com.android.server.twilight.TwilightService;
import com.android.server.uri.UriGrantsManagerService;
@@ -251,6 +252,8 @@
"com.android.server.print.PrintManagerService";
private static final String COMPANION_DEVICE_MANAGER_SERVICE_CLASS =
"com.android.server.companion.CompanionDeviceManagerService";
+ private static final String VIRTUAL_DEVICE_MANAGER_SERVICE_CLASS =
+ "com.android.server.companion.virtual.VirtualDeviceManagerService";
private static final String STATS_COMPANION_APEX_PATH =
"/apex/com.android.os.statsd/javalib/service-statsd.jar";
private static final String SCHEDULING_APEX_PATH =
@@ -2322,6 +2325,11 @@
t.traceBegin("StartCompanionDeviceManager");
mSystemServiceManager.startService(COMPANION_DEVICE_MANAGER_SERVICE_CLASS);
t.traceEnd();
+
+ // VirtualDeviceManager depends on CDM to control the associations.
+ t.traceBegin("StartVirtualDeviceManager");
+ mSystemServiceManager.startService(VIRTUAL_DEVICE_MANAGER_SERVICE_CLASS);
+ t.traceEnd();
}
t.traceBegin("StartRestrictionManager");
@@ -2340,6 +2348,13 @@
if (mPackageManager.hasSystemFeature(PackageManager.FEATURE_LIVE_TV)
|| mPackageManager.hasSystemFeature(PackageManager.FEATURE_LEANBACK)) {
+ t.traceBegin("StartTvIAppManager");
+ mSystemServiceManager.startService(TvIAppManagerService.class);
+ t.traceEnd();
+ }
+
+ if (mPackageManager.hasSystemFeature(PackageManager.FEATURE_LIVE_TV)
+ || mPackageManager.hasSystemFeature(PackageManager.FEATURE_LEANBACK)) {
t.traceBegin("StartTvInputManager");
mSystemServiceManager.startService(TvInputManagerService.class);
t.traceEnd();
diff --git a/services/tests/PackageManager/TEST_MAPPING b/services/tests/PackageManager/TEST_MAPPING
new file mode 100644
index 0000000..72d4c82
--- /dev/null
+++ b/services/tests/PackageManager/TEST_MAPPING
@@ -0,0 +1,8 @@
+{
+ "presubmit": [
+ {
+ "name": "PackageInstallerTests"
+ }
+ ]
+}
+
diff --git a/services/tests/PackageManagerComponentOverrideTests/TEST_MAPPING b/services/tests/PackageManagerComponentOverrideTests/TEST_MAPPING
new file mode 100644
index 0000000..528c949
--- /dev/null
+++ b/services/tests/PackageManagerComponentOverrideTests/TEST_MAPPING
@@ -0,0 +1,8 @@
+{
+ "presubmit": [
+ {
+ "name": "PackageManagerComponentOverrideTests"
+ }
+ ]
+}
+
diff --git a/services/tests/PackageManagerServiceTests/OWNERS b/services/tests/PackageManagerServiceTests/OWNERS
index 182dfe8..86ae581 100644
--- a/services/tests/PackageManagerServiceTests/OWNERS
+++ b/services/tests/PackageManagerServiceTests/OWNERS
@@ -1,3 +1 @@
-chiuwinson@google.com
-patb@google.com
-toddke@google.com
+include /PACKAGE_MANAGER_OWNERS
diff --git a/services/tests/PackageManagerServiceTests/TEST_MAPPING b/services/tests/PackageManagerServiceTests/TEST_MAPPING
new file mode 100644
index 0000000..af0008c
--- /dev/null
+++ b/services/tests/PackageManagerServiceTests/TEST_MAPPING
@@ -0,0 +1,18 @@
+{
+ "presubmit": [
+ {
+ "name": "AppEnumerationInternalTests"
+ }
+ ],
+ "postsubmit": [
+ {
+ "name": "PackageManagerServiceHostTests"
+ }
+ ],
+ "imports": [
+ {
+ "path": "frameworks/base/services/tests/PackageManagerServiceTests/unit"
+ }
+ ]
+}
+
diff --git a/services/tests/mockingservicestests/src/com/android/server/pm/PackageManagerServiceHibernationTests.kt b/services/tests/mockingservicestests/src/com/android/server/pm/PackageManagerServiceHibernationTests.kt
index 3ee2348..15acdac 100644
--- a/services/tests/mockingservicestests/src/com/android/server/pm/PackageManagerServiceHibernationTests.kt
+++ b/services/tests/mockingservicestests/src/com/android/server/pm/PackageManagerServiceHibernationTests.kt
@@ -16,8 +16,10 @@
package com.android.server.pm
+import android.content.Context
import android.os.Build
import android.os.Handler
+import android.os.PowerManager
import android.provider.DeviceConfig
import android.provider.DeviceConfig.NAMESPACE_APP_HIBERNATION
import android.testing.AndroidTestingRunner
@@ -55,6 +57,8 @@
@Mock
lateinit var appHibernationManager: AppHibernationManagerInternal
+ @Mock
+ lateinit var powerManager: PowerManager
@Before
@Throws(Exception::class)
@@ -68,6 +72,24 @@
.thenReturn(appHibernationManager)
whenever(rule.mocks().injector.handler)
.thenReturn(Handler(TestableLooper.get(this).looper))
+ val injector = object : PackageDexOptimizer.Injector {
+ override fun getAppHibernationManagerInternal(): AppHibernationManagerInternal {
+ return appHibernationManager
+ }
+
+ override fun getPowerManager(context: Context?): PowerManager {
+ return powerManager
+ }
+ }
+ val packageDexOptimizer = PackageDexOptimizer(
+ injector,
+ rule.mocks().installer,
+ rule.mocks().installLock,
+ rule.mocks().context,
+ "*dexopt*")
+ whenever(rule.mocks().injector.packageDexOptimizer)
+ .thenReturn(packageDexOptimizer)
+ whenever(appHibernationManager.isOatArtifactDeletionEnabled).thenReturn(true)
}
@Test
diff --git a/services/tests/mockingservicestests/src/com/android/server/pm/StagingManagerTest.java b/services/tests/mockingservicestests/src/com/android/server/pm/StagingManagerTest.java
index 6a4d69f..b72f05f 100644
--- a/services/tests/mockingservicestests/src/com/android/server/pm/StagingManagerTest.java
+++ b/services/tests/mockingservicestests/src/com/android/server/pm/StagingManagerTest.java
@@ -43,7 +43,6 @@
import android.content.pm.PackageInstaller.SessionInfo;
import android.content.pm.PackageInstaller.SessionInfo.StagedSessionErrorCode;
import android.content.pm.StagedApexInfo;
-import android.os.Message;
import android.os.SystemProperties;
import android.os.storage.IStorageManager;
import android.platform.test.annotations.Presubmit;
@@ -113,7 +112,7 @@
when(SystemProperties.get(eq("ro.apex.updatable"), anyString())).thenReturn("true");
mTmpDir = mTemporaryFolder.newFolder("StagingManagerTest");
- mStagingManager = new StagingManager(mContext, null, mApexManager);
+ mStagingManager = new StagingManager(mContext, mApexManager);
}
@After
@@ -123,32 +122,6 @@
}
}
- /**
- * Tests that sessions committed later shouldn't cause earlier ones to fail the overlapping
- * check.
- */
- @Test
- public void checkNonOverlappingWithStagedSessions_laterSessionShouldNotFailEarlierOnes()
- throws Exception {
- // Create 2 sessions with overlapping packages
- StagingManager.StagedSession session1 = createSession(111, "com.foo", 1);
- StagingManager.StagedSession session2 = createSession(222, "com.foo", 2);
-
- mStagingManager.createSession(session1);
- mStagingManager.createSession(session2);
- // Session1 should not fail in spite of the overlapping packages
- mStagingManager.checkNonOverlappingWithStagedSessions(session1);
- // setSessionFailed() should've been called when doing overlapping checks on session1
- verify(session2, times(1)).setSessionFailed(anyInt(), anyString());
-
- // Yet another session with overlapping packages
- StagingManager.StagedSession session3 = createSession(333, "com.foo", 3);
- mStagingManager.createSession(session3);
- assertThrows(PackageManagerException.class,
- () -> mStagingManager.checkNonOverlappingWithStagedSessions(session3));
- verify(session3, never()).setSessionFailed(anyInt(), anyString());
- }
-
@Test
public void restoreSessions_nonParentSession_throwsIAE() throws Exception {
FakeStagedSession session = new FakeStagedSession(239);
@@ -726,10 +699,9 @@
{
FakeStagedSession session = new FakeStagedSession(239);
session.setIsApex(true);
- mStagingManager.createSession(session);
-
+ session.setSessionReady();
mockApexManagerGetStagedApexInfoWithSessionId();
- triggerEndOfPreRebootVerification(session);
+ mStagingManager.commitSession(session);
assertThat(session.isSessionReady()).isTrue();
ArgumentCaptor<ApexStagedEvent> argumentCaptor = ArgumentCaptor.forClass(
@@ -744,9 +716,8 @@
Mockito.clearInvocations(observer);
FakeStagedSession session = new FakeStagedSession(240);
session.setIsApex(true);
- mStagingManager.createSession(session);
-
- triggerEndOfPreRebootVerification(session);
+ session.setSessionReady();
+ mStagingManager.commitSession(session);
assertThat(session.isSessionReady()).isTrue();
ArgumentCaptor<ApexStagedEvent> argumentCaptor = ArgumentCaptor.forClass(
@@ -762,9 +733,8 @@
Mockito.clearInvocations(observer);
FakeStagedSession session = new FakeStagedSession(241);
session.setIsApex(true);
- mStagingManager.createSession(session);
-
- triggerEndOfPreRebootVerification(session);
+ session.setSessionReady();
+ mStagingManager.commitSession(session);
assertThat(session.isSessionReady()).isTrue();
verify(observer, never()).onApexStaged(any());
@@ -800,21 +770,13 @@
// Trigger end of pre-reboot verification
FakeStagedSession session = new FakeStagedSession(239);
- mStagingManager.createSession(session);
+ session.setSessionReady();
+ mStagingManager.commitSession(session);
- triggerEndOfPreRebootVerification(session);
assertThat(session.isSessionReady()).isTrue();
verify(observer, never()).onApexStaged(any());
}
- private void triggerEndOfPreRebootVerification(StagingManager.StagedSession session) {
- StagingManager.PreRebootVerificationHandler handler =
- mStagingManager.mPreRebootVerificationHandler;
- Message msg = handler.obtainMessage(
- handler.MSG_PRE_REBOOT_VERIFICATION_END, session.sessionId(), -1, session);
- handler.handleMessage(msg);
- }
-
private StagingManager.StagedSession createSession(int sessionId, String packageName,
long committedMillis) {
PackageInstaller.SessionParams params = new PackageInstaller.SessionParams(
@@ -1071,9 +1033,6 @@
}
@Override
- public void notifyEndPreRebootVerification() {}
-
- @Override
public void verifySession() {
mVerificationStarted = true;
}
diff --git a/services/tests/servicestests/src/com/android/server/BatteryServiceTest.java b/services/tests/servicestests/src/com/android/server/BatteryServiceTest.java
index cb12ba7..a2ecbc3 100644
--- a/services/tests/servicestests/src/com/android/server/BatteryServiceTest.java
+++ b/services/tests/servicestests/src/com/android/server/BatteryServiceTest.java
@@ -47,7 +47,6 @@
@Mock BatteryService.HealthServiceWrapper.IHealthSupplier mHealthServiceSupplier;
BatteryService.HealthServiceWrapper mWrapper;
- private static final String HEALTHD = BatteryService.HealthServiceWrapper.INSTANCE_HEALTHD;
private static final String VENDOR = BatteryService.HealthServiceWrapper.INSTANCE_VENDOR;
@Override
@@ -117,7 +116,7 @@
@SmallTest
public void testWrapPreferVendor() throws Exception {
- initForInstances(VENDOR, HEALTHD);
+ initForInstances(VENDOR);
mWrapper.init(mCallback, mManagerSupplier, mHealthServiceSupplier);
waitHandlerThreadFinish();
verify(mCallback, times(1)).onRegistration(same(null), same(mMockedHal), eq(VENDOR));
@@ -126,16 +125,6 @@
}
@SmallTest
- public void testUseHealthd() throws Exception {
- initForInstances(HEALTHD);
- mWrapper.init(mCallback, mManagerSupplier, mHealthServiceSupplier);
- waitHandlerThreadFinish();
- verify(mCallback, times(1)).onRegistration(same(null), same(mMockedHal), eq(HEALTHD));
- verify(mCallback, never()).onRegistration(same(mMockedHal), same(mMockedHal), anyString());
- verify(mCallback, times(1)).onRegistration(same(mMockedHal), same(mMockedHal2), eq(HEALTHD));
- }
-
- @SmallTest
public void testNoService() throws Exception {
initForInstances("unrelated");
try {
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 fb5c557..96af617 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
@@ -100,7 +100,11 @@
MagnificationAnimationCallback.class);
private final MagnificationInfoChangedCallback mRequestObserver = mock(
MagnificationInfoChangedCallback.class);
- final MessageCapturingHandler mMessageCapturingHandler = new MessageCapturingHandler(null);
+ private final MessageCapturingHandler mMessageCapturingHandler = new MessageCapturingHandler(
+ null);
+ private final MagnificationScaleProvider mScaleProvider = mock(
+ MagnificationScaleProvider.class);
+
ValueAnimator mMockValueAnimator;
ValueAnimator.AnimatorUpdateListener mTargetAnimationListener;
@@ -123,7 +127,7 @@
initMockWindowManager();
mFullScreenMagnificationController = new FullScreenMagnificationController(
- mMockControllerCtx, new Object(), mRequestObserver);
+ mMockControllerCtx, new Object(), mRequestObserver, mScaleProvider);
}
@After
@@ -412,12 +416,12 @@
MagnificationSpec startSpec = getCurrentMagnificationSpec(displayId);
PointF newCenter = INITIAL_BOUNDS_LOWER_RIGHT_2X_CENTER;
PointF offsets = computeOffsets(INITIAL_MAGNIFICATION_BOUNDS, newCenter,
- FullScreenMagnificationController.MAX_SCALE);
+ MagnificationScaleProvider.MAX_SCALE);
MagnificationSpec endSpec = getMagnificationSpec(
- FullScreenMagnificationController.MAX_SCALE, offsets);
+ MagnificationScaleProvider.MAX_SCALE, offsets);
assertTrue(mFullScreenMagnificationController.setScaleAndCenter(displayId,
- FullScreenMagnificationController.MAX_SCALE + 1.0f,
+ MagnificationScaleProvider.MAX_SCALE + 1.0f,
newCenter.x, newCenter.y, false, SERVICE_ID_1));
mMessageCapturingHandler.sendAllMessages();
@@ -632,31 +636,6 @@
}
@Test
- public void testSetUserId_resetsOnlyIfIdChanges() {
- for (int i = 0; i < DISPLAY_COUNT; i++) {
- testSetUserId_resetsOnlyIfIdChanges(i);
- resetMockWindowManager();
- }
- }
-
- private void testSetUserId_resetsOnlyIfIdChanges(int displayId) {
- final int userId1 = 1;
- final int userId2 = 2;
-
- register(displayId);
- mFullScreenMagnificationController.setUserId(userId1);
- PointF startCenter = INITIAL_MAGNIFICATION_BOUNDS_CENTER;
- float scale = 2.0f;
- mFullScreenMagnificationController.setScale(displayId, scale, startCenter.x, startCenter.y,
- false, SERVICE_ID_1);
-
- mFullScreenMagnificationController.setUserId(userId1);
- assertTrue(mFullScreenMagnificationController.isMagnifying(displayId));
- mFullScreenMagnificationController.setUserId(userId2);
- assertFalse(mFullScreenMagnificationController.isMagnifying(displayId));
- }
-
- @Test
public void testResetIfNeeded_doesWhatItSays() {
for (int i = 0; i < DISPLAY_COUNT; i++) {
testResetIfNeeded_doesWhatItSays(i);
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 6c32f7e..2060223 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
@@ -22,6 +22,8 @@
import static android.view.MotionEvent.ACTION_POINTER_UP;
import static android.view.MotionEvent.ACTION_UP;
+import static androidx.test.platform.app.InstrumentationRegistry.getInstrumentation;
+
import static com.android.server.testutils.TestUtils.strictMock;
import static org.junit.Assert.assertFalse;
@@ -38,16 +40,15 @@
import android.animation.ValueAnimator;
import android.annotation.NonNull;
-import android.content.Context;
import android.graphics.PointF;
import android.os.Handler;
import android.os.Message;
+import android.testing.TestableContext;
import android.util.DebugUtils;
import android.view.InputDevice;
import android.view.MotionEvent;
import android.view.ViewConfiguration;
-import androidx.test.InstrumentationRegistry;
import androidx.test.runner.AndroidJUnit4;
import com.android.server.accessibility.AccessibilityManagerService;
@@ -60,6 +61,7 @@
import org.junit.After;
import org.junit.Before;
+import org.junit.Rule;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Mock;
@@ -121,7 +123,6 @@
private static final int DISPLAY_0 = 0;
- private Context mContext;
FullScreenMagnificationController mFullScreenMagnificationController;
@Mock
MagnificationGestureHandler.Callback mMockCallback;
@@ -134,6 +135,9 @@
@Mock
AccessibilityTraceManager mMockTraceManager;
+ @Rule
+ public final TestableContext mContext = new TestableContext(getInstrumentation().getContext());
+
private OffsettableClock mClock;
private FullScreenMagnificationGestureHandler mMgh;
private TestHandler mHandler;
@@ -143,7 +147,6 @@
@Before
public void setUp() {
MockitoAnnotations.initMocks(this);
- mContext = InstrumentationRegistry.getContext();
final FullScreenMagnificationController.ControllerContext mockController =
mock(FullScreenMagnificationController.ControllerContext.class);
final WindowManagerInternal mockWindowManager = mock(WindowManagerInternal.class);
@@ -157,14 +160,16 @@
when(mockController.getAnimationDuration()).thenReturn(1000L);
when(mockWindowManager.setMagnificationCallbacks(eq(DISPLAY_0), any())).thenReturn(true);
mFullScreenMagnificationController = new FullScreenMagnificationController(mockController,
- new Object(), mMagnificationInfoChangedCallback) {
+ new Object(), mMagnificationInfoChangedCallback,
+ new MagnificationScaleProvider(mContext)) {
@Override
public boolean magnificationRegionContains(int displayId, float x, float y) {
return true;
}
@Override
- void setForceShowMagnifiableBounds(int displayId, boolean show) {}
+ void setForceShowMagnifiableBounds(int displayId, boolean show) {
+ }
};
mFullScreenMagnificationController.register(DISPLAY_0);
mClock = new OffsettableClock.Stopped();
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 2cb3d27..69061c1 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
@@ -46,6 +46,7 @@
import android.os.UserHandle;
import android.provider.Settings;
import android.test.mock.MockContentResolver;
+import android.testing.DexmakerShareClassLoaderRule;
import android.view.Display;
import android.view.accessibility.IRemoteMagnificationAnimationCallback;
import android.view.accessibility.MagnificationAnimationCallback;
@@ -58,6 +59,7 @@
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;
@@ -79,7 +81,8 @@
private static final float MAGNIFIED_CENTER_X = 100;
private static final float MAGNIFIED_CENTER_Y = 200;
private static final float DEFAULT_SCALE = 3f;
- private static final int CURRENT_USER_ID = UserHandle.USER_CURRENT;
+ private static final int CURRENT_USER_ID = UserHandle.USER_SYSTEM;
+ private static final int SECOND_USER_ID = CURRENT_USER_ID + 1;
private static final int MODE_WINDOW = Settings.Secure.ACCESSIBILITY_MAGNIFICATION_MODE_WINDOW;
private static final int MODE_FULLSCREEN =
Settings.Secure.ACCESSIBILITY_MAGNIFICATION_MODE_FULLSCREEN;
@@ -94,6 +97,7 @@
private Context mContext;
@Mock
private FullScreenMagnificationController mScreenMagnificationController;
+ private MagnificationScaleProvider mScaleProvider;
@Captor
private ArgumentCaptor<MagnificationAnimationCallback> mCallbackArgumentCaptor;
@@ -103,6 +107,11 @@
private MagnificationController mMagnificationController;
private FullScreenMagnificationControllerStubber mScreenMagnificationControllerStubber;
+ // To mock package-private class
+ @Rule
+ public final DexmakerShareClassLoaderRule mDexmakerShareClassLoaderRule =
+ new DexmakerShareClassLoaderRule();
+
@Before
public void setUp() throws Exception {
MockitoAnnotations.initMocks(this);
@@ -113,15 +122,17 @@
Settings.Secure.putFloatForUser(mMockResolver,
Settings.Secure.ACCESSIBILITY_DISPLAY_MAGNIFICATION_SCALE, DEFAULT_SCALE,
CURRENT_USER_ID);
+ mScaleProvider = spy(new MagnificationScaleProvider(mContext));
mWindowMagnificationManager = Mockito.spy(
new WindowMagnificationManager(mContext, CURRENT_USER_ID,
- mock(WindowMagnificationManager.Callback.class), mTraceManager));
+ mock(WindowMagnificationManager.Callback.class), mTraceManager,
+ mScaleProvider));
mMockConnection = new MockWindowMagnificationConnection(true);
mWindowMagnificationManager.setConnection(mMockConnection.getConnection());
mScreenMagnificationControllerStubber = new FullScreenMagnificationControllerStubber(
mScreenMagnificationController);
mMagnificationController = spy(new MagnificationController(mService, new Object(), mContext,
- mScreenMagnificationController, mWindowMagnificationManager));
+ mScreenMagnificationController, mWindowMagnificationManager, mScaleProvider));
mMagnificationController.setMagnificationCapabilities(
Settings.Secure.ACCESSIBILITY_MAGNIFICATION_MODE_ALL);
@@ -283,14 +294,16 @@
verify(mScreenMagnificationController).onDisplayRemoved(TEST_DISPLAY);
verify(mWindowMagnificationManager).onDisplayRemoved(TEST_DISPLAY);
+ verify(mScaleProvider).onDisplayRemoved(TEST_DISPLAY);
}
@Test
- public void updateUserIdIfNeeded_AllModulesAvailable_setUserId() {
- mMagnificationController.updateUserIdIfNeeded(CURRENT_USER_ID);
+ public void updateUserIdIfNeeded_AllModulesAvailable_disableMagnificationAndChangeUserId() {
+ mMagnificationController.updateUserIdIfNeeded(SECOND_USER_ID);
- verify(mScreenMagnificationController).setUserId(CURRENT_USER_ID);
- verify(mWindowMagnificationManager).setUserId(CURRENT_USER_ID);
+ verify(mScreenMagnificationController).resetAllIfNeeded(false);
+ verify(mWindowMagnificationManager).disableAllWindowMagnifiers();
+ verify(mScaleProvider).onUserChanged(SECOND_USER_ID);
}
@Test
@@ -575,6 +588,13 @@
verify(mMagnificationController, never()).logMagnificationModeWithIme(anyInt());
}
+ @Test
+ public void onUserRemoved_notifyScaleProvider() {
+ mMagnificationController.onUserRemoved(SECOND_USER_ID);
+
+ verify(mScaleProvider).onUserRemoved(SECOND_USER_ID);
+ }
+
private void setMagnificationEnabled(int mode) throws RemoteException {
setMagnificationEnabled(mode, MAGNIFIED_CENTER_X, MAGNIFIED_CENTER_Y);
}
@@ -627,7 +647,8 @@
TEST_DISPLAY);
doAnswer(invocation -> mIsMagnifying).when(
mScreenMagnificationController).isForceShowMagnifiableBounds(TEST_DISPLAY);
- doAnswer(invocation -> mScale).when(mScreenMagnificationController).getPersistedScale();
+ doAnswer(invocation -> mScale).when(mScreenMagnificationController).getPersistedScale(
+ TEST_DISPLAY);
doAnswer(invocation -> mScale).when(mScreenMagnificationController).getScale(
TEST_DISPLAY);
doAnswer(invocation -> mCenterX).when(mScreenMagnificationController).getCenterX(
diff --git a/services/tests/servicestests/src/com/android/server/accessibility/magnification/MagnificationScaleProviderTest.java b/services/tests/servicestests/src/com/android/server/accessibility/magnification/MagnificationScaleProviderTest.java
new file mode 100644
index 0000000..9b392b2
--- /dev/null
+++ b/services/tests/servicestests/src/com/android/server/accessibility/magnification/MagnificationScaleProviderTest.java
@@ -0,0 +1,100 @@
+/*
+ * Copyright (C) 2021 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.accessibility.magnification;
+
+import static androidx.test.platform.app.InstrumentationRegistry.getInstrumentation;
+
+import static org.junit.Assert.assertEquals;
+
+import android.os.UserHandle;
+import android.testing.TestableContext;
+import android.view.Display;
+
+import com.android.compatibility.common.util.TestUtils;
+
+import org.junit.Before;
+import org.junit.Rule;
+import org.junit.Test;
+/**
+ * Tests for {@link MagnificationScaleProvider}.
+ */
+public class MagnificationScaleProviderTest {
+
+ private static final int TEST_DISPLAY = Display.DEFAULT_DISPLAY + 1;
+ private static final int CURRENT_USER_ID = UserHandle.USER_SYSTEM;
+ private static final int SECOND_USER_ID = CURRENT_USER_ID + 1;
+
+ private static final float TEST_SCALE = 3;
+ private static final float DEFAULT_SCALE =
+ MagnificationScaleProvider.DEFAULT_MAGNIFICATION_SCALE;
+
+ @Rule
+ public final TestableContext mContext = new TestableContext(getInstrumentation().getContext());
+
+ private MagnificationScaleProvider mScaleProvider;
+
+ @Before
+ public void setUp() {
+ mScaleProvider = new MagnificationScaleProvider(mContext);
+ }
+
+ @Test
+ public void putScaleOnDefaultDisplay_getExpectedValue() throws Exception {
+ mScaleProvider.putScale(TEST_SCALE, Display.DEFAULT_DISPLAY);
+
+ TestUtils.waitUntil("settings value is not changed",
+ () -> Float.compare(mScaleProvider.getScale(Display.DEFAULT_DISPLAY),
+ TEST_SCALE) == 0);
+ }
+
+ @Test
+ public void putScaleOnTestDisplay_getExpectedValue() {
+ mScaleProvider.putScale(TEST_SCALE, TEST_DISPLAY);
+
+ assertEquals(TEST_SCALE, mScaleProvider.getScale(TEST_DISPLAY), 0);
+ }
+
+ @Test
+ public void onUserChanged_putScale_fallbackToDefaultScale() {
+ mScaleProvider.putScale(TEST_SCALE, TEST_DISPLAY);
+
+ mScaleProvider.onUserChanged(SECOND_USER_ID);
+ assertEquals(DEFAULT_SCALE, mScaleProvider.getScale(TEST_DISPLAY), 0);
+ }
+
+ @Test
+ public void onUserRemoved_setScaleOnSecondUser_fallbackToDefaultScale() {
+ mScaleProvider.onUserChanged(SECOND_USER_ID);
+ mScaleProvider.putScale(TEST_SCALE, TEST_DISPLAY);
+ mScaleProvider.onUserChanged(CURRENT_USER_ID);
+
+ mScaleProvider.onUserRemoved(SECOND_USER_ID);
+ // Assume the second user is created with the same id
+ mScaleProvider.onUserChanged(SECOND_USER_ID);
+
+ assertEquals(DEFAULT_SCALE, mScaleProvider.getScale(TEST_DISPLAY), 0);
+ }
+
+ @Test
+ public void onTestDisplayRemoved_setScaleOnTestDisplay_fallbackToDefaultScale() {
+ mScaleProvider.putScale(TEST_SCALE, TEST_DISPLAY);
+
+ mScaleProvider.onDisplayRemoved(TEST_DISPLAY);
+
+ assertEquals(DEFAULT_SCALE, mScaleProvider.getScale(TEST_DISPLAY), 0);
+ }
+}
diff --git a/services/tests/servicestests/src/com/android/server/accessibility/magnification/WindowMagnificationGestureHandlerTest.java b/services/tests/servicestests/src/com/android/server/accessibility/magnification/WindowMagnificationGestureHandlerTest.java
index 95f4327..1b8aff5 100644
--- a/services/tests/servicestests/src/com/android/server/accessibility/magnification/WindowMagnificationGestureHandlerTest.java
+++ b/services/tests/servicestests/src/com/android/server/accessibility/magnification/WindowMagnificationGestureHandlerTest.java
@@ -21,10 +21,10 @@
import static org.junit.Assert.fail;
import static org.mockito.Mockito.mock;
-import android.content.Context;
import android.graphics.PointF;
import android.graphics.Rect;
import android.os.RemoteException;
+import android.testing.TestableContext;
import android.util.DebugUtils;
import android.view.InputDevice;
import android.view.MotionEvent;
@@ -39,6 +39,7 @@
import org.junit.After;
import org.junit.Before;
+import org.junit.Rule;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Mock;
@@ -67,7 +68,10 @@
public static final float DEFAULT_TAP_Y = 299;
private static final int DISPLAY_0 = MockWindowMagnificationConnection.TEST_DISPLAY;
- private Context mContext;
+ @Rule
+ public final TestableContext mContext = new TestableContext(
+ InstrumentationRegistry.getInstrumentation().getContext());
+
private WindowMagnificationManager mWindowMagnificationManager;
private MockWindowMagnificationConnection mMockConnection;
private WindowMagnificationGestureHandler mWindowMagnificationGestureHandler;
@@ -79,9 +83,9 @@
@Before
public void setUp() throws RemoteException {
MockitoAnnotations.initMocks(this);
- mContext = InstrumentationRegistry.getInstrumentation().getContext();
mWindowMagnificationManager = new WindowMagnificationManager(mContext, 0,
- mock(WindowMagnificationManager.Callback.class), mMockTrace);
+ mock(WindowMagnificationManager.Callback.class), mMockTrace,
+ new MagnificationScaleProvider(mContext));
mMockConnection = new MockWindowMagnificationConnection();
mWindowMagnificationGestureHandler = new WindowMagnificationGestureHandler(
mContext, mWindowMagnificationManager, mMockTrace, mMockCallback,
diff --git a/services/tests/servicestests/src/com/android/server/accessibility/magnification/WindowMagnificationManagerTest.java b/services/tests/servicestests/src/com/android/server/accessibility/magnification/WindowMagnificationManagerTest.java
index af6d40f..da881c4 100644
--- a/services/tests/servicestests/src/com/android/server/accessibility/magnification/WindowMagnificationManagerTest.java
+++ b/services/tests/servicestests/src/com/android/server/accessibility/magnification/WindowMagnificationManagerTest.java
@@ -67,7 +67,7 @@
public class WindowMagnificationManagerTest {
private static final int TEST_DISPLAY = Display.DEFAULT_DISPLAY;
- private static final int CURRENT_USER_ID = UserHandle.USER_CURRENT;
+ private static final int CURRENT_USER_ID = UserHandle.USER_SYSTEM;
private MockWindowMagnificationConnection mMockConnection;
@Mock
@@ -91,7 +91,7 @@
mResolver = new MockContentResolver();
mMockConnection = new MockWindowMagnificationConnection();
mWindowMagnificationManager = new WindowMagnificationManager(mContext, CURRENT_USER_ID,
- mMockCallback, mMockTrace);
+ mMockCallback, mMockTrace, new MagnificationScaleProvider(mContext));
when(mContext.getContentResolver()).thenReturn(mResolver);
doAnswer((InvocationOnMock invocation) -> {
@@ -230,7 +230,7 @@
public void getPersistedScale() {
mWindowMagnificationManager.setConnection(mMockConnection.getConnection());
- assertEquals(mWindowMagnificationManager.getPersistedScale(), 2.5f);
+ assertEquals(mWindowMagnificationManager.getPersistedScale(TEST_DISPLAY), 2.5f);
}
@Test
@@ -264,7 +264,7 @@
mWindowMagnificationManager.setScale(TEST_DISPLAY, 10.0f);
assertEquals(mWindowMagnificationManager.getScale(TEST_DISPLAY),
- WindowMagnificationManager.MAX_SCALE);
+ MagnificationScaleProvider.MAX_SCALE);
}
@Test
diff --git a/services/tests/servicestests/src/com/android/server/pm/parsing/AndroidPackageParsingTestBase.kt b/services/tests/servicestests/src/com/android/server/pm/parsing/AndroidPackageParsingTestBase.kt
index 0602a55..f009488 100644
--- a/services/tests/servicestests/src/com/android/server/pm/parsing/AndroidPackageParsingTestBase.kt
+++ b/services/tests/servicestests/src/com/android/server/pm/parsing/AndroidPackageParsingTestBase.kt
@@ -334,10 +334,8 @@
launchToken=${this.launchToken}
lockTaskLaunchMode=${this.lockTaskLaunchMode}
logo=${this.logo}
- maxAspectRatio=${this.maxAspectRatio}
maxRecents=${this.maxRecents}
metaData=${this.metaData.dumpToString()}
- minAspectRatio=${this.minAspectRatio}
name=${this.name}
nonLocalizedLabel=${
// Per b/184574333, v1 mistakenly trimmed the label. v2 fixed this, but for test
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 f61d300..5694e59 100755
--- a/services/tests/uiservicestests/src/com/android/server/notification/NotificationManagerServiceTest.java
+++ b/services/tests/uiservicestests/src/com/android/server/notification/NotificationManagerServiceTest.java
@@ -3708,6 +3708,8 @@
assertEquals(IMPORTANCE_LOW,
mService.getNotificationRecord(sbn.getKey()).getImportance());
+ assertEquals(IMPORTANCE_UNSPECIFIED, mBinderService.getPackageImportance(
+ sbn.getPackageName()));
nb = new Notification.Builder(mContext)
.setContentTitle("foo")
diff --git a/services/tests/uiservicestests/src/com/android/server/notification/NotificationPermissionMigrationTest.java b/services/tests/uiservicestests/src/com/android/server/notification/NotificationPermissionMigrationTest.java
index 3ec8729..016b579 100755
--- a/services/tests/uiservicestests/src/com/android/server/notification/NotificationPermissionMigrationTest.java
+++ b/services/tests/uiservicestests/src/com/android/server/notification/NotificationPermissionMigrationTest.java
@@ -21,6 +21,7 @@
import static android.app.NotificationManager.EXTRA_BLOCKED_STATE;
import static android.app.NotificationManager.IMPORTANCE_DEFAULT;
import static android.app.NotificationManager.IMPORTANCE_NONE;
+import static android.app.NotificationManager.IMPORTANCE_UNSPECIFIED;
import static android.content.pm.PackageManager.FEATURE_WATCH;
import static android.content.pm.PackageManager.PERMISSION_GRANTED;
import static android.os.UserHandle.USER_SYSTEM;
@@ -123,6 +124,7 @@
import com.android.server.wm.WindowManagerInternal;
import org.junit.After;
+import org.junit.Assert;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
@@ -663,4 +665,17 @@
verify(mWorkerHandler, never()).post(
any(NotificationManagerService.EnqueueNotificationRunnable.class));
}
+
+ @Test
+ public void testDefaultChannelDoesNotUpdateApp_postMigrationToPermissions() throws Exception {
+ final NotificationChannel defaultChannel = mBinderService.getNotificationChannel(
+ PKG_N_MR1, ActivityManager.getCurrentUser(), PKG_N_MR1,
+ NotificationChannel.DEFAULT_CHANNEL_ID);
+ defaultChannel.setImportance(IMPORTANCE_NONE);
+
+ mBinderService.updateNotificationChannelForPackage(PKG_N_MR1, mUid, defaultChannel);
+
+ verify(mPermissionHelper).setNotificationPermission(
+ PKG_N_MR1, ActivityManager.getCurrentUser(), false, true);
+ }
}
diff --git a/services/tests/uiservicestests/src/com/android/server/notification/PreferencesHelperTest.java b/services/tests/uiservicestests/src/com/android/server/notification/PreferencesHelperTest.java
index 5324ec5f..d90f91a 100644
--- a/services/tests/uiservicestests/src/com/android/server/notification/PreferencesHelperTest.java
+++ b/services/tests/uiservicestests/src/com/android/server/notification/PreferencesHelperTest.java
@@ -4072,6 +4072,28 @@
assertTrue((channelA.getUserLockedFields() & USER_LOCKED_IMPORTANCE) == 0);
assertTrue((channelB.getUserLockedFields() & USER_LOCKED_IMPORTANCE) == 0);
assertTrue((channelC.getUserLockedFields() & USER_LOCKED_IMPORTANCE) == 0);
+ }
+ @Test
+ public void testDefaultChannelUpdatesApp_preMigrationToPermissions() throws Exception {
+ final NotificationChannel defaultChannel = mHelper.getNotificationChannel(PKG_N_MR1,
+ UID_N_MR1,
+ NotificationChannel.DEFAULT_CHANNEL_ID, false);
+ defaultChannel.setImportance(IMPORTANCE_NONE);
+ mHelper.updateNotificationChannel(PKG_N_MR1, UID_N_MR1, defaultChannel, true);
+
+ assertEquals(IMPORTANCE_NONE, mHelper.getImportance(PKG_N_MR1, UID_N_MR1));
+ }
+
+ @Test
+ public void testDefaultChannelDoesNotUpdateApp_postMigrationToPermissions() throws Exception {
+ when(mPermissionHelper.isMigrationEnabled()).thenReturn(true);
+ final NotificationChannel defaultChannel = mHelper.getNotificationChannel(PKG_N_MR1,
+ UID_N_MR1,
+ NotificationChannel.DEFAULT_CHANNEL_ID, false);
+ defaultChannel.setImportance(IMPORTANCE_NONE);
+ mHelper.updateNotificationChannel(PKG_N_MR1, UID_N_MR1, defaultChannel, true);
+
+ assertEquals(IMPORTANCE_UNSPECIFIED, mHelper.getImportance(PKG_N_MR1, UID_N_MR1));
}
}
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 1435b6f..5327dee 100644
--- a/services/tests/wmtests/src/com/android/server/wm/ActivityRecordTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/ActivityRecordTests.java
@@ -166,6 +166,8 @@
@Before
public void setUp() throws Exception {
setBooted(mAtm);
+ // Because the booted state is set, avoid starting real home if there is no task.
+ doReturn(false).when(mRootWindowContainer).resumeHomeActivity(any(), anyString(), any());
}
private TestStartingWindowOrganizer registerTestStartingWindowOrganizer() {
@@ -1083,6 +1085,7 @@
*/
@Test
public void testFinishActivityIfPossible_nonVisibleNoAppTransition() {
+ registerTestTransitionPlayer();
final ActivityRecord activity = createActivityWithTask();
// Put an activity on top of test activity to make it invisible and prevent us from
// accidentally resuming the topmost one again.
@@ -1093,6 +1096,7 @@
activity.finishIfPossible("test", false /* oomAdj */);
verify(activity.mDisplayContent, never()).prepareAppTransition(eq(TRANSIT_CLOSE));
+ assertFalse(activity.inTransition());
}
/**
@@ -1101,11 +1105,7 @@
*/
@Test
public void testFinishActivityIfPossible_lastInTaskRequestsTransitionWithTrigger() {
- // Set-up mock shell transitions
- final TestTransitionPlayer testPlayer = new TestTransitionPlayer(
- mAtm.getTransitionController(), mAtm.mWindowOrganizerController);
- mAtm.getTransitionController().registerTransitionPlayer(testPlayer);
-
+ final TestTransitionPlayer testPlayer = registerTestTransitionPlayer();
final ActivityRecord activity = createActivityWithTask();
activity.finishing = false;
activity.mVisibleRequested = true;
@@ -1117,6 +1117,29 @@
}
/**
+ * Verify that when collecting activity to the existing close transition, it should not affect
+ * ready state.
+ */
+ @Test
+ public void testFinishActivityIfPossible_collectToExistingTransition() {
+ final TestTransitionPlayer testPlayer = registerTestTransitionPlayer();
+ final ActivityRecord activity = createActivityWithTask();
+ activity.setState(PAUSED, "test");
+ activity.finishIfPossible("test", false /* oomAdj */);
+ final Transition lastTransition = testPlayer.mLastTransit;
+ assertTrue(lastTransition.allReady());
+ assertTrue(activity.inTransition());
+
+ // Collect another activity to the existing transition without changing ready state.
+ final ActivityRecord activity2 = createActivityRecord(activity.getTask());
+ activity2.setState(PAUSING, "test");
+ activity2.finishIfPossible("test", false /* oomAdj */);
+ assertTrue(activity2.inTransition());
+ assertEquals(lastTransition, testPlayer.mLastTransit);
+ assertTrue(lastTransition.allReady());
+ }
+
+ /**
* Verify that complete finish request for non-finishing activity is invalid.
*/
@Test(expected = IllegalArgumentException.class)
@@ -2467,9 +2490,8 @@
public void testCreateRemoveStartingWindow() {
registerTestStartingWindowOrganizer();
final ActivityRecord activity = new ActivityBuilder(mAtm).setCreateTask(true).build();
- activity.addStartingWindow(mPackageName,
- android.R.style.Theme, null, "Test", 0, 0, 0, 0, null, true, true, false, true,
- false, false, false);
+ activity.addStartingWindow(mPackageName, android.R.style.Theme, null, true, true, false,
+ true, false, false, false);
waitUntilHandlersIdle();
assertHasStartingWindow(activity);
activity.removeStartingWindow();
@@ -2480,9 +2502,8 @@
private void testLegacySplashScreen(int targetSdk, int verifyType) {
final ActivityRecord activity = new ActivityBuilder(mAtm).setCreateTask(true).build();
activity.mTargetSdk = targetSdk;
- activity.addStartingWindow(mPackageName,
- android.R.style.Theme, null, "Test", 0, 0, 0, 0, null, true, true, false, true,
- false, false, false);
+ activity.addStartingWindow(mPackageName, android.R.style.Theme, null, true, true, false,
+ true, false, false, false);
waitUntilHandlersIdle();
assertHasStartingWindow(activity);
assertEquals(activity.mStartingData.mTypeParams & TYPE_PARAMETER_LEGACY_SPLASH_SCREEN,
@@ -2518,13 +2539,11 @@
.setVisible(false).build();
final ActivityRecord activity2 = new ActivityBuilder(mAtm).setCreateTask(true)
.setVisible(false).build();
- activity1.addStartingWindow(mPackageName,
- android.R.style.Theme, null, "Test", 0, 0, 0, 0, null, true, true, false, true,
- false, false, false);
+ activity1.addStartingWindow(mPackageName, android.R.style.Theme, null, true, true, false,
+ true, false, false, false);
waitUntilHandlersIdle();
- activity2.addStartingWindow(mPackageName,
- android.R.style.Theme, null, "Test", 0, 0, 0, 0, activity1,
- true, true, false, true, false, false, false);
+ activity2.addStartingWindow(mPackageName, android.R.style.Theme, activity1, true, true,
+ false, true, false, false, false);
waitUntilHandlersIdle();
assertFalse(mDisplayContent.mSkipAppTransitionAnimation);
assertNoStartingWindow(activity1);
@@ -2539,14 +2558,11 @@
organizer.setRunnableWhenAddingSplashScreen(
() -> {
// Surprise, ...! Transfer window in the middle of the creation flow.
- activity2.addStartingWindow(mPackageName,
- android.R.style.Theme, null, "Test", 0, 0, 0, 0,
- activity1, true, true, false,
- true, false, false, false);
+ activity2.addStartingWindow(mPackageName, android.R.style.Theme, activity1,
+ true, true, false, true, false, false, false);
});
- activity1.addStartingWindow(mPackageName,
- android.R.style.Theme, null, "Test", 0, 0, 0, 0, null, true, true, false, true,
- false, false, false);
+ activity1.addStartingWindow(mPackageName, android.R.style.Theme, null, true, true, false,
+ true, false, false, false);
waitUntilHandlersIdle();
assertNoStartingWindow(activity1);
assertHasStartingWindow(activity2);
@@ -2557,13 +2573,11 @@
registerTestStartingWindowOrganizer();
final ActivityRecord activity1 = new ActivityBuilder(mAtm).setCreateTask(true).build();
final ActivityRecord activity2 = new ActivityBuilder(mAtm).setCreateTask(true).build();
- activity1.addStartingWindow(mPackageName,
- android.R.style.Theme, null, "Test", 0, 0, 0, 0, null, true, true, false, true,
- false, false, false);
+ activity1.addStartingWindow(mPackageName, android.R.style.Theme, null, true, true, false,
+ true, false, false, false);
waitUntilHandlersIdle();
- activity2.addStartingWindow(mPackageName,
- android.R.style.Theme, null, "Test", 0, 0, 0, 0, activity1,
- true, true, false, true, false, false, false);
+ activity2.addStartingWindow(mPackageName, android.R.style.Theme, activity1, true, true,
+ false, true, false, false, false);
waitUntilHandlersIdle();
assertNoStartingWindow(activity1);
assertHasStartingWindow(activity2);
@@ -2601,11 +2615,10 @@
registerTestStartingWindowOrganizer();
final ActivityRecord activity = new ActivityBuilder(mAtm).setCreateTask(true).build();
final Task task = activity.getTask();
- activity.addStartingWindow(mPackageName, android.R.style.Theme, null /* compatInfo */,
- "Test", 0 /* labelRes */, 0 /* icon */, 0 /* logo */, 0 /* windowFlags */,
- null /* transferFrom */, true /* newTask */, true /* taskSwitch */,
- false /* processRunning */, false /* allowTaskSnapshot */,
- false /* activityCreate */, false /* suggestEmpty */, false /* activityAllDrawn */);
+ activity.addStartingWindow(mPackageName, android.R.style.Theme, null /* transferFrom */,
+ true /* newTask */, true /* taskSwitch */, false /* processRunning */,
+ false /* allowTaskSnapshot */, false /* activityCreate */, false /* suggestEmpty
+ */, false /* activityAllDrawn */);
waitUntilHandlersIdle();
assertHasStartingWindow(activity);
@@ -2651,9 +2664,8 @@
final ActivityRecord topActivity = new ActivityBuilder(mAtm).setTask(task).build();
topActivity.setVisible(false);
task.positionChildAt(topActivity, POSITION_TOP);
- activity.addStartingWindow(mPackageName,
- android.R.style.Theme, null, "Test", 0, 0, 0, 0, null, true, true, false, true,
- false, false, false);
+ activity.addStartingWindow(mPackageName, android.R.style.Theme, null, true, true, false,
+ true, false, false, false);
waitUntilHandlersIdle();
// Make activities to have different rotation from it display and set fixed rotation
@@ -2668,9 +2680,8 @@
doReturn(true).when(activity).isAnimating(anyInt());
// Make sure the fixed rotation transform linked to activity2 when adding starting window
// on activity2.
- topActivity.addStartingWindow(mPackageName,
- android.R.style.Theme, null, "Test", 0, 0, 0, 0, activity,
- false, false, false, true, false, false, false);
+ topActivity.addStartingWindow(mPackageName, android.R.style.Theme, activity, false, false,
+ false, true, false, false, false);
waitUntilHandlersIdle();
assertTrue(topActivity.hasFixedRotationTransform());
}
@@ -2684,9 +2695,8 @@
activityTop.getTask().addChild(activityBottom, 0);
// Add a starting window.
- activityTop.addStartingWindow(mPackageName,
- android.R.style.Theme, null, "Test", 0, 0, 0, 0, null, true, true, false, true,
- false, false, false);
+ activityTop.addStartingWindow(mPackageName, android.R.style.Theme, null, true, true, false,
+ true, false, false, false);
waitUntilHandlersIdle();
// Make the top one invisible, and try transferring the starting window from the top to the
diff --git a/services/tests/wmtests/src/com/android/server/wm/DisplayAreaPolicyBuilderTest.java b/services/tests/wmtests/src/com/android/server/wm/DisplayAreaPolicyBuilderTest.java
index af21e02..525888d 100644
--- a/services/tests/wmtests/src/com/android/server/wm/DisplayAreaPolicyBuilderTest.java
+++ b/services/tests/wmtests/src/com/android/server/wm/DisplayAreaPolicyBuilderTest.java
@@ -85,7 +85,7 @@
@Rule
public final SystemServicesTestRule mSystemServices = new SystemServicesTestRule();
- private TestWindowManagerPolicy mPolicy = new TestWindowManagerPolicy(null, null);
+ private TestWindowManagerPolicy mPolicy = new TestWindowManagerPolicy();
private WindowManagerService mWms;
private RootDisplayArea mRoot;
private DisplayArea.Tokens mImeContainer;
diff --git a/services/tests/wmtests/src/com/android/server/wm/DisplayContentTests.java b/services/tests/wmtests/src/com/android/server/wm/DisplayContentTests.java
index 663d45b..0a3c813 100644
--- a/services/tests/wmtests/src/com/android/server/wm/DisplayContentTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/DisplayContentTests.java
@@ -1667,11 +1667,7 @@
public void testShellTransitRotation() {
DisplayContent dc = createNewDisplay();
- // Set-up mock shell transitions
- final TestTransitionPlayer testPlayer = new TestTransitionPlayer(
- mAtm.getTransitionController(), mAtm.mWindowOrganizerController);
- mAtm.getTransitionController().registerTransitionPlayer(testPlayer);
-
+ final TestTransitionPlayer testPlayer = registerTestTransitionPlayer();
final DisplayRotation dr = dc.getDisplayRotation();
doCallRealMethod().when(dr).updateRotationUnchecked(anyBoolean());
// Rotate 180 degree so the display doesn't have configuration change. This condition is
diff --git a/services/tests/wmtests/src/com/android/server/wm/DisplayPolicyLayoutTests.java b/services/tests/wmtests/src/com/android/server/wm/DisplayPolicyLayoutTests.java
index 4957ab9..03132c4 100644
--- a/services/tests/wmtests/src/com/android/server/wm/DisplayPolicyLayoutTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/DisplayPolicyLayoutTests.java
@@ -50,7 +50,6 @@
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotEquals;
import static org.junit.Assert.assertThat;
-import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.Mockito.doNothing;
import static org.mockito.Mockito.spy;
@@ -107,9 +106,6 @@
@Before
public void setUp() throws Exception {
mWindow = spy(createWindow(null, TYPE_APPLICATION, "window"));
- // We only test window frames set by DisplayPolicy, so here prevents computeFrameLw from
- // changing those frames.
- doNothing().when(mWindow).computeFrame(any());
spyOn(mStatusBarWindow);
spyOn(mNavBarWindow);
diff --git a/services/tests/wmtests/src/com/android/server/wm/DisplayPolicyTestsBase.java b/services/tests/wmtests/src/com/android/server/wm/DisplayPolicyTestsBase.java
index 3982a83..1d2baab 100644
--- a/services/tests/wmtests/src/com/android/server/wm/DisplayPolicyTestsBase.java
+++ b/services/tests/wmtests/src/com/android/server/wm/DisplayPolicyTestsBase.java
@@ -31,6 +31,7 @@
import static com.android.server.wm.utils.CoordinateTransforms.transformPhysicalToLogicalCoordinates;
import static org.junit.Assert.assertEquals;
+import static org.mockito.ArgumentMatchers.anyInt;
import android.content.Context;
import android.content.ContextWrapper;
@@ -75,13 +76,12 @@
final TestContextWrapper context = new TestContextWrapper(
mDisplayPolicy.getContext(), mDisplayPolicy.getCurrentUserResources());
final TestableResources resources = context.getResourceMocker();
- resources.addOverride(R.dimen.status_bar_height_portrait, STATUS_BAR_HEIGHT);
- resources.addOverride(R.dimen.status_bar_height_landscape, STATUS_BAR_HEIGHT);
resources.addOverride(R.dimen.navigation_bar_height, NAV_BAR_HEIGHT);
resources.addOverride(R.dimen.navigation_bar_height_landscape, NAV_BAR_HEIGHT);
resources.addOverride(R.dimen.navigation_bar_width, NAV_BAR_HEIGHT);
resources.addOverride(R.dimen.navigation_bar_frame_height_landscape, NAV_BAR_HEIGHT);
resources.addOverride(R.dimen.navigation_bar_frame_height, NAV_BAR_HEIGHT);
+ doReturn(STATUS_BAR_HEIGHT).when(mDisplayPolicy).getStatusBarHeightForRotation(anyInt());
doReturn(resources.getResources()).when(mDisplayPolicy).getCurrentUserResources();
doReturn(true).when(mDisplayPolicy).hasNavigationBar();
doReturn(true).when(mDisplayPolicy).hasStatusBar();
diff --git a/services/tests/wmtests/src/com/android/server/wm/RemoteAnimationControllerTest.java b/services/tests/wmtests/src/com/android/server/wm/RemoteAnimationControllerTest.java
index 08312ef..575e082 100644
--- a/services/tests/wmtests/src/com/android/server/wm/RemoteAnimationControllerTest.java
+++ b/services/tests/wmtests/src/com/android/server/wm/RemoteAnimationControllerTest.java
@@ -36,12 +36,14 @@
import static com.android.server.wm.SurfaceAnimator.ANIMATION_TYPE_APP_TRANSITION;
import static com.android.server.wm.SurfaceAnimator.ANIMATION_TYPE_WINDOW_ANIMATION;
+import static junit.framework.Assert.assertFalse;
import static junit.framework.Assert.fail;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertTrue;
import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.ArgumentMatchers.anyFloat;
import static org.mockito.ArgumentMatchers.anyInt;
import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.Mockito.mock;
@@ -699,6 +701,51 @@
}
}
+ @UseTestDisplay(addWindows = W_INPUT_METHOD)
+ @Test
+ public void testLaunchRemoteAnimationWithoutImeBehind() {
+ final WindowState win1 = createWindow(null /* parent */, TYPE_BASE_APPLICATION, "testWin1");
+ final WindowState win2 = createWindow(null /* parent */, TYPE_BASE_APPLICATION, "testWin2");
+
+ // Simulating win1 has shown IME and being IME layering/input target
+ mDisplayContent.setImeLayeringTarget(win1);
+ mDisplayContent.setImeInputTarget(win1);
+ mImeWindow.mWinAnimator.mSurfaceController = mock(WindowSurfaceController.class);
+ mImeWindow.mWinAnimator.hide(mDisplayContent.getPendingTransaction(), "test");
+ spyOn(mDisplayContent);
+ doReturn(true).when(mImeWindow.mWinAnimator.mSurfaceController).hasSurface();
+ doReturn(true).when(mImeWindow.mWinAnimator.mSurfaceController)
+ .prepareToShowInTransaction(any(), anyFloat());
+ makeWindowVisibleAndDrawn(mImeWindow);
+ assertTrue(mImeWindow.isOnScreen());
+ assertFalse(mImeWindow.isParentWindowHidden());
+
+ try {
+ // Simulating now win1 is being covered by the lockscreen which has no surface,
+ // and then launching an activity win2 with the remote animation
+ win1.mHasSurface = false;
+ mDisplayContent.mOpeningApps.add(win2.mActivityRecord);
+ final AnimationAdapter adapter = mController.createRemoteAnimationRecord(
+ win2.mActivityRecord, new Point(50, 100), null,
+ new Rect(50, 100, 150, 150), null).mAdapter;
+ adapter.startAnimation(mMockLeash, mMockTransaction, ANIMATION_TYPE_APP_TRANSITION,
+ mFinishedCallback);
+
+ mDisplayContent.applySurfaceChangesTransaction();
+ mController.goodToGo(TRANSIT_OLD_TASK_OPEN);
+ mWm.mAnimator.executeAfterPrepareSurfacesRunnables();
+
+ verify(mMockRunner).onAnimationStart(eq(TRANSIT_OLD_TASK_OPEN),
+ any(), any(), any(), any());
+ // Verify the IME window won't apply surface change transaction with forAllImeWindows
+ verify(mDisplayContent, never()).forAllImeWindows(any(), eq(true));
+ } catch (Exception e) {
+ // no-op
+ } finally {
+ mDisplayContent.mOpeningApps.clear();
+ }
+ }
+
private AnimationAdapter setupForNonAppTargetNavBar(int transit, boolean shouldAttachNavBar) {
final WindowState win = createWindow(null /* parent */, TYPE_BASE_APPLICATION, "testWin");
mDisplayContent.mOpeningApps.add(win.mActivityRecord);
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 6f0bea7..73e571a 100644
--- a/services/tests/wmtests/src/com/android/server/wm/SizeCompatTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/SizeCompatTests.java
@@ -83,6 +83,8 @@
import androidx.test.filters.MediumTest;
+import com.android.internal.policy.SystemBarUtils;
+
import libcore.junit.util.compat.CoreCompatChangeRule.DisableCompatChanges;
import libcore.junit.util.compat.CoreCompatChangeRule.EnableCompatChanges;
@@ -1121,6 +1123,98 @@
}
@Test
+ @EnableCompatChanges({ActivityInfo.OVERRIDE_MIN_ASPECT_RATIO,
+ ActivityInfo.OVERRIDE_MIN_ASPECT_RATIO_MEDIUM})
+ public void testOverrideMinAspectRatioScreenOrientationNotSetThenChangedToPortrait() {
+ // In this test, the activity's orientation isn't fixed to portrait, therefore the override
+ // isn't applied.
+
+ setUpDisplaySizeWithApp(1000, 1200);
+
+ // Create a size compat activity on the same task.
+ final ActivityRecord activity = new ActivityBuilder(mAtm)
+ .setTask(mTask)
+ .setComponent(ComponentName.createRelative(mContext,
+ SizeCompatTests.class.getName()))
+ .setUid(android.os.Process.myUid())
+ .build();
+
+ // The per-package override should have no effect
+ assertEquals(1200, activity.getBounds().height());
+ assertEquals(1000, activity.getBounds().width());
+
+ // After changing the orientation to portrait the override should be applied.
+ activity.setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);
+ activity.clearSizeCompatMode();
+
+ // The per-package override forces the activity into a 3:2 aspect ratio
+ assertEquals(1200, activity.getBounds().height());
+ assertEquals(1200 / ActivityInfo.OVERRIDE_MIN_ASPECT_RATIO_MEDIUM_VALUE,
+ activity.getBounds().width(), 0.5);
+ }
+
+ @Test
+ @EnableCompatChanges({ActivityInfo.OVERRIDE_MIN_ASPECT_RATIO,
+ ActivityInfo.OVERRIDE_MIN_ASPECT_RATIO_MEDIUM})
+ public void testOverrideMinAspectRatioScreenOrientationLandscapeThenChangedToPortrait() {
+ // In this test, the activity's orientation isn't fixed to portrait, therefore the override
+ // isn't applied.
+
+ setUpDisplaySizeWithApp(1000, 1200);
+
+ // Create a size compat activity on the same task.
+ final ActivityRecord activity = new ActivityBuilder(mAtm)
+ .setTask(mTask)
+ .setScreenOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE)
+ .setComponent(ComponentName.createRelative(mContext,
+ SizeCompatTests.class.getName()))
+ .setUid(android.os.Process.myUid())
+ .build();
+
+ // The per-package override should have no effect
+ assertEquals(1200, activity.getBounds().height());
+ assertEquals(1000, activity.getBounds().width());
+
+ // After changing the orientation to portrait the override should be applied.
+ activity.setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);
+ activity.clearSizeCompatMode();
+
+ // The per-package override forces the activity into a 3:2 aspect ratio
+ assertEquals(1200, activity.getBounds().height());
+ assertEquals(1200 / ActivityInfo.OVERRIDE_MIN_ASPECT_RATIO_MEDIUM_VALUE,
+ activity.getBounds().width(), 0.5);
+ }
+
+ @Test
+ @EnableCompatChanges({ActivityInfo.OVERRIDE_MIN_ASPECT_RATIO,
+ ActivityInfo.OVERRIDE_MIN_ASPECT_RATIO_MEDIUM})
+ public void testOverrideMinAspectRatioScreenOrientationPortraitThenChangedToUnspecified() {
+ setUpDisplaySizeWithApp(1000, 1200);
+
+ // Create a size compat activity on the same task.
+ final ActivityRecord activity = new ActivityBuilder(mAtm)
+ .setTask(mTask)
+ .setScreenOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT)
+ .setComponent(ComponentName.createRelative(mContext,
+ SizeCompatTests.class.getName()))
+ .setUid(android.os.Process.myUid())
+ .build();
+
+ // The per-package override forces the activity into a 3:2 aspect ratio
+ assertEquals(1200, activity.getBounds().height());
+ assertEquals(1200 / ActivityInfo.OVERRIDE_MIN_ASPECT_RATIO_MEDIUM_VALUE,
+ activity.getBounds().width(), 0.5);
+
+ // After changing the orientation to landscape the override shouldn't be applied.
+ activity.setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED);
+ activity.clearSizeCompatMode();
+
+ // The per-package override should have no effect
+ assertEquals(1200, activity.getBounds().height());
+ assertEquals(1000, activity.getBounds().width());
+ }
+
+ @Test
@EnableCompatChanges({ActivityInfo.OVERRIDE_MIN_ASPECT_RATIO_MEDIUM})
public void testOverrideMinAspectRatioWithoutGlobalOverride() {
// In this test, only OVERRIDE_MIN_ASPECT_RATIO_1_5 is set, which has no effect without
@@ -2128,8 +2222,7 @@
displayContent.mWmService, mock(Session.class), new TestIWindow(), attrs, token);
token.addWindow(statusBar);
statusBar.setRequestedSize(displayContent.mBaseDisplayWidth,
- displayContent.getDisplayUiContext().getResources().getDimensionPixelSize(
- com.android.internal.R.dimen.status_bar_height));
+ SystemBarUtils.getStatusBarHeight(displayContent.getDisplayUiContext()));
displayPolicy.addWindowLw(statusBar, attrs);
displayPolicy.layoutWindowLw(statusBar, null, displayContent.mDisplayFrames);
diff --git a/services/tests/wmtests/src/com/android/server/wm/SyncEngineTests.java b/services/tests/wmtests/src/com/android/server/wm/SyncEngineTests.java
index 7bac3e7..420ea8e 100644
--- a/services/tests/wmtests/src/com/android/server/wm/SyncEngineTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/SyncEngineTests.java
@@ -62,7 +62,7 @@
public void testTrivialSyncCallback() {
TestWindowContainer mockWC = new TestWindowContainer(mWm, false /* waiter */);
- BLASTSyncEngine bse = new BLASTSyncEngine(mWm);
+ final BLASTSyncEngine bse = createTestBLASTSyncEngine();
BLASTSyncEngine.TransactionReadyListener listener = mock(
BLASTSyncEngine.TransactionReadyListener.class);
@@ -90,7 +90,7 @@
public void testWaitingSyncCallback() {
TestWindowContainer mockWC = new TestWindowContainer(mWm, true /* waiter */);
- BLASTSyncEngine bse = new BLASTSyncEngine(mWm);
+ final BLASTSyncEngine bse = createTestBLASTSyncEngine();
BLASTSyncEngine.TransactionReadyListener listener = mock(
BLASTSyncEngine.TransactionReadyListener.class);
@@ -114,7 +114,7 @@
public void testInvisibleSyncCallback() {
TestWindowContainer mockWC = new TestWindowContainer(mWm, true /* waiter */);
- BLASTSyncEngine bse = new BLASTSyncEngine(mWm);
+ final BLASTSyncEngine bse = createTestBLASTSyncEngine();
BLASTSyncEngine.TransactionReadyListener listener = mock(
BLASTSyncEngine.TransactionReadyListener.class);
@@ -142,7 +142,7 @@
parentWC.addChild(childWC, POSITION_TOP);
parentWC.addChild(childWC2, POSITION_TOP);
- BLASTSyncEngine bse = new BLASTSyncEngine(mWm);
+ final BLASTSyncEngine bse = createTestBLASTSyncEngine();
BLASTSyncEngine.TransactionReadyListener listener = mock(
BLASTSyncEngine.TransactionReadyListener.class);
@@ -175,7 +175,7 @@
TestWindowContainer childWC = new TestWindowContainer(mWm, true /* waiter */);
parentWC.addChild(childWC, POSITION_TOP);
- BLASTSyncEngine bse = new BLASTSyncEngine(mWm);
+ final BLASTSyncEngine bse = createTestBLASTSyncEngine();
BLASTSyncEngine.TransactionReadyListener listener = mock(
BLASTSyncEngine.TransactionReadyListener.class);
@@ -206,7 +206,7 @@
parentWC.addChild(topChildWC, POSITION_TOP);
parentWC.addChild(botChildWC, POSITION_BOTTOM);
- BLASTSyncEngine bse = new BLASTSyncEngine(mWm);
+ final BLASTSyncEngine bse = createTestBLASTSyncEngine();
BLASTSyncEngine.TransactionReadyListener listener = mock(
BLASTSyncEngine.TransactionReadyListener.class);
@@ -238,7 +238,7 @@
parentWC.addChild(topChildWC, POSITION_TOP);
parentWC.addChild(botChildWC, POSITION_BOTTOM);
- BLASTSyncEngine bse = new BLASTSyncEngine(mWm);
+ final BLASTSyncEngine bse = createTestBLASTSyncEngine();
BLASTSyncEngine.TransactionReadyListener listener = mock(
BLASTSyncEngine.TransactionReadyListener.class);
@@ -273,7 +273,7 @@
parentWC.addChild(topChildWC, POSITION_TOP);
nonMemberParentWC.addChild(botChildWC, POSITION_BOTTOM);
- BLASTSyncEngine bse = new BLASTSyncEngine(mWm);
+ final BLASTSyncEngine bse = createTestBLASTSyncEngine();
BLASTSyncEngine.TransactionReadyListener listener = mock(
BLASTSyncEngine.TransactionReadyListener.class);
@@ -312,7 +312,7 @@
parentWC.addChild(topChildWC, POSITION_TOP);
parentWC.addChild(botChildWC, POSITION_BOTTOM);
- BLASTSyncEngine bse = new BLASTSyncEngine(mWm);
+ final BLASTSyncEngine bse = createTestBLASTSyncEngine();
BLASTSyncEngine.TransactionReadyListener listener = mock(
BLASTSyncEngine.TransactionReadyListener.class);
diff --git a/services/tests/wmtests/src/com/android/server/wm/SystemServicesTestRule.java b/services/tests/wmtests/src/com/android/server/wm/SystemServicesTestRule.java
index 5bc45d7..db60b98 100644
--- a/services/tests/wmtests/src/com/android/server/wm/SystemServicesTestRule.java
+++ b/services/tests/wmtests/src/com/android/server/wm/SystemServicesTestRule.java
@@ -99,7 +99,6 @@
private static final String TAG = SystemServicesTestRule.class.getSimpleName();
static int sNextDisplayId = DEFAULT_DISPLAY + 100;
- static int sNextTaskId = 100;
private static final int[] TEST_USER_PROFILE_IDS = {};
@@ -109,8 +108,6 @@
private ActivityManagerService mAmService;
private ActivityTaskManagerService mAtmService;
private WindowManagerService mWmService;
- private TestWindowManagerPolicy mWMPolicy;
- private TestDisplayWindowSettingsProvider mTestDisplayWindowSettingsProvider;
private WindowState.PowerManagerWrapper mPowerManagerWrapper;
private InputManagerService mImService;
private InputChannel mInputChannel;
@@ -283,14 +280,14 @@
private void setUpWindowManagerService() {
mPowerManagerWrapper = mock(WindowState.PowerManagerWrapper.class);
- mWMPolicy = new TestWindowManagerPolicy(this::getWindowManagerService,
- mPowerManagerWrapper);
- mTestDisplayWindowSettingsProvider = new TestDisplayWindowSettingsProvider();
+ TestWindowManagerPolicy wmPolicy = new TestWindowManagerPolicy();
+ TestDisplayWindowSettingsProvider testDisplayWindowSettingsProvider =
+ new TestDisplayWindowSettingsProvider();
// Suppress StrictMode violation (DisplayWindowSettings) to avoid log flood.
DisplayThread.getHandler().post(StrictMode::allowThreadDiskWritesMask);
mWmService = WindowManagerService.main(
- mContext, mImService, false, false, mWMPolicy, mAtmService,
- mTestDisplayWindowSettingsProvider, StubTransaction::new,
+ mContext, mImService, false, false, wmPolicy, mAtmService,
+ testDisplayWindowSettingsProvider, StubTransaction::new,
() -> mSurfaceFactory.get(), (unused) -> new MockSurfaceControlBuilder());
spyOn(mWmService);
spyOn(mWmService.mRoot);
diff --git a/services/tests/wmtests/src/com/android/server/wm/TaskSnapshotSurfaceTest.java b/services/tests/wmtests/src/com/android/server/wm/TaskSnapshotSurfaceTest.java
deleted file mode 100644
index 9372530..0000000
--- a/services/tests/wmtests/src/com/android/server/wm/TaskSnapshotSurfaceTest.java
+++ /dev/null
@@ -1,336 +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 com.android.server.wm;
-
-import static android.app.WindowConfiguration.ACTIVITY_TYPE_STANDARD;
-import static android.app.WindowConfiguration.WINDOWING_MODE_FULLSCREEN;
-import static android.content.res.Configuration.ORIENTATION_PORTRAIT;
-import static android.view.WindowManager.LayoutParams.FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS;
-import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_TRUSTED_OVERLAY;
-import static android.view.WindowManager.LayoutParams.TYPE_BASE_APPLICATION;
-
-import static com.android.dx.mockito.inline.extended.ExtendedMockito.mock;
-import static com.android.dx.mockito.inline.extended.ExtendedMockito.never;
-import static com.android.dx.mockito.inline.extended.ExtendedMockito.verify;
-import static com.android.dx.mockito.inline.extended.ExtendedMockito.when;
-
-import static com.google.common.truth.Truth.assertThat;
-
-import static org.junit.Assert.assertEquals;
-import static org.mockito.ArgumentMatchers.argThat;
-import static org.mockito.Matchers.any;
-import static org.mockito.Matchers.anyInt;
-import static org.mockito.Matchers.eq;
-
-import android.app.ActivityManager.TaskDescription;
-import android.content.ComponentName;
-import android.graphics.Canvas;
-import android.graphics.Color;
-import android.graphics.ColorSpace;
-import android.graphics.Point;
-import android.graphics.Rect;
-import android.hardware.HardwareBuffer;
-import android.platform.test.annotations.Presubmit;
-import android.view.Display;
-import android.view.IWindowSession;
-import android.view.InsetsState;
-import android.view.Surface;
-import android.view.SurfaceControl;
-import android.view.WindowManager;
-import android.window.TaskSnapshot;
-
-import androidx.test.filters.SmallTest;
-
-import com.android.server.wm.TaskSnapshotSurface.Window;
-
-import org.junit.Before;
-import org.junit.Test;
-import org.junit.runner.RunWith;
-
-/**
- * Test class for {@link TaskSnapshotSurface}.
- *
- * Build/Install/Run:
- * atest WmTests:TaskSnapshotSurfaceTest
- */
-@SmallTest
-@Presubmit
-@RunWith(WindowTestRunner.class)
-public class TaskSnapshotSurfaceTest extends WindowTestsBase {
-
- private TaskSnapshotSurface mSurface;
-
- private void setupSurface(int width, int height, Rect contentInsets, int sysuiVis,
- int windowFlags, Rect taskBounds) {
- // Previously when constructing TaskSnapshots for this test, scale was 1.0f, so to mimic
- // this behavior set the taskSize to be the same as the taskBounds width and height. The
- // taskBounds passed here are assumed to be the same task bounds as when the snapshot was
- // taken. We assume there is no aspect ratio mismatch between the screenshot and the
- // taskBounds
- assertEquals(width, taskBounds.width());
- assertEquals(height, taskBounds.height());
- Point taskSize = new Point(taskBounds.width(), taskBounds.height());
-
- final TaskSnapshot snapshot = createTaskSnapshot(width, height, taskSize, contentInsets);
- mSurface = new TaskSnapshotSurface(mWm, Display.DEFAULT_DISPLAY, new Window(),
- new SurfaceControl(), snapshot, "Test", createTaskDescription(Color.WHITE,
- Color.RED, Color.BLUE), sysuiVis, windowFlags, 0, taskBounds, ORIENTATION_PORTRAIT,
- ACTIVITY_TYPE_STANDARD, new InsetsState());
- }
-
- private TaskSnapshot createTaskSnapshot(int width, int height,
- Point taskSize, Rect contentInsets) {
- final HardwareBuffer buffer = HardwareBuffer.create(width, height, HardwareBuffer.RGBA_8888,
- 1, HardwareBuffer.USAGE_CPU_READ_RARELY);
- return new TaskSnapshot(
- System.currentTimeMillis(),
- new ComponentName("", ""), buffer,
- ColorSpace.get(ColorSpace.Named.SRGB), ORIENTATION_PORTRAIT,
- Surface.ROTATION_0, taskSize, contentInsets, false,
- true /* isRealSnapshot */, WINDOWING_MODE_FULLSCREEN,
- 0 /* systemUiVisibility */, false /* isTranslucent */, false /* hasImeSurface */);
- }
-
- private static TaskDescription createTaskDescription(int background, int statusBar,
- int navigationBar) {
- final TaskDescription td = new TaskDescription();
- td.setBackgroundColor(background);
- td.setStatusBarColor(statusBar);
- td.setNavigationBarColor(navigationBar);
- return td;
- }
-
- private void setupSurface(int width, int height) {
- setupSurface(width, height, new Rect(), 0, FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS,
- new Rect(0, 0, width, height));
- }
-
- private boolean isTrustedOverlay(WindowManager.LayoutParams params) {
- return (params.privateFlags & PRIVATE_FLAG_TRUSTED_OVERLAY) != 0;
- }
-
- @Before
- public void setUp() throws Exception {
- mSystemServicesTestRule.setSurfaceFactory(() -> {
- Surface surface = mock(Surface.class);
- when(surface.isValid()).thenReturn(true);
- return surface;
- });
- }
-
- @Test
- public void createSurface_asTrustedOverlay() throws Exception {
- Point task = new Point(200, 100);
- ActivityRecord activityRecord = createActivityRecord(mDisplayContent);
- createWindow(null, TYPE_BASE_APPLICATION, activityRecord, "window");
- TaskSnapshot taskSnapshot = createTaskSnapshot(task.x, task.y, task, new Rect());
- IWindowSession session = mock(IWindowSession.class);
-
- TaskSnapshotSurface surface = TaskSnapshotSurface.create(mWm, activityRecord, taskSnapshot,
- session);
-
- assertThat(surface).isNotNull();
- verify(session).addToDisplay(any(), argThat(this::isTrustedOverlay), anyInt(), anyInt(),
- any(), any(), any(), any());
- }
-
- @Test
- public void fillEmptyBackground_fillHorizontally() {
- setupSurface(200, 100);
- final Canvas mockCanvas = mock(Canvas.class);
- when(mockCanvas.getWidth()).thenReturn(200);
- when(mockCanvas.getHeight()).thenReturn(100);
- mSurface.drawBackgroundAndBars(mockCanvas, new Rect(0, 0, 100, 200));
- verify(mockCanvas).drawRect(eq(100.0f), eq(0.0f), eq(200.0f), eq(100.0f), any());
- }
-
- @Test
- public void fillEmptyBackground_fillVertically() {
- setupSurface(100, 200);
- final Canvas mockCanvas = mock(Canvas.class);
- when(mockCanvas.getWidth()).thenReturn(100);
- when(mockCanvas.getHeight()).thenReturn(200);
- mSurface.drawBackgroundAndBars(mockCanvas, new Rect(0, 0, 200, 100));
- verify(mockCanvas).drawRect(eq(0.0f), eq(100.0f), eq(100.0f), eq(200.0f), any());
- }
-
- @Test
- public void fillEmptyBackground_fillBoth() {
- setupSurface(200, 200);
- final Canvas mockCanvas = mock(Canvas.class);
- when(mockCanvas.getWidth()).thenReturn(200);
- when(mockCanvas.getHeight()).thenReturn(200);
- mSurface.drawBackgroundAndBars(mockCanvas, new Rect(0, 0, 100, 100));
- verify(mockCanvas).drawRect(eq(100.0f), eq(0.0f), eq(200.0f), eq(100.0f), any());
- verify(mockCanvas).drawRect(eq(0.0f), eq(100.0f), eq(200.0f), eq(200.0f), any());
- }
-
- @Test
- public void fillEmptyBackground_dontFill_sameSize() {
- setupSurface(100, 100);
- final Canvas mockCanvas = mock(Canvas.class);
- when(mockCanvas.getWidth()).thenReturn(100);
- when(mockCanvas.getHeight()).thenReturn(100);
- mSurface.drawBackgroundAndBars(mockCanvas, new Rect(0, 0, 100, 100));
- verify(mockCanvas, never()).drawRect(anyInt(), anyInt(), anyInt(), anyInt(), any());
- }
-
- @Test
- public void fillEmptyBackground_dontFill_bitmapLarger() {
- setupSurface(100, 100);
- final Canvas mockCanvas = mock(Canvas.class);
- when(mockCanvas.getWidth()).thenReturn(100);
- when(mockCanvas.getHeight()).thenReturn(100);
- mSurface.drawBackgroundAndBars(mockCanvas, new Rect(0, 0, 200, 200));
- verify(mockCanvas, never()).drawRect(anyInt(), anyInt(), anyInt(), anyInt(), any());
- }
-
- @Test
- public void testCalculateSnapshotCrop() {
- setupSurface(100, 100, new Rect(0, 10, 0, 10), 0, 0, new Rect(0, 0, 100, 100));
- assertEquals(new Rect(0, 0, 100, 90), mSurface.calculateSnapshotCrop());
- }
-
- @Test
- public void testCalculateSnapshotCrop_taskNotOnTop() {
- setupSurface(100, 100, new Rect(0, 10, 0, 10), 0, 0, new Rect(0, 50, 100, 150));
- assertEquals(new Rect(0, 10, 100, 90), mSurface.calculateSnapshotCrop());
- }
-
- @Test
- public void testCalculateSnapshotCrop_navBarLeft() {
- setupSurface(100, 100, new Rect(10, 10, 0, 0), 0, 0, new Rect(0, 0, 100, 100));
- assertEquals(new Rect(10, 0, 100, 100), mSurface.calculateSnapshotCrop());
- }
-
- @Test
- public void testCalculateSnapshotCrop_navBarRight() {
- setupSurface(100, 100, new Rect(0, 10, 10, 0), 0, 0, new Rect(0, 0, 100, 100));
- assertEquals(new Rect(0, 0, 90, 100), mSurface.calculateSnapshotCrop());
- }
-
- @Test
- public void testCalculateSnapshotCrop_waterfall() {
- setupSurface(100, 100, new Rect(5, 10, 5, 10), 0, 0, new Rect(0, 0, 100, 100));
- assertEquals(new Rect(5, 0, 95, 90), mSurface.calculateSnapshotCrop());
- }
-
- @Test
- public void testCalculateSnapshotFrame() {
- setupSurface(100, 100);
- final Rect insets = new Rect(0, 10, 0, 10);
- mSurface.setFrames(new Rect(0, 0, 100, 100), insets);
- assertEquals(new Rect(0, 0, 100, 80),
- mSurface.calculateSnapshotFrame(new Rect(0, 10, 100, 90)));
- }
-
- @Test
- public void testCalculateSnapshotFrame_navBarLeft() {
- setupSurface(100, 100);
- final Rect insets = new Rect(10, 10, 0, 0);
- mSurface.setFrames(new Rect(0, 0, 100, 100), insets);
- assertEquals(new Rect(10, 0, 100, 90),
- mSurface.calculateSnapshotFrame(new Rect(10, 10, 100, 100)));
- }
-
- @Test
- public void testCalculateSnapshotFrame_waterfall() {
- setupSurface(100, 100, new Rect(5, 10, 5, 10), 0, 0, new Rect(0, 0, 100, 100));
- final Rect insets = new Rect(0, 10, 0, 10);
- mSurface.setFrames(new Rect(5, 0, 95, 100), insets);
- assertEquals(new Rect(0, 0, 90, 90),
- mSurface.calculateSnapshotFrame(new Rect(5, 0, 95, 90)));
- }
-
- @Test
- public void testDrawStatusBarBackground() {
- setupSurface(100, 100);
- final Rect insets = new Rect(0, 10, 10, 0);
- mSurface.setFrames(new Rect(0, 0, 100, 100), insets);
- final Canvas mockCanvas = mock(Canvas.class);
- when(mockCanvas.getWidth()).thenReturn(100);
- when(mockCanvas.getHeight()).thenReturn(100);
- mSurface.mSystemBarBackgroundPainter.drawStatusBarBackground(
- mockCanvas, new Rect(0, 0, 50, 100), 10);
- verify(mockCanvas).drawRect(eq(50.0f), eq(0.0f), eq(90.0f), eq(10.0f), any());
- }
-
- @Test
- public void testDrawStatusBarBackground_nullFrame() {
- setupSurface(100, 100);
- final Rect insets = new Rect(0, 10, 10, 0);
- mSurface.setFrames(new Rect(0, 0, 100, 100), insets);
- final Canvas mockCanvas = mock(Canvas.class);
- when(mockCanvas.getWidth()).thenReturn(100);
- when(mockCanvas.getHeight()).thenReturn(100);
- mSurface.mSystemBarBackgroundPainter.drawStatusBarBackground(
- mockCanvas, null, 10);
- verify(mockCanvas).drawRect(eq(0.0f), eq(0.0f), eq(90.0f), eq(10.0f), any());
- }
-
- @Test
- public void testDrawStatusBarBackground_nope() {
- setupSurface(100, 100);
- final Rect insets = new Rect(0, 10, 10, 0);
- mSurface.setFrames(new Rect(0, 0, 100, 100), insets);
- final Canvas mockCanvas = mock(Canvas.class);
- when(mockCanvas.getWidth()).thenReturn(100);
- when(mockCanvas.getHeight()).thenReturn(100);
- mSurface.mSystemBarBackgroundPainter.drawStatusBarBackground(
- mockCanvas, new Rect(0, 0, 100, 100), 10);
- verify(mockCanvas, never()).drawRect(anyInt(), anyInt(), anyInt(), anyInt(), any());
- }
-
- @Test
- public void testDrawNavigationBarBackground() {
- final Rect insets = new Rect(0, 10, 0, 10);
- setupSurface(100, 100, insets, 0, FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS,
- new Rect(0, 0, 100, 100));
- mSurface.setFrames(new Rect(0, 0, 100, 100), insets);
- final Canvas mockCanvas = mock(Canvas.class);
- when(mockCanvas.getWidth()).thenReturn(100);
- when(mockCanvas.getHeight()).thenReturn(100);
- mSurface.mSystemBarBackgroundPainter.drawNavigationBarBackground(mockCanvas);
- verify(mockCanvas).drawRect(eq(new Rect(0, 90, 100, 100)), any());
- }
-
- @Test
- public void testDrawNavigationBarBackground_left() {
- final Rect insets = new Rect(10, 10, 0, 0);
- setupSurface(100, 100, insets, 0, FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS,
- new Rect(0, 0, 100, 100));
- mSurface.setFrames(new Rect(0, 0, 100, 100), insets);
- final Canvas mockCanvas = mock(Canvas.class);
- when(mockCanvas.getWidth()).thenReturn(100);
- when(mockCanvas.getHeight()).thenReturn(100);
- mSurface.mSystemBarBackgroundPainter.drawNavigationBarBackground(mockCanvas);
- verify(mockCanvas).drawRect(eq(new Rect(0, 0, 10, 100)), any());
- }
-
- @Test
- public void testDrawNavigationBarBackground_right() {
- final Rect insets = new Rect(0, 10, 10, 0);
- setupSurface(100, 100, insets, 0, FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS,
- new Rect(0, 0, 100, 100));
- mSurface.setFrames(new Rect(0, 0, 100, 100), insets);
- final Canvas mockCanvas = mock(Canvas.class);
- when(mockCanvas.getWidth()).thenReturn(100);
- when(mockCanvas.getHeight()).thenReturn(100);
- mSurface.mSystemBarBackgroundPainter.drawNavigationBarBackground(mockCanvas);
- verify(mockCanvas).drawRect(eq(new Rect(90, 0, 100, 100)), any());
- }
-}
diff --git a/services/tests/wmtests/src/com/android/server/wm/TestWindowManagerPolicy.java b/services/tests/wmtests/src/com/android/server/wm/TestWindowManagerPolicy.java
index 9001578..f570005 100644
--- a/services/tests/wmtests/src/com/android/server/wm/TestWindowManagerPolicy.java
+++ b/services/tests/wmtests/src/com/android/server/wm/TestWindowManagerPolicy.java
@@ -16,23 +16,16 @@
package com.android.server.wm;
-import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION_STARTING;
import static android.view.WindowManager.LayoutParams.TYPE_NOTIFICATION_SHADE;
-import static com.android.dx.mockito.inline.extended.ExtendedMockito.doReturn;
-import static com.android.dx.mockito.inline.extended.ExtendedMockito.mock;
-
import android.annotation.Nullable;
import android.content.Context;
-import android.content.res.CompatibilityInfo;
import android.content.res.Configuration;
import android.os.Bundle;
import android.os.IBinder;
import android.os.PowerManager.GoToSleepReason;
import android.os.PowerManager.WakeReason;
-import android.os.RemoteException;
import android.util.proto.ProtoOutputStream;
-import android.view.IWindow;
import android.view.IWindowManager;
import android.view.KeyEvent;
import android.view.WindowManager;
@@ -41,30 +34,19 @@
import com.android.internal.policy.IKeyguardDismissCallback;
import com.android.internal.policy.IShortcutService;
import com.android.server.policy.WindowManagerPolicy;
-import com.android.server.wm.WindowState.PowerManagerWrapper;
import java.io.PrintWriter;
-import java.util.function.Supplier;
class TestWindowManagerPolicy implements WindowManagerPolicy {
- private final Supplier<WindowManagerService> mWmSupplier;
- private final PowerManagerWrapper mPowerManagerWrapper;
- int mRotationToReport = 0;
boolean mKeyguardShowingAndNotOccluded = false;
boolean mOkToAnimate = true;
- private Runnable mRunnableWhenAddingSplashScreen;
-
- TestWindowManagerPolicy(Supplier<WindowManagerService> wmSupplier,
- PowerManagerWrapper powerManagerWrapper) {
- mWmSupplier = wmSupplier;
- mPowerManagerWrapper = powerManagerWrapper;
+ TestWindowManagerPolicy() {
}
@Override
- public void registerShortcutKey(long shortcutCode, IShortcutService shortcutKeyReceiver)
- throws RemoteException {
+ public void registerShortcutKey(long shortcutCode, IShortcutService shortcutKeyReceiver) {
}
@Override
@@ -91,42 +73,6 @@
return attrs.type == TYPE_NOTIFICATION_SHADE;
}
- /**
- * Sets a runnable to run when adding a splash screen which gets executed after the window has
- * been added but before returning the surface.
- */
- void setRunnableWhenAddingSplashScreen(Runnable r) {
- mRunnableWhenAddingSplashScreen = r;
- }
-
- @Override
- public StartingSurface addSplashScreen(IBinder appToken, int userId, String packageName,
- int theme, CompatibilityInfo compatInfo, CharSequence nonLocalizedLabel, int labelRes,
- int icon, int logo, int windowFlags, Configuration overrideConfig, int displayId) {
- final com.android.server.wm.WindowState window;
- final ActivityRecord activity;
- final WindowManagerService wm = mWmSupplier.get();
- synchronized (wm.mGlobalLock) {
- activity = wm.mRoot.getActivityRecord(appToken);
- IWindow iWindow = mock(IWindow.class);
- doReturn(mock(IBinder.class)).when(iWindow).asBinder();
- window = WindowTestsBase.createWindow(null, TYPE_APPLICATION_STARTING, activity,
- "Starting window", 0 /* ownerId */, 0 /* userId*/, false /* internalWindows */,
- wm, mock(Session.class), iWindow, mPowerManagerWrapper);
- activity.mStartingWindow = window;
- }
- if (mRunnableWhenAddingSplashScreen != null) {
- mRunnableWhenAddingSplashScreen.run();
- mRunnableWhenAddingSplashScreen = null;
- }
- return (a) -> {
- synchronized (wm.mGlobalLock) {
- activity.removeChild(window);
- activity.mStartingWindow = null;
- }
- };
- }
-
@Override
public Animation createHiddenByKeyguardExit(boolean onWallpaper,
boolean goingToNotificationShade, boolean subtleAnimation) {
diff --git a/services/tests/wmtests/src/com/android/server/wm/TransitionTests.java b/services/tests/wmtests/src/com/android/server/wm/TransitionTests.java
index a1c24c2..4e77fa7 100644
--- a/services/tests/wmtests/src/com/android/server/wm/TransitionTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/TransitionTests.java
@@ -21,7 +21,6 @@
import static android.app.WindowConfiguration.WINDOWING_MODE_FULLSCREEN;
import static android.view.WindowManager.LayoutParams.TYPE_WALLPAPER;
import static android.view.WindowManager.TRANSIT_CLOSE;
-import static android.view.WindowManager.TRANSIT_OLD_TASK_OPEN;
import static android.view.WindowManager.TRANSIT_OPEN;
import static android.view.WindowManager.TRANSIT_TO_BACK;
import static android.window.TransitionInfo.FLAG_IS_WALLPAPER;
@@ -44,6 +43,7 @@
import android.platform.test.annotations.Presubmit;
import android.util.ArrayMap;
import android.util.ArraySet;
+import android.view.SurfaceControl;
import android.window.ITaskOrganizer;
import android.window.ITransitionPlayer;
import android.window.TransitionInfo;
@@ -53,9 +53,12 @@
import org.junit.Test;
import org.junit.runner.RunWith;
+import java.util.concurrent.CountDownLatch;
+import java.util.concurrent.TimeUnit;
+
/**
* Build/Install/Run:
- * atest WmTests:TransitionRecordTests
+ * atest WmTests:TransitionTests
*/
@SmallTest
@Presubmit
@@ -64,13 +67,13 @@
private Transition createTestTransition(int transitType) {
TransitionController controller = mock(TransitionController.class);
- BLASTSyncEngine sync = new BLASTSyncEngine(mWm);
- return new Transition(transitType, 0 /* flags */, controller, sync);
+ final BLASTSyncEngine sync = createTestBLASTSyncEngine();
+ return new Transition(transitType, 0 /* flags */, 0 /* timeoutMs */, controller, sync);
}
@Test
public void testCreateInfo_NewTask() {
- final Transition transition = createTestTransition(TRANSIT_OLD_TASK_OPEN);
+ final Transition transition = createTestTransition(TRANSIT_OPEN);
ArrayMap<WindowContainer, Transition.ChangeInfo> changes = transition.mChanges;
ArraySet<WindowContainer> participants = transition.mParticipants;
@@ -88,7 +91,7 @@
closing.mVisibleRequested = false;
opening.mVisibleRequested = true;
- int transit = TRANSIT_OLD_TASK_OPEN;
+ final int transit = transition.mType;
int flags = 0;
// Check basic both tasks participating
@@ -127,7 +130,7 @@
@Test
public void testCreateInfo_NestedTasks() {
- final Transition transition = createTestTransition(TRANSIT_OLD_TASK_OPEN);
+ final Transition transition = createTestTransition(TRANSIT_OPEN);
ArrayMap<WindowContainer, Transition.ChangeInfo> changes = transition.mChanges;
ArraySet<WindowContainer> participants = transition.mParticipants;
@@ -152,7 +155,7 @@
opening.mVisibleRequested = true;
opening2.mVisibleRequested = true;
- int transit = TRANSIT_OLD_TASK_OPEN;
+ final int transit = transition.mType;
int flags = 0;
// Check full promotion from leaf
@@ -177,7 +180,7 @@
@Test
public void testCreateInfo_DisplayArea() {
- final Transition transition = createTestTransition(TRANSIT_OLD_TASK_OPEN);
+ final Transition transition = createTestTransition(TRANSIT_OPEN);
ArrayMap<WindowContainer, Transition.ChangeInfo> changes = transition.mChanges;
ArraySet<WindowContainer> participants = transition.mParticipants;
final Task showTask = createTask(mDisplayContent);
@@ -199,7 +202,7 @@
showing.mVisibleRequested = true;
showing2.mVisibleRequested = true;
- int transit = TRANSIT_OLD_TASK_OPEN;
+ final int transit = transition.mType;
int flags = 0;
// Check promotion to DisplayArea
@@ -228,7 +231,7 @@
@Test
public void testCreateInfo_existenceChange() {
- final Transition transition = createTestTransition(TRANSIT_OLD_TASK_OPEN);
+ final Transition transition = createTestTransition(TRANSIT_OPEN);
final Task openTask = createTask(mDisplayContent);
final ActivityRecord opening = createActivityRecord(openTask);
@@ -258,7 +261,7 @@
@Test
public void testCreateInfo_ordering() {
- final Transition transition = createTestTransition(TRANSIT_OLD_TASK_OPEN);
+ final Transition transition = createTestTransition(TRANSIT_OPEN);
// pick some number with a high enough chance of being out-of-order when added to set.
final int taskCount = 6;
@@ -294,7 +297,7 @@
@Test
public void testCreateInfo_wallpaper() {
- final Transition transition = createTestTransition(TRANSIT_OLD_TASK_OPEN);
+ final Transition transition = createTestTransition(TRANSIT_OPEN);
// pick some number with a high enough chance of being out-of-order when added to set.
final int taskCount = 4;
final int showWallpaperTask = 2;
@@ -345,7 +348,7 @@
@Test
public void testTargets_noIntermediatesToWallpaper() {
- final Transition transition = createTestTransition(TRANSIT_OLD_TASK_OPEN);
+ final Transition transition = createTestTransition(TRANSIT_OPEN);
final WallpaperWindowToken wallpaperWindowToken = new WallpaperWindowToken(mWm,
mock(IBinder.class), true, mDisplayContent, true /* ownerCanManageAppTokens */);
@@ -419,7 +422,7 @@
openInOpen.mVisibleRequested = true;
openInChange.mVisibleRequested = true;
- int transit = TRANSIT_OLD_TASK_OPEN;
+ final int transit = transition.mType;
int flags = 0;
// Check full promotion from leaf
@@ -450,6 +453,22 @@
}
@Test
+ public void testTimeout() {
+ final TransitionController controller = new TransitionController(mAtm,
+ mock(TaskSnapshotController.class));
+ final BLASTSyncEngine sync = new BLASTSyncEngine(mWm);
+ final CountDownLatch latch = new CountDownLatch(1);
+ // When the timeout is reached, it will finish the sync-group and notify transaction ready.
+ new Transition(TRANSIT_OPEN, 0 /* flags */, 10 /* timeoutMs */, controller, sync) {
+ @Override
+ public void onTransactionReady(int syncId, SurfaceControl.Transaction transaction) {
+ latch.countDown();
+ }
+ };
+ assertTrue(awaitInWmLock(() -> latch.await(3, TimeUnit.SECONDS)));
+ }
+
+ @Test
public void testIntermediateVisibility() {
final TaskSnapshotController snapshotController = mock(TaskSnapshotController.class);
final TransitionController controller = new TransitionController(mAtm, snapshotController);
diff --git a/services/tests/wmtests/src/com/android/server/wm/WindowFrameTests.java b/services/tests/wmtests/src/com/android/server/wm/WindowFrameTests.java
deleted file mode 100644
index 316309c..0000000
--- a/services/tests/wmtests/src/com/android/server/wm/WindowFrameTests.java
+++ /dev/null
@@ -1,325 +0,0 @@
-/*
- * Copyright (C) 2016 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;
-
-import static android.app.WindowConfiguration.WINDOWING_MODE_FREEFORM;
-import static android.app.WindowConfiguration.WINDOWING_MODE_FULLSCREEN;
-import static android.app.WindowConfiguration.WINDOWING_MODE_SPLIT_SCREEN_SECONDARY;
-import static android.view.InsetsState.ITYPE_IME;
-import static android.view.InsetsState.ITYPE_STATUS_BAR;
-import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION;
-
-import static com.android.dx.mockito.inline.extended.ExtendedMockito.mock;
-import static com.android.dx.mockito.inline.extended.ExtendedMockito.spyOn;
-
-import static org.junit.Assert.assertEquals;
-
-import android.content.res.Configuration;
-import android.graphics.Rect;
-import android.platform.test.annotations.Presubmit;
-import android.view.DisplayInfo;
-import android.view.Gravity;
-import android.view.InsetsSource;
-import android.view.InsetsState;
-import android.view.InsetsVisibilities;
-import android.view.WindowManager;
-
-import androidx.test.filters.FlakyTest;
-import androidx.test.filters.SmallTest;
-
-import org.junit.Before;
-import org.junit.Test;
-import org.junit.runner.RunWith;
-import org.mockito.Mockito;
-
-/**
- * Tests for the {@link WindowState#computeFrameLw} method and other window frame machinery.
- *
- * Build/Install/Run:
- * atest WmTests:WindowFrameTests
- */
-@SmallTest
-@Presubmit
-@RunWith(WindowTestRunner.class)
-public class WindowFrameTests extends WindowTestsBase {
-
- private DisplayContent mTestDisplayContent;
- private DisplayFrames mTestDisplayFrames;
-
- @Before
- public void setUp() throws Exception {
- DisplayInfo testDisplayInfo = new DisplayInfo(mDisplayInfo);
- testDisplayInfo.displayCutout = null;
- mTestDisplayContent = createNewDisplay(testDisplayInfo);
- mTestDisplayFrames = mTestDisplayContent.mDisplayFrames;
- }
-
- // Do not use this function directly in the tests below. Instead, use more explicit function
- // such as assertFlame().
- private void assertRect(Rect rect, int left, int top, int right, int bottom) {
- assertEquals(left, rect.left);
- assertEquals(top, rect.top);
- assertEquals(right, rect.right);
- assertEquals(bottom, rect.bottom);
- }
-
- private void assertFrame(WindowState w, Rect frame) {
- assertEquals(w.getFrame(), frame);
- }
-
- private void assertFrame(WindowState w, int left, int top, int right, int bottom) {
- assertRect(w.getFrame(), left, top, right, bottom);
- }
-
- private void assertRelFrame(WindowState w, int left, int top, int right, int bottom) {
- assertRect(w.getRelativeFrame(), left, top, right, bottom);
- }
-
- @Test
- public void testLayoutInFullscreenTask() {
- // fullscreen task doesn't use bounds for computeFrame
- WindowState w = createWindow();
- w.mAttrs.gravity = Gravity.LEFT | Gravity.TOP;
-
- // With no insets or system decor all the frames incoming from PhoneWindowManager
- // are identical.
- final Rect pf = new Rect(0, 0, 1000, 1000);
-
- // Here the window has FILL_PARENT, FILL_PARENT
- // so we expect it to fill the entire available frame.
- w.getWindowFrames().setFrames(pf, pf);
- w.computeFrame(mTestDisplayFrames);
- assertFrame(w, 0, 0, 1000, 1000);
- assertRelFrame(w, 0, 0, 1000, 1000);
-
- // It can select various widths and heights within the bounds.
- // Strangely the window attribute width is ignored for normal windows
- // and we use mRequestedWidth/mRequestedHeight
- w.mAttrs.width = 300;
- w.mAttrs.height = 300;
- w.computeFrame(mTestDisplayFrames);
- // Explicit width and height without requested width/height
- // gets us nothing.
- assertFrame(w, 0, 0, 0, 0);
-
- w.mRequestedWidth = 300;
- w.mRequestedHeight = 300;
- w.computeFrame(mTestDisplayFrames);
- // With requestedWidth/Height we can freely choose our size within the
- // parent bounds.
- assertFrame(w, 0, 0, 300, 300);
-
- // With FLAG_SCALED though, requestedWidth/height is used to control
- // the unscaled surface size, and mAttrs.width/height becomes the
- // layout controller.
- w.mAttrs.flags = WindowManager.LayoutParams.FLAG_SCALED;
- w.mRequestedHeight = -1;
- w.mRequestedWidth = -1;
- w.mAttrs.width = 100;
- w.mAttrs.height = 100;
- w.computeFrame(mTestDisplayFrames);
- assertFrame(w, 0, 0, 100, 100);
- w.mAttrs.flags = 0;
-
- // But sizes too large will be clipped to the containing frame
- w.mRequestedWidth = 1200;
- w.mRequestedHeight = 1200;
- w.computeFrame(mTestDisplayFrames);
- assertFrame(w, 0, 0, 1000, 1000);
-
- // Before they are clipped though windows will be shifted
- w.mAttrs.x = 300;
- w.mAttrs.y = 300;
- w.mRequestedWidth = 1000;
- w.mRequestedHeight = 1000;
- w.computeFrame(mTestDisplayFrames);
- assertFrame(w, 0, 0, 1000, 1000);
-
- // If there is room to move around in the parent frame the window will be shifted according
- // to gravity.
- w.mAttrs.x = 0;
- w.mAttrs.y = 0;
- w.mRequestedWidth = 300;
- w.mRequestedHeight = 300;
- w.mAttrs.gravity = Gravity.RIGHT | Gravity.TOP;
- w.computeFrame(mTestDisplayFrames);
- assertFrame(w, 700, 0, 1000, 300);
- assertRelFrame(w, 700, 0, 1000, 300);
- w.mAttrs.gravity = Gravity.RIGHT | Gravity.BOTTOM;
- w.computeFrame(mTestDisplayFrames);
- assertFrame(w, 700, 700, 1000, 1000);
- assertRelFrame(w, 700, 700, 1000, 1000);
- // Window specified x and y are interpreted as offsets in the opposite
- // direction of gravity
- w.mAttrs.x = 100;
- w.mAttrs.y = 100;
- w.computeFrame(mTestDisplayFrames);
- assertFrame(w, 600, 600, 900, 900);
- assertRelFrame(w, 600, 600, 900, 900);
- }
-
- @Test
- public void testLayoutNonfullscreenTask() {
- removeGlobalMinSizeRestriction();
- final DisplayInfo displayInfo = mWm.getDefaultDisplayContentLocked().getDisplayInfo();
- final int logicalWidth = displayInfo.logicalWidth;
- final int logicalHeight = displayInfo.logicalHeight;
-
- final Rect taskBounds = new Rect(
- logicalWidth / 4, logicalHeight / 4, logicalWidth / 4 * 3, logicalHeight / 4 * 3);
- WindowState w = createWindow();
- final Task task = w.getTask();
- // Use split-screen because it is non-fullscreen, but also not floating
- task.setWindowingMode(WINDOWING_MODE_SPLIT_SCREEN_SECONDARY);
- task.setBounds(taskBounds);
- // The bounds we are requesting might be different from what the system resolved based on
- // other factors.
- final Rect resolvedTaskBounds = task.getBounds();
- w.mAttrs.gravity = Gravity.LEFT | Gravity.TOP;
-
- final Rect pf = new Rect(0, 0, logicalWidth, logicalHeight);
- final WindowFrames windowFrames = w.getWindowFrames();
- windowFrames.setFrames(pf, pf);
- w.computeFrame(mTestDisplayFrames);
- // For non fullscreen tasks the containing frame is based off the
- // task bounds not the parent frame.
- assertEquals(resolvedTaskBounds, w.getFrame());
- assertEquals(0, w.getRelativeFrame().left);
- assertEquals(0, w.getRelativeFrame().top);
-
- pf.set(0, 0, logicalWidth, logicalHeight);
- // We still produce insets against the containing frame the same way.
- final int cfRight = logicalWidth / 2;
- final int cfBottom = logicalHeight / 2;
- final Rect cf = new Rect(0, 0, cfRight, cfBottom);
- windowFrames.setFrames(pf, pf);
- w.computeFrame(mTestDisplayFrames);
- assertEquals(resolvedTaskBounds, w.getFrame());
- assertEquals(0, w.getRelativeFrame().left);
- assertEquals(0, w.getRelativeFrame().top);
- }
-
- @Test
- @FlakyTest(bugId = 137879065)
- public void testLayoutLetterboxedWindow() {
- // First verify task behavior in multi-window mode.
- final DisplayInfo displayInfo = mTestDisplayContent.getDisplayInfo();
- final int logicalWidth = displayInfo.logicalWidth;
- final int logicalHeight = displayInfo.logicalHeight;
-
- final int taskLeft = logicalWidth / 5;
- final int taskTop = logicalHeight / 5;
- final int taskRight = logicalWidth / 4 * 3;
- final int taskBottom = logicalHeight / 4 * 3;
- final Rect taskBounds = new Rect(taskLeft, taskTop, taskRight, taskBottom);
- WindowState w = createWindow();
- final Task task = w.getTask();
- // Use split-screen because it is non-fullscreen, but also not floating
- task.setWindowingMode(WINDOWING_MODE_SPLIT_SCREEN_SECONDARY);
- task.setBounds(taskBounds);
- w.mAttrs.gravity = Gravity.LEFT | Gravity.TOP;
-
- final Rect pf = new Rect(0, 0, logicalWidth, logicalHeight);
- final WindowFrames windowFrames = w.getWindowFrames();
- windowFrames.setFrames(pf, pf);
- w.computeFrame(mTestDisplayFrames);
- // For non fullscreen tasks the containing frame is based off the
- // task bounds not the parent frame.
- assertFrame(w, taskLeft, taskTop, taskRight, taskBottom);
-
- // Now simulate switch to fullscreen for letterboxed app.
- final int xInset = logicalWidth / 10;
- final Rect cf = new Rect(xInset, 0, logicalWidth - xInset, logicalHeight);
- Configuration config = new Configuration(w.mActivityRecord.getRequestedOverrideConfiguration());
- config.windowConfiguration.setBounds(cf);
- config.windowConfiguration.setAppBounds(cf);
- w.mActivityRecord.onRequestedOverrideConfigurationChanged(config);
- pf.set(0, 0, logicalWidth, logicalHeight);
- task.setWindowingMode(WINDOWING_MODE_FULLSCREEN);
- task.setBounds(null);
- windowFrames.setFrames(pf, pf);
- w.computeFrame(mTestDisplayFrames);
- assertFrame(w, cf);
- }
-
- @Test
- public void testFreeformContentInsets() {
- removeGlobalMinSizeRestriction();
- // fullscreen task doesn't use bounds for computeFrame
- WindowState w = createWindow();
- final Task task = w.getTask();
- w.mAttrs.gravity = Gravity.LEFT | Gravity.TOP;
- task.setWindowingMode(WINDOWING_MODE_FREEFORM);
-
- // Make IME attach to the window and can produce insets.
- final DisplayContent dc = mTestDisplayContent;
- dc.setImeLayeringTarget(w);
- WindowState mockIme = mock(WindowState.class);
- Mockito.doReturn(true).when(mockIme).isVisibleNow();
- dc.mInputMethodWindow = mockIme;
- final InsetsState state = dc.getInsetsStateController().getRawInsetsState();
- final InsetsSource imeSource = state.getSource(ITYPE_IME);
- final Rect imeFrame = new Rect(state.getDisplayFrame());
- imeFrame.top = 400;
- imeSource.setFrame(imeFrame);
- imeSource.setVisible(true);
- final InsetsVisibilities requestedVisibilities = new InsetsVisibilities();
- requestedVisibilities.setVisibility(ITYPE_IME, true);
- w.setRequestedVisibilities(requestedVisibilities);
- w.mAboveInsetsState.addSource(imeSource);
-
- // With no insets or system decor all the frames incoming from PhoneWindowManager
- // are identical.
- final Rect pf = new Rect(0, 0, 1000, 800);
-
- // First check that it only gets moved up enough to show window.
- final Rect winRect = new Rect(200, 200, 300, 500);
- task.setBounds(winRect);
- w.getWindowFrames().setFrames(pf, pf);
- w.computeFrame(mTestDisplayFrames);
- assertFrame(w, winRect.left, imeFrame.top - winRect.height(), winRect.right, imeFrame.top);
-
- // Now check that it won't get moved beyond the top
- winRect.bottom = 650;
- task.setBounds(winRect);
- w.setBounds(winRect);
- w.getWindowFrames().setFrames(pf, pf);
- w.computeFrame(mTestDisplayFrames);
- assertFrame(w, winRect.left, 0, winRect.right, winRect.height());
-
- // Now we have status bar. Check that it won't go into the status bar area.
- final Rect statusBarFrame = new Rect(state.getDisplayFrame());
- statusBarFrame.bottom = 60;
- state.getSource(ITYPE_STATUS_BAR).setFrame(statusBarFrame);
- w.getWindowFrames().setFrames(pf, pf);
- w.computeFrame(mTestDisplayFrames);
- assertFrame(w, winRect.left, statusBarFrame.bottom, winRect.right,
- statusBarFrame.bottom + winRect.height());
-
- // Check that it's moved back without ime insets
- state.removeSource(ITYPE_IME);
- w.getWindowFrames().setFrames(pf, pf);
- w.computeFrame(mTestDisplayFrames);
- assertEquals(winRect, w.getFrame());
- }
-
- private WindowState createWindow() {
- final WindowState ws = createWindow(null, TYPE_APPLICATION, mTestDisplayContent, "WindowFrameTests");
- spyOn(ws);
- return ws;
- }
-}
diff --git a/services/tests/wmtests/src/com/android/server/wm/WindowLayoutTests.java b/services/tests/wmtests/src/com/android/server/wm/WindowLayoutTests.java
new file mode 100644
index 0000000..117f2ff
--- /dev/null
+++ b/services/tests/wmtests/src/com/android/server/wm/WindowLayoutTests.java
@@ -0,0 +1,158 @@
+/*
+ * Copyright (C) 2021 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;
+
+import static android.view.WindowLayout.UNSPECIFIED_LENGTH;
+
+import static org.junit.Assert.assertEquals;
+
+import android.app.WindowConfiguration;
+import android.graphics.Rect;
+import android.platform.test.annotations.Presubmit;
+import android.view.Gravity;
+import android.view.InsetsState;
+import android.view.InsetsVisibilities;
+import android.view.WindowLayout;
+import android.view.WindowManager;
+
+import androidx.test.filters.SmallTest;
+
+import org.junit.Before;
+import org.junit.Test;
+
+/**
+ * Tests for the {@link WindowLayout#computeWindowFrames}.
+ *
+ * Build/Install/Run:
+ * atest WmTests:WindowLayoutTests
+ */
+@SmallTest
+@Presubmit
+public class WindowLayoutTests {
+ private static final int DISPLAY_WIDTH = 500;
+ private static final int DISPLAY_HEIGHT = 1000;
+ private static final int STATUS_BAR_HEIGHT = 10;
+ private static final int NAVIGATION_BAR_HEIGHT = 15;
+
+ private final WindowLayout mWindowLayout = new WindowLayout();
+ private final Rect mDisplayFrame = new Rect();
+ private final Rect mParentFrame = new Rect();
+ private final Rect mFrame = new Rect();
+
+ private WindowManager.LayoutParams mAttrs;
+ private InsetsState mState;
+ private final Rect mDisplayCutoutSafe = new Rect();
+ private Rect mWindowBounds;
+ private int mWindowingMode;
+ private int mRequestedWidth;
+ private int mRequestedHeight;
+ private InsetsVisibilities mRequestedVisibilities;
+ private Rect mAttachedWindowFrame;
+ private float mCompatScale;
+
+ @Before
+ public void setUp() {
+ mAttrs = new WindowManager.LayoutParams();
+ mState = new InsetsState();
+ mState.setDisplayFrame(new Rect(0, 0, DISPLAY_WIDTH, DISPLAY_HEIGHT));
+ mState.getSource(InsetsState.ITYPE_STATUS_BAR).setFrame(
+ 0, 0, DISPLAY_WIDTH, STATUS_BAR_HEIGHT);
+ mState.getSource(InsetsState.ITYPE_NAVIGATION_BAR).setFrame(
+ 0, DISPLAY_HEIGHT - NAVIGATION_BAR_HEIGHT, DISPLAY_WIDTH, DISPLAY_HEIGHT);
+ mState.getDisplayCutoutSafe(mDisplayCutoutSafe);
+ mWindowBounds = new Rect(0, 0, DISPLAY_WIDTH, DISPLAY_HEIGHT);
+ mWindowingMode = WindowConfiguration.WINDOWING_MODE_FULLSCREEN;
+ mRequestedWidth = DISPLAY_WIDTH;
+ mRequestedHeight = DISPLAY_HEIGHT;
+ mRequestedVisibilities = new InsetsVisibilities();
+ mAttachedWindowFrame = null;
+ mCompatScale = 1f;
+ }
+
+ @Test
+ public void testDefaultLayoutParams() {
+ computeWindowFrames();
+
+ assertRect(0, STATUS_BAR_HEIGHT, DISPLAY_WIDTH, DISPLAY_HEIGHT - NAVIGATION_BAR_HEIGHT,
+ mDisplayFrame);
+ assertRect(0, STATUS_BAR_HEIGHT, DISPLAY_WIDTH, DISPLAY_HEIGHT - NAVIGATION_BAR_HEIGHT,
+ mParentFrame);
+ assertRect(0, STATUS_BAR_HEIGHT, DISPLAY_WIDTH, DISPLAY_HEIGHT - NAVIGATION_BAR_HEIGHT,
+ mFrame);
+ }
+
+ @Test
+ public void testUnmeasured() {
+ mRequestedWidth = UNSPECIFIED_LENGTH;
+ mRequestedHeight = UNSPECIFIED_LENGTH;
+ computeWindowFrames();
+
+ assertRect(0, STATUS_BAR_HEIGHT, DISPLAY_WIDTH, DISPLAY_HEIGHT - NAVIGATION_BAR_HEIGHT,
+ mDisplayFrame);
+ assertRect(0, STATUS_BAR_HEIGHT, DISPLAY_WIDTH, DISPLAY_HEIGHT - NAVIGATION_BAR_HEIGHT,
+ mParentFrame);
+ assertRect(0, STATUS_BAR_HEIGHT, DISPLAY_WIDTH, DISPLAY_HEIGHT - NAVIGATION_BAR_HEIGHT,
+ mFrame);
+ }
+
+ @Test
+ public void testUnmeasuredWithSizeSpecifiedInLayoutParams() {
+ final int width = DISPLAY_WIDTH / 2;
+ final int height = DISPLAY_HEIGHT / 2;
+ mRequestedWidth = UNSPECIFIED_LENGTH;
+ mRequestedHeight = UNSPECIFIED_LENGTH;
+ mAttrs.width = width;
+ mAttrs.height = height;
+ mAttrs.gravity = Gravity.LEFT | Gravity.TOP;
+ computeWindowFrames();
+
+ assertRect(0, STATUS_BAR_HEIGHT, DISPLAY_WIDTH, DISPLAY_HEIGHT - NAVIGATION_BAR_HEIGHT,
+ mDisplayFrame);
+ assertRect(0, STATUS_BAR_HEIGHT, DISPLAY_WIDTH, DISPLAY_HEIGHT - NAVIGATION_BAR_HEIGHT,
+ mParentFrame);
+ assertRect(0, STATUS_BAR_HEIGHT, width, STATUS_BAR_HEIGHT + height,
+ mFrame);
+ }
+
+ @Test
+ public void testNonFullscreenWindowBounds() {
+ final int top = Math.max(DISPLAY_HEIGHT / 2, STATUS_BAR_HEIGHT);
+ mWindowBounds.set(0, top, DISPLAY_WIDTH, DISPLAY_HEIGHT);
+ mRequestedWidth = UNSPECIFIED_LENGTH;
+ mRequestedHeight = UNSPECIFIED_LENGTH;
+ computeWindowFrames();
+
+ assertRect(0, top, DISPLAY_WIDTH, DISPLAY_HEIGHT - NAVIGATION_BAR_HEIGHT,
+ mDisplayFrame);
+ assertRect(0, top, DISPLAY_WIDTH, DISPLAY_HEIGHT - NAVIGATION_BAR_HEIGHT,
+ mParentFrame);
+ assertRect(0, top, DISPLAY_WIDTH, DISPLAY_HEIGHT - NAVIGATION_BAR_HEIGHT,
+ mFrame);
+ }
+
+ // TODO(b/161810301): Move tests here from DisplayPolicyLayoutTests and add more tests.
+
+ private void computeWindowFrames() {
+ mWindowLayout.computeWindowFrames(mAttrs, mState, mDisplayCutoutSafe, mWindowBounds,
+ mWindowingMode, mRequestedWidth, mRequestedHeight, mRequestedVisibilities,
+ mAttachedWindowFrame, mCompatScale, mDisplayFrame, mParentFrame, mFrame);
+ }
+
+ private void assertRect(int left, int top, int right, int bottom, Rect actual) {
+ assertEquals(new Rect(left, top, right, bottom), actual);
+ }
+}
diff --git a/services/tests/wmtests/src/com/android/server/wm/WindowTestsBase.java b/services/tests/wmtests/src/com/android/server/wm/WindowTestsBase.java
index b2d4eea..42fe0e9 100644
--- a/services/tests/wmtests/src/com/android/server/wm/WindowTestsBase.java
+++ b/services/tests/wmtests/src/com/android/server/wm/WindowTestsBase.java
@@ -54,7 +54,6 @@
import static com.android.dx.mockito.inline.extended.ExtendedMockito.doNothing;
import static com.android.dx.mockito.inline.extended.ExtendedMockito.doReturn;
import static com.android.dx.mockito.inline.extended.ExtendedMockito.spyOn;
-import static com.android.server.wm.StartingSurfaceController.DEBUG_ENABLE_SHELL_DRAWER;
import static com.android.server.wm.WindowContainer.POSITION_BOTTOM;
import static com.android.server.wm.WindowContainer.POSITION_TOP;
import static com.android.server.wm.WindowStateAnimator.HAS_DRAWN;
@@ -285,8 +284,6 @@
mStatusBarWindow.mAttrs.gravity = Gravity.TOP;
mStatusBarWindow.mAttrs.layoutInDisplayCutoutMode =
LAYOUT_IN_DISPLAY_CUTOUT_MODE_ALWAYS;
- mStatusBarWindow.setRequestedSize(WindowManager.LayoutParams.MATCH_PARENT,
- STATUS_BAR_HEIGHT);
}
}
if (addAll || ArrayUtils.contains(requestedWindows, W_NOTIFICATION_SHADE)) {
@@ -789,6 +786,23 @@
};
}
+ BLASTSyncEngine createTestBLASTSyncEngine() {
+ return new BLASTSyncEngine(mWm) {
+ @Override
+ void scheduleTimeout(SyncGroup s, long timeoutMs) {
+ // Disable timeout.
+ }
+ };
+ }
+
+ /** Sets up a simple implementation of transition player for shell transitions. */
+ TestTransitionPlayer registerTestTransitionPlayer() {
+ final TestTransitionPlayer testPlayer = new TestTransitionPlayer(
+ mAtm.getTransitionController(), mAtm.mWindowOrganizerController);
+ testPlayer.mController.registerTransitionPlayer(testPlayer);
+ return testPlayer;
+ }
+
/**
* Avoids rotating screen disturbed by some conditions. It is usually used for the default
* display that is not the instance of {@link TestDisplayContent} (it bypasses the conditions).
@@ -1420,18 +1434,12 @@
mAtm = service;
mWMService = mAtm.mWindowManager;
mPowerManagerWrapper = powerManagerWrapper;
- if (DEBUG_ENABLE_SHELL_DRAWER) {
- mAtm.mTaskOrganizerController.setDeferTaskOrgCallbacksConsumer(Runnable::run);
- mAtm.mTaskOrganizerController.registerTaskOrganizer(this);
- }
+ mAtm.mTaskOrganizerController.setDeferTaskOrgCallbacksConsumer(Runnable::run);
+ mAtm.mTaskOrganizerController.registerTaskOrganizer(this);
}
void setRunnableWhenAddingSplashScreen(Runnable r) {
- if (DEBUG_ENABLE_SHELL_DRAWER) {
- mRunnableWhenAddingSplashScreen = r;
- } else {
- ((TestWindowManagerPolicy) mWMService.mPolicy).setRunnableWhenAddingSplashScreen(r);
- }
+ mRunnableWhenAddingSplashScreen = r;
}
@Override
@@ -1597,7 +1605,7 @@
}
}
- class TestTransitionPlayer extends ITransitionPlayer.Stub {
+ static class TestTransitionPlayer extends ITransitionPlayer.Stub {
final TransitionController mController;
final WindowOrganizerController mOrganizer;
Transition mLastTransit = null;
diff --git a/services/tests/wmtests/src/com/android/server/wm/ZOrderingTests.java b/services/tests/wmtests/src/com/android/server/wm/ZOrderingTests.java
index 6c3a1f6..dfbdede 100644
--- a/services/tests/wmtests/src/com/android/server/wm/ZOrderingTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/ZOrderingTests.java
@@ -23,7 +23,6 @@
import static android.app.WindowConfiguration.WINDOWING_MODE_MULTI_WINDOW;
import static android.app.WindowConfiguration.WINDOWING_MODE_PINNED;
import static android.app.WindowConfiguration.WINDOWING_MODE_SPLIT_SCREEN_PRIMARY;
-import static android.app.WindowConfiguration.WINDOWING_MODE_SPLIT_SCREEN_SECONDARY;
import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION;
import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION_ABOVE_SUB_PANEL;
import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION_ATTACHED_DIALOG;
@@ -469,24 +468,42 @@
@Test
public void testDockedDividerPosition() {
- final WindowState pinnedStackWindow = createWindow(null, WINDOWING_MODE_PINNED,
- ACTIVITY_TYPE_STANDARD, TYPE_BASE_APPLICATION, mDisplayContent,
- "pinnedStackWindow");
- final WindowState splitScreenWindow = createWindow(null,
- WINDOWING_MODE_SPLIT_SCREEN_PRIMARY, ACTIVITY_TYPE_STANDARD, TYPE_BASE_APPLICATION,
- mDisplayContent, "splitScreenWindow");
- final WindowState splitScreenSecondaryWindow = createWindow(null,
- WINDOWING_MODE_SPLIT_SCREEN_SECONDARY, ACTIVITY_TYPE_STANDARD,
- TYPE_BASE_APPLICATION, mDisplayContent, "splitScreenSecondaryWindow");
- final WindowState assistantStackWindow = createWindow(null,
- WINDOWING_MODE_FULLSCREEN, ACTIVITY_TYPE_ASSISTANT, TYPE_BASE_APPLICATION,
- mDisplayContent, "assistantStackWindow");
+ final Task pinnedTask =
+ createTask(mDisplayContent, WINDOWING_MODE_PINNED, ACTIVITY_TYPE_STANDARD);
+ final WindowState pinnedWindow =
+ createAppWindow(pinnedTask, ACTIVITY_TYPE_STANDARD, "pinnedWindow");
+
+ final Task belowTask =
+ createTask(mDisplayContent, WINDOWING_MODE_FULLSCREEN, ACTIVITY_TYPE_STANDARD);
+ final WindowState belowTaskWindow =
+ createAppWindow(belowTask, ACTIVITY_TYPE_STANDARD, "belowTaskWindow");
+
+ final Task splitScreenTask1 =
+ createTask(mDisplayContent, WINDOWING_MODE_MULTI_WINDOW, ACTIVITY_TYPE_STANDARD);
+ final WindowState splitWindow1 =
+ createAppWindow(splitScreenTask1, ACTIVITY_TYPE_STANDARD, "splitWindow1");
+ final Task splitScreenTask2 =
+ createTask(mDisplayContent, WINDOWING_MODE_MULTI_WINDOW, ACTIVITY_TYPE_STANDARD);
+ final WindowState splitWindow2 =
+ createAppWindow(splitScreenTask2, ACTIVITY_TYPE_STANDARD, "splitWindow2");
+ splitScreenTask1.setAdjacentTaskFragment(splitScreenTask2);
+ splitScreenTask2.setAdjacentTaskFragment(splitScreenTask1);
+
+ final Task aboveTask =
+ createTask(mDisplayContent, WINDOWING_MODE_FULLSCREEN, ACTIVITY_TYPE_STANDARD);
+ final WindowState aboveTaskWindow =
+ createAppWindow(aboveTask, ACTIVITY_TYPE_STANDARD, "aboveTaskWindow");
mDisplayContent.assignChildLayers(mTransaction);
- assertWindowHigher(mDockedDividerWindow, splitScreenWindow);
- assertWindowHigher(mDockedDividerWindow, splitScreenSecondaryWindow);
- assertWindowHigher(pinnedStackWindow, mDockedDividerWindow);
+ assertWindowHigher(splitWindow1, belowTaskWindow);
+ assertWindowHigher(splitWindow1, belowTaskWindow);
+ assertWindowHigher(splitWindow2, belowTaskWindow);
+ assertWindowHigher(splitWindow2, belowTaskWindow);
+ assertWindowHigher(mDockedDividerWindow, splitWindow1);
+ assertWindowHigher(mDockedDividerWindow, splitWindow2);
+ assertWindowHigher(aboveTaskWindow, mDockedDividerWindow);
+ assertWindowHigher(pinnedWindow, aboveTaskWindow);
}
@Test
diff --git a/services/usb/java/com/android/server/usb/UsbDeviceManager.java b/services/usb/java/com/android/server/usb/UsbDeviceManager.java
index 0d7b23d..4220fd7 100644
--- a/services/usb/java/com/android/server/usb/UsbDeviceManager.java
+++ b/services/usb/java/com/android/server/usb/UsbDeviceManager.java
@@ -771,6 +771,8 @@
private void broadcastUsbAccessoryHandshake() {
// send a sticky broadcast containing USB accessory handshake information
Intent intent = new Intent(UsbManager.ACTION_USB_ACCESSORY_HANDSHAKE)
+ .addFlags(Intent.FLAG_RECEIVER_INCLUDE_BACKGROUND
+ | Intent.FLAG_RECEIVER_FOREGROUND)
.putExtra(UsbManager.EXTRA_ACCESSORY_UEVENT_TIME,
mAccessoryConnectionStartTime)
.putExtra(UsbManager.EXTRA_ACCESSORY_STRING_COUNT,
diff --git a/telephony/common/com/android/internal/telephony/TelephonyPermissions.java b/telephony/common/com/android/internal/telephony/TelephonyPermissions.java
index 7a424c8..10fba60 100644
--- a/telephony/common/com/android/internal/telephony/TelephonyPermissions.java
+++ b/telephony/common/com/android/internal/telephony/TelephonyPermissions.java
@@ -650,7 +650,13 @@
private static boolean checkCarrierPrivilegeForAnySubId(Context context, int uid) {
SubscriptionManager sm = (SubscriptionManager) context.getSystemService(
Context.TELEPHONY_SUBSCRIPTION_SERVICE);
- int[] activeSubIds = sm.getCompleteActiveSubscriptionIdList();
+ int[] activeSubIds;
+ final long identity = Binder.clearCallingIdentity();
+ try {
+ activeSubIds = sm.getCompleteActiveSubscriptionIdList();
+ } finally {
+ Binder.restoreCallingIdentity(identity);
+ }
for (int activeSubId : activeSubIds) {
if (getCarrierPrivilegeStatus(context, activeSubId, uid)
== TelephonyManager.CARRIER_PRIVILEGE_STATUS_HAS_ACCESS) {
diff --git a/telephony/java/android/telephony/CarrierConfigManager.java b/telephony/java/android/telephony/CarrierConfigManager.java
index edfb7bf..22eb50a 100644
--- a/telephony/java/android/telephony/CarrierConfigManager.java
+++ b/telephony/java/android/telephony/CarrierConfigManager.java
@@ -1886,6 +1886,20 @@
"lte_plus_threshold_bandwidth_khz_int";
/**
+ * The combined channel bandwidth threshold (non-inclusive) in KHz required to display the
+ * NR advanced (i.e. 5G+) data icon. It is 0 by default, meaning minimum bandwidth check is
+ * not enabled. Other factors like bands or frequency can also determine whether the NR
+ * advanced data icon is shown or not.
+ *
+ * @see #KEY_ADDITIONAL_NR_ADVANCED_BANDS_INT_ARRAY
+ * @see #KEY_NR_ADVANCED_CAPABLE_PCO_ID_INT
+ *
+ * @hide
+ */
+ public static final String KEY_NR_ADVANCED_THRESHOLD_BANDWIDTH_KHZ_INT =
+ "nr_advanced_threshold_bandwidth_khz_int";
+
+ /**
* The string is used to filter redundant string from PLMN Network Name that's supplied by
* specific carrier.
*
@@ -3550,6 +3564,17 @@
"nr_advanced_capable_pco_id_int";
/**
+ * Enabled NR advanced (i.e. 5G+) icon while roaming. The default value is {@code true}, meaming
+ * the same NR advanced logic used for home network will be used for roaming network as well.
+ * Set this to {@code false} will disable NR advanced icon while the device is roaming,
+ * regardless meeting NR advanced criteria or not.
+ *
+ * @hide
+ */
+ public static final String KEY_ENABLE_NR_ADVANCED_WHILE_ROAMING_BOOL =
+ "enable_nr_advanced_for_roaming_bool";
+
+ /**
* This configuration allows the framework to use user data communication to detect Idle state,
* and this is used on the 5G icon.
*
@@ -5227,6 +5252,16 @@
public static final String KEY_VONR_SETTING_VISIBILITY_BOOL = "vonr_setting_visibility_bool";
/**
+ * Flag specifying whether VoNR should be enabled for carrier.
+ * If true, VoNr will be enabled. If false, hard disabled.
+ *
+ * Disabled by default.
+ *
+ * @hide
+ */
+ public static final String KEY_VONR_ENABLED_BOOL = "vonr_enabled_bool";
+
+ /**
* Determine whether unthrottle data retry when tracking area code (TAC/LAC) from cell changes
*
* @hide
@@ -5622,6 +5657,7 @@
sDefaults.putString(KEY_SHOW_CARRIER_DATA_ICON_PATTERN_STRING, "");
sDefaults.putBoolean(KEY_HIDE_LTE_PLUS_DATA_ICON_BOOL, true);
sDefaults.putInt(KEY_LTE_PLUS_THRESHOLD_BANDWIDTH_KHZ_INT, 20000);
+ sDefaults.putInt(KEY_NR_ADVANCED_THRESHOLD_BANDWIDTH_KHZ_INT, 0);
sDefaults.putIntArray(KEY_CARRIER_NR_AVAILABILITIES_INT_ARRAY,
new int[]{CARRIER_NR_AVAILABILITY_NSA, CARRIER_NR_AVAILABILITY_SA});
sDefaults.putBoolean(KEY_LTE_ENABLED_BOOL, true);
@@ -5717,6 +5753,7 @@
sDefaults.putLong(KEY_5G_WATCHDOG_TIME_MS_LONG, 3600000);
sDefaults.putIntArray(KEY_ADDITIONAL_NR_ADVANCED_BANDS_INT_ARRAY, new int[0]);
sDefaults.putInt(KEY_NR_ADVANCED_CAPABLE_PCO_ID_INT, 0);
+ sDefaults.putBoolean(KEY_ENABLE_NR_ADVANCED_WHILE_ROAMING_BOOL, true);
sDefaults.putBoolean(KEY_LTE_ENDC_USING_USER_DATA_FOR_RRC_DETECTION_BOOL, false);
sDefaults.putBoolean(KEY_UNMETERED_NR_NSA_BOOL, false);
sDefaults.putBoolean(KEY_UNMETERED_NR_NSA_MMWAVE_BOOL, false);
@@ -5856,6 +5893,7 @@
sDefaults.putBoolean(KEY_DISPLAY_NO_DATA_NOTIFICATION_ON_PERMANENT_FAILURE_BOOL, false);
sDefaults.putBoolean(KEY_UNTHROTTLE_DATA_RETRY_WHEN_TAC_CHANGES_BOOL, false);
sDefaults.putBoolean(KEY_VONR_SETTING_VISIBILITY_BOOL, false);
+ sDefaults.putBoolean(KEY_VONR_ENABLED_BOOL, false);
}
/**
diff --git a/telephony/java/android/telephony/SubscriptionManager.java b/telephony/java/android/telephony/SubscriptionManager.java
index 3b44a34..d5315ac 100644
--- a/telephony/java/android/telephony/SubscriptionManager.java
+++ b/telephony/java/android/telephony/SubscriptionManager.java
@@ -949,6 +949,15 @@
public static final String VOIMS_OPT_IN_STATUS = SimInfo.COLUMN_VOIMS_OPT_IN_STATUS;
/**
+ * TelephonyProvider column name for NR Advanced calling
+ * Determines if the user has enabled VoNR settings for this subscription.
+ *
+ * @hide
+ */
+ public static final String NR_ADVANCED_CALLING_ENABLED =
+ SimInfo.COLUMN_NR_ADVANCED_CALLING_ENABLED;
+
+ /**
* Profile class of the subscription
* @hide
*/
diff --git a/telephony/java/android/telephony/TelephonyManager.java b/telephony/java/android/telephony/TelephonyManager.java
index a4afea1..9c52220 100644
--- a/telephony/java/android/telephony/TelephonyManager.java
+++ b/telephony/java/android/telephony/TelephonyManager.java
@@ -2951,7 +2951,12 @@
* currently in use on the device for data transmission.
*
* If this object has been created with {@link #createForSubscriptionId}, applies to the given
- * subId. Otherwise, applies to {@link SubscriptionManager#getDefaultDataSubscriptionId()}
+ * subId. Otherwise, applies to {@link SubscriptionManager#getActiveDataSubscriptionId()}.
+ *
+ * Note: Before {@link SubscriptionManager#getActiveDataSubscriptionId()} was introduced in API
+ * level 30, it was applied to {@link SubscriptionManager#getDefaultDataSubscriptionId()} which
+ * may be different now from {@link SubscriptionManager#getActiveDataSubscriptionId()}, e.g.
+ * when opportunistic network is providing cellular internet connection to the user.
*
* <p>Requires Permission: {@link android.Manifest.permission#READ_PHONE_STATE READ_PHONE_STATE}
* or that the calling app has carrier privileges (see {@link #hasCarrierPrivileges}).
diff --git a/telephony/java/android/telephony/TelephonyScanManager.java b/telephony/java/android/telephony/TelephonyScanManager.java
index e890acb..9572154 100644
--- a/telephony/java/android/telephony/TelephonyScanManager.java
+++ b/telephony/java/android/telephony/TelephonyScanManager.java
@@ -36,6 +36,7 @@
import java.util.Arrays;
import java.util.List;
+import java.util.Objects;
import java.util.concurrent.Executor;
/**
@@ -152,16 +153,9 @@
throw new RuntimeException(
"Failed to find NetworkScanInfo with id " + message.arg2);
}
- NetworkScanCallback callback = nsi.mCallback;
- Executor executor = nsi.mExecutor;
- if (callback == null) {
- throw new RuntimeException(
- "Failed to find NetworkScanCallback with id " + message.arg2);
- }
- if (executor == null) {
- throw new RuntimeException(
- "Failed to find Executor with id " + message.arg2);
- }
+
+ final NetworkScanCallback callback = nsi.mCallback;
+ final Executor executor = nsi.mExecutor;
switch (message.what) {
case CALLBACK_RESTRICTED_SCAN_RESULTS:
@@ -246,17 +240,24 @@
NetworkScanRequest request, Executor executor, NetworkScanCallback callback,
String callingPackage, @Nullable String callingFeatureId) {
try {
+ Objects.requireNonNull(request, "Request was null");
+ Objects.requireNonNull(callback, "Callback was null");
+ Objects.requireNonNull(executor, "Executor was null");
final ITelephony telephony = getITelephony();
if (telephony == null) return null;
- int scanId = telephony.requestNetworkScan(
- subId, request, mMessenger, new Binder(), callingPackage,
- callingFeatureId);
- if (scanId == INVALID_SCAN_ID) {
- Rlog.e(TAG, "Failed to initiate network scan");
- return null;
- }
+ // The lock must be taken before calling requestNetworkScan because the resulting
+ // scanId can be invoked asynchronously on another thread at any time after
+ // requestNetworkScan invoked, leaving a critical section between that call and adding
+ // the record to the ScanInfo cache.
synchronized (mScanInfo) {
+ int scanId = telephony.requestNetworkScan(
+ subId, request, mMessenger, new Binder(), callingPackage,
+ callingFeatureId);
+ if (scanId == INVALID_SCAN_ID) {
+ Rlog.e(TAG, "Failed to initiate network scan");
+ return null;
+ }
// We link to death whenever a scan is started to ensure that we are linked
// at the point that phone process death might matter.
// We never unlink because:
diff --git a/tests/DynamicCodeLoggerIntegrationTests/OWNERS b/tests/DynamicCodeLoggerIntegrationTests/OWNERS
new file mode 100644
index 0000000..d9eb141
--- /dev/null
+++ b/tests/DynamicCodeLoggerIntegrationTests/OWNERS
@@ -0,0 +1 @@
+file:/services/core/java/com/android/server/pm/dex/OWNERS
diff --git a/tests/FlickerTests/src/com/android/server/wm/flicker/close/CloseAppTransition.kt b/tests/FlickerTests/src/com/android/server/wm/flicker/close/CloseAppTransition.kt
index 5aa1e27..339a5bd 100644
--- a/tests/FlickerTests/src/com/android/server/wm/flicker/close/CloseAppTransition.kt
+++ b/tests/FlickerTests/src/com/android/server/wm/flicker/close/CloseAppTransition.kt
@@ -197,7 +197,7 @@
testSpec.replacesLayer(testApp.component, LAUNCHER_COMPONENT)
}
- @Postsubmit
+ @Presubmit
@Test
fun runPresubmitAssertion() {
flickerRule.checkPresubmitAssertions()
diff --git a/tests/FlickerTests/src/com/android/server/wm/flicker/launch/OpenAppColdTest.kt b/tests/FlickerTests/src/com/android/server/wm/flicker/launch/OpenAppColdTest.kt
index be919cd..2f5a389 100644
--- a/tests/FlickerTests/src/com/android/server/wm/flicker/launch/OpenAppColdTest.kt
+++ b/tests/FlickerTests/src/com/android/server/wm/flicker/launch/OpenAppColdTest.kt
@@ -16,7 +16,6 @@
package com.android.server.wm.flicker.launch
-import android.platform.test.annotations.Postsubmit
import android.platform.test.annotations.Presubmit
import androidx.test.filters.FlakyTest
import androidx.test.filters.RequiresDevice
@@ -88,12 +87,12 @@
}
/** {@inheritDoc} */
- @Postsubmit
+ @Presubmit
@Test
override fun appLayerReplacesLauncher() = super.appLayerReplacesLauncher()
/** {@inheritDoc} */
- @Postsubmit
+ @Presubmit
@Test
override fun appWindowReplacesLauncherAsTopWindow() =
super.appWindowReplacesLauncherAsTopWindow()
diff --git a/tests/FlickerTests/src/com/android/server/wm/flicker/launch/OpenAppNonResizeableTest.kt b/tests/FlickerTests/src/com/android/server/wm/flicker/launch/OpenAppNonResizeableTest.kt
index cf10c53..ad0da5b 100644
--- a/tests/FlickerTests/src/com/android/server/wm/flicker/launch/OpenAppNonResizeableTest.kt
+++ b/tests/FlickerTests/src/com/android/server/wm/flicker/launch/OpenAppNonResizeableTest.kt
@@ -203,7 +203,7 @@
* Checks that the screen is locked at the start of the transition ([colorFadComponent])
* layer is visible
*/
- @Postsubmit
+ @Presubmit
@Test
fun screenLockedStart() {
testSpec.assertLayersStart {
@@ -216,7 +216,7 @@
* it cannot use the regular assertion (check over time), because on lock screen neither
* the app not the launcher are visible, and there is no top visible window.
*/
- @Postsubmit
+ @Presubmit
@Test
override fun appWindowReplacesLauncherAsTopWindow() {
testSpec.assertWm {
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 fd8abc6..0bde8a0 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
@@ -95,7 +95,7 @@
}
}
- @Postsubmit
+ @Presubmit
@Test
fun runPresubmitAssertion() {
flickerRule.checkPresubmitAssertions()
diff --git a/tests/RollbackTest/RollbackTest/src/com/android/tests/rollback/StagedRollbackTest.java b/tests/RollbackTest/RollbackTest/src/com/android/tests/rollback/StagedRollbackTest.java
index ffc8f47..bb4866f 100644
--- a/tests/RollbackTest/RollbackTest/src/com/android/tests/rollback/StagedRollbackTest.java
+++ b/tests/RollbackTest/RollbackTest/src/com/android/tests/rollback/StagedRollbackTest.java
@@ -256,10 +256,7 @@
// verify rollback
assertThat(InstallUtils.getInstalledVersion(packageName)).isEqualTo(2);
- RollbackManager rm = RollbackUtils.getRollbackManager();
- RollbackInfo rollback = getUniqueRollbackInfoForPackage(
- rm.getAvailableRollbacks(), packageName);
- assertThat(rollback).isNotNull();
+ RollbackInfo rollback = RollbackUtils.waitForAvailableRollback(packageName);
assertThat(rollback).packagesContainsExactly(Rollback.from(apex2).to(apex1));
assertThat(rollback).isNotStaged();
diff --git a/tests/SharedLibraryLoadingTest/Android.bp b/tests/SharedLibraryLoadingTest/Android.bp
new file mode 100644
index 0000000..088278d
--- /dev/null
+++ b/tests/SharedLibraryLoadingTest/Android.bp
@@ -0,0 +1,37 @@
+// Copyright (C) 2021 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 {
+ // See: http://go/android-license-faq
+ // A large-scale-change added 'default_applicable_licenses' to import
+ // all of the 'license_kinds' from "frameworks_base_license"
+ // to get the below license kinds:
+ // SPDX-license-identifier-Apache-2.0
+ default_applicable_licenses: ["frameworks_base_license"],
+}
+
+java_test_host {
+ name: "SharedLibraryLoadingTests",
+ libs: [
+ "tradefed",
+ "junit",
+ ],
+ test_suites: ["general-tests"],
+ data: [
+ ":SharedLibraryLoadingTests_StandardSharedLibrary",
+ ":SharedLibraryLoadingTests_SharedLibraryLoadedAfter",
+ ":SharedLibraryLoadingTests_SharedLibraryClientTests",
+ ":SharedLibraryLoadingTests_Overlay",
+ ],
+}
diff --git a/tests/SharedLibraryLoadingTest/AndroidTest.xml b/tests/SharedLibraryLoadingTest/AndroidTest.xml
new file mode 100644
index 0000000..947453d
--- /dev/null
+++ b/tests/SharedLibraryLoadingTest/AndroidTest.xml
@@ -0,0 +1,45 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ ~ Copyright (C) 2021 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.
+ -->
+
+<configuration description="Host-driven test module config for SharedLibraryHostTests">
+ <option name="test-tag" value="SharedLibraryLoadingTests" />
+ <option name="test-suite-tag" value="apct" />
+ <option name="test-suite-tag" value="apct-instrumentation" />
+
+ <target_preparer class="com.android.tradefed.targetprep.RootTargetPreparer" />
+ <target_preparer class="com.android.compatibility.common.tradefed.targetprep.FilePusher">
+ <option name="cleanup" value="false" />
+ <option name="remount-system" value="true" />
+ <option name="push"
+ value="SharedLibraryLoadingTests_StandardSharedLibrary.apk->/product/app/SharedLibraryLoadingTests_StandardSharedLibrary.apk" />
+ <option name="push"
+ value="SharedLibraryLoadingTests_SharedLibraryLoadedAfter.apk->/product/app/SharedLibraryLoadingTests_SharedLibraryLoadedAfter.apk" />
+ <option name="push"
+ value="SharedLibraryLoadingTests_Overlay.apk->/product/overlay/SharedLibraryLoadingTests_Overlay.apk" />
+ </target_preparer>
+
+ <target_preparer class="com.android.tradefed.targetprep.RebootTargetPreparer" />
+
+ <target_preparer class="com.android.tradefed.targetprep.TestAppInstallSetup">
+ <option name="cleanup-apks" value="true" />
+ <option name="test-file-name" value="SharedLibraryLoadingTests_SharedLibraryClientTests.apk" />
+ </target_preparer>
+
+ <test class="com.android.tradefed.testtype.AndroidJUnitTest">
+ <option name="package" value="com.android.sharedlibloadingtest.client" />
+ </test>
+</configuration>
\ No newline at end of file
diff --git a/tests/SharedLibraryLoadingTest/OWNERS b/tests/SharedLibraryLoadingTest/OWNERS
new file mode 100644
index 0000000..d7b4569
--- /dev/null
+++ b/tests/SharedLibraryLoadingTest/OWNERS
@@ -0,0 +1,2 @@
+stenning@google.com
+
diff --git a/tests/SharedLibraryLoadingTest/test-apps/Overlay/Android.bp b/tests/SharedLibraryLoadingTest/test-apps/Overlay/Android.bp
new file mode 100644
index 0000000..b2f4e89
--- /dev/null
+++ b/tests/SharedLibraryLoadingTest/test-apps/Overlay/Android.bp
@@ -0,0 +1,29 @@
+// Copyright (C) 2021 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 {
+ // See: http://go/android-license-faq
+ // A large-scale-change added 'default_applicable_licenses' to import
+ // all of the 'license_kinds' from "frameworks_base_license"
+ // to get the below license kinds:
+ // SPDX-license-identifier-Apache-2.0
+ default_applicable_licenses: ["frameworks_base_license"],
+}
+
+android_test_helper_app {
+ name: "SharedLibraryLoadingTests_Overlay",
+ platform_apis: true,
+ certificate: "platform",
+ aaptflags: ["--no-resource-removal"],
+}
diff --git a/packages/SystemUI/res/color/prv_color_surface.xml b/tests/SharedLibraryLoadingTest/test-apps/Overlay/AndroidManifest.xml
similarity index 68%
copy from packages/SystemUI/res/color/prv_color_surface.xml
copy to tests/SharedLibraryLoadingTest/test-apps/Overlay/AndroidManifest.xml
index b9d016c..ae2784c 100644
--- a/packages/SystemUI/res/color/prv_color_surface.xml
+++ b/tests/SharedLibraryLoadingTest/test-apps/Overlay/AndroidManifest.xml
@@ -14,7 +14,11 @@
~ See the License for the specific language governing permissions and
~ limitations under the License.
-->
-<selector xmlns:androidprv="http://schemas.android.com/apk/prv/res/android"
- xmlns:android="http://schemas.android.com/apk/res/android">
- <item android:color="?androidprv:attr/colorSurface" />
-</selector>
\ No newline at end of file
+
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+ package="com.android.sharedlibloadingtest.overlay">
+ <application android:hasCode="false" />
+ <overlay android:targetPackage="android"
+ android:isStatic="true"
+ android:priority="1"/>
+</manifest>
\ No newline at end of file
diff --git a/packages/SystemUI/res/values/arrays_tv.xml b/tests/SharedLibraryLoadingTest/test-apps/Overlay/res/values/config.xml
similarity index 76%
rename from packages/SystemUI/res/values/arrays_tv.xml
rename to tests/SharedLibraryLoadingTest/test-apps/Overlay/res/values/config.xml
index 9c77077..15da3db 100644
--- a/packages/SystemUI/res/values/arrays_tv.xml
+++ b/tests/SharedLibraryLoadingTest/test-apps/Overlay/res/values/config.xml
@@ -1,7 +1,7 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
-/**
- * Copyright (c) 2017, The Android Open Source Project
+/*
+ * Copyright (C) 2020 Google Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -17,6 +17,7 @@
*/
-->
<resources>
- <string-array name="audio_recording_disclosure_exempt_apps" translatable="false">
+ <string-array name="config_sharedLibrariesLoadedAfterApp" translatable="false">
+ <item>com.android.sharedlibloadingtest.shared_library_after</item>
</string-array>
-</resources>
+</resources>
\ No newline at end of file
diff --git a/tests/SharedLibraryLoadingTest/test-apps/SharedLibraryClientTests/Android.bp b/tests/SharedLibraryLoadingTest/test-apps/SharedLibraryClientTests/Android.bp
new file mode 100644
index 0000000..0d20497
--- /dev/null
+++ b/tests/SharedLibraryLoadingTest/test-apps/SharedLibraryClientTests/Android.bp
@@ -0,0 +1,35 @@
+// Copyright (C) 2021 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"],
+}
+
+android_test_helper_app {
+ name: "SharedLibraryLoadingTests_SharedLibraryClientTests",
+ srcs: ["**/*.java"],
+ resource_dirs: ["res"],
+ libs: [
+ "SharedLibraryLoadingTests_StandardSharedLibrary",
+ "SharedLibraryLoadingTests_SharedLibraryLoadedAfter",
+ "android.test.base",
+ ],
+ static_libs: [
+ "androidx.test.ext.junit",
+ "androidx.test.rules",
+ "androidx.test.core",
+ "testng",
+ ],
+ platform_apis: true,
+}
diff --git a/tests/SharedLibraryLoadingTest/test-apps/SharedLibraryClientTests/AndroidManifest.xml b/tests/SharedLibraryLoadingTest/test-apps/SharedLibraryClientTests/AndroidManifest.xml
new file mode 100644
index 0000000..e3a9b9b
--- /dev/null
+++ b/tests/SharedLibraryLoadingTest/test-apps/SharedLibraryClientTests/AndroidManifest.xml
@@ -0,0 +1,29 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ ~ Copyright (C) 2021 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 xmlns:android="http://schemas.android.com/apk/res/android"
+ package="com.android.sharedlibloadingtest.client">
+ <application>
+ <uses-library android:name="android.test.runner" />
+ <uses-library android:name="com.android.sharedlibloadingtest.shared_library"/>
+ <uses-library android:name="com.android.sharedlibloadingtest.shared_library_after"/>
+ </application>
+
+ <instrumentation
+ android:name="androidx.test.runner.AndroidJUnitRunner"
+ android:targetPackage="com.android.sharedlibloadingtest.client" />
+</manifest>
\ No newline at end of file
diff --git a/packages/SystemUI/res/transition/tv_privacy_chip_expand.xml b/tests/SharedLibraryLoadingTest/test-apps/SharedLibraryClientTests/res/values/values.xml
similarity index 80%
copy from packages/SystemUI/res/transition/tv_privacy_chip_expand.xml
copy to tests/SharedLibraryLoadingTest/test-apps/SharedLibraryClientTests/res/values/values.xml
index 059ebc8..5e0544e 100644
--- a/packages/SystemUI/res/transition/tv_privacy_chip_expand.xml
+++ b/tests/SharedLibraryLoadingTest/test-apps/SharedLibraryClientTests/res/values/values.xml
@@ -14,7 +14,7 @@
~ See the License for the specific language governing permissions and
~ limitations under the License.
-->
-<transitionSet xmlns:android="http://schemas.android.com/apk/res/android">
- <changeBounds/>
- <fade android:fadingMode="fade_out" />
-</transitionSet>
+
+<resources>
+ <string name="identical_resource_key">client value</string>
+</resources>
\ No newline at end of file
diff --git a/core/java/android/companion/Association.aidl b/tests/SharedLibraryLoadingTest/test-apps/SharedLibraryClientTests/src/com/android/sharedlibloadingtest/ClientClass.java
similarity index 72%
copy from core/java/android/companion/Association.aidl
copy to tests/SharedLibraryLoadingTest/test-apps/SharedLibraryClientTests/src/com/android/sharedlibloadingtest/ClientClass.java
index 2a28f1f..e48fb83 100644
--- a/core/java/android/companion/Association.aidl
+++ b/tests/SharedLibraryLoadingTest/test-apps/SharedLibraryClientTests/src/com/android/sharedlibloadingtest/ClientClass.java
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2019 The Android Open Source Project
+ * Copyright (C) 2021 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.
@@ -13,6 +13,12 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-package android.companion;
-parcelable Association;
+package com.android.sharedlibloadingtest;
+
+public class ClientClass {
+ @Override
+ public String toString() {
+ return "Client Code";
+ }
+}
diff --git a/core/java/android/companion/Association.aidl b/tests/SharedLibraryLoadingTest/test-apps/SharedLibraryClientTests/src/com/android/sharedlibloadingtest/DuplicateClassA.java
similarity index 71%
copy from core/java/android/companion/Association.aidl
copy to tests/SharedLibraryLoadingTest/test-apps/SharedLibraryClientTests/src/com/android/sharedlibloadingtest/DuplicateClassA.java
index 2a28f1f..4c77155 100644
--- a/core/java/android/companion/Association.aidl
+++ b/tests/SharedLibraryLoadingTest/test-apps/SharedLibraryClientTests/src/com/android/sharedlibloadingtest/DuplicateClassA.java
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2019 The Android Open Source Project
+ * Copyright (C) 2021 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.
@@ -13,6 +13,12 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-package android.companion;
-parcelable Association;
+package com.android.sharedlibloadingtest;
+
+public class DuplicateClassA {
+ @Override
+ public String toString() {
+ return "Client's Version";
+ }
+}
diff --git a/core/java/android/companion/Association.aidl b/tests/SharedLibraryLoadingTest/test-apps/SharedLibraryClientTests/src/com/android/sharedlibloadingtest/DuplicateClassB.java
similarity index 71%
copy from core/java/android/companion/Association.aidl
copy to tests/SharedLibraryLoadingTest/test-apps/SharedLibraryClientTests/src/com/android/sharedlibloadingtest/DuplicateClassB.java
index 2a28f1f..86aa6a1 100644
--- a/core/java/android/companion/Association.aidl
+++ b/tests/SharedLibraryLoadingTest/test-apps/SharedLibraryClientTests/src/com/android/sharedlibloadingtest/DuplicateClassB.java
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2019 The Android Open Source Project
+ * Copyright (C) 2021 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.
@@ -13,6 +13,12 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-package android.companion;
-parcelable Association;
+package com.android.sharedlibloadingtest;
+
+public class DuplicateClassB {
+ @Override
+ public String toString() {
+ return "Client's Version B";
+ }
+}
diff --git a/tests/SharedLibraryLoadingTest/test-apps/SharedLibraryClientTests/src/com/android/sharedlibloadingtest/client/SharedLibraryLoadingOrderTest.java b/tests/SharedLibraryLoadingTest/test-apps/SharedLibraryClientTests/src/com/android/sharedlibloadingtest/client/SharedLibraryLoadingOrderTest.java
new file mode 100644
index 0000000..43bcb1a
--- /dev/null
+++ b/tests/SharedLibraryLoadingTest/test-apps/SharedLibraryClientTests/src/com/android/sharedlibloadingtest/client/SharedLibraryLoadingOrderTest.java
@@ -0,0 +1,90 @@
+/*
+ * Copyright (C) 2021 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.sharedlibloadingtest.client;
+
+import static org.testng.Assert.assertEquals;
+
+import android.content.Context;
+import android.content.res.Resources;
+
+import androidx.test.core.app.ApplicationProvider;
+import androidx.test.ext.junit.runners.AndroidJUnit4;
+
+import com.android.internal.util.Preconditions;
+import com.android.sharedlibloadingtest.ClientClass;
+import com.android.sharedlibloadingtest.DuplicateClassA;
+import com.android.sharedlibloadingtest.DuplicateClassB;
+import com.android.sharedlibloadingtest.SharedClassAfter;
+import com.android.sharedlibloadingtest.StdSharedClass;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+import java.util.Collections;
+import java.util.HashSet;
+
+@RunWith(AndroidJUnit4.class)
+public class SharedLibraryLoadingOrderTest {
+
+ @Test
+ public void testLoadingOfStdShareLibsShouldBeFirst() {
+ Preconditions.checkArgument(!getLibsLoadedAfter()
+ .contains("com.android.sharedlibloadingtest.shared_library"));
+ DuplicateClassA clazz = new DuplicateClassA();
+ assertEquals(clazz.toString(), "Standard Shared Lib's Version");
+
+ StdSharedClass stdSharedClass = new StdSharedClass();
+ assertEquals(stdSharedClass.toString(), "Nothing Special Lib");
+
+ ClientClass clientCode = new ClientClass();
+ assertEquals(clientCode.toString(), "Client Code");
+ }
+
+ @Test
+ public void testLoadingOfShareLibsIsAfter() {
+ Preconditions.checkArgument(getLibsLoadedAfter()
+ .contains("com.android.sharedlibloadingtest.shared_library_after"));
+ DuplicateClassB clazz = new DuplicateClassB();
+ assertEquals(clazz.toString(), "Client's Version B");
+
+ SharedClassAfter stdSharedClass = new SharedClassAfter();
+ assertEquals(stdSharedClass.toString(), "Also Nothing Special");
+
+ ClientClass clientCode = new ClientClass();
+ assertEquals(clientCode.toString(), "Client Code");
+ }
+
+ @Test
+ public void testLoadingOfResource() {
+ // aapt compiler gives each lib their own namespace so this test just confirming
+ // the resources can be loaded from the same context object
+ Context context = ApplicationProvider.getApplicationContext();
+ String clientString = context.getResources().getString(R.string.identical_resource_key);
+ assertEquals(clientString, "client value");
+ assertEquals(StdSharedClass.getResString(context), "std lib value");
+ assertEquals(SharedClassAfter.getResString(context), "loaded after value");
+
+ }
+
+ private HashSet<String> getLibsLoadedAfter() {
+ Resources systemR = Resources.getSystem();
+ HashSet<String> libsToLoadAfter = new HashSet<>();
+ Collections.addAll(libsToLoadAfter, systemR.getStringArray(
+ com.android.internal.R.array.config_sharedLibrariesLoadedAfterApp));
+ return libsToLoadAfter;
+ }
+}
diff --git a/tests/SharedLibraryLoadingTest/test-apps/SharedLibraryLoadedAfter/Android.bp b/tests/SharedLibraryLoadingTest/test-apps/SharedLibraryLoadedAfter/Android.bp
new file mode 100644
index 0000000..db9b3ed
--- /dev/null
+++ b/tests/SharedLibraryLoadingTest/test-apps/SharedLibraryLoadedAfter/Android.bp
@@ -0,0 +1,30 @@
+// Copyright (C) 2021 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 {
+ // See: http://go/android-license-faq
+ // A large-scale-change added 'default_applicable_licenses' to import
+ // all of the 'license_kinds' from "frameworks_base_license"
+ // to get the below license kinds:
+ // SPDX-license-identifier-Apache-2.0
+ default_applicable_licenses: ["frameworks_base_license"],
+}
+
+android_test_helper_app {
+ name: "SharedLibraryLoadingTests_SharedLibraryLoadedAfter",
+ srcs: ["**/*.java"],
+ resource_dirs: ["res"],
+ sdk_version: "current",
+ aaptflags: ["--shared-lib"],
+}
diff --git a/packages/SystemUI/res/color/prv_color_surface.xml b/tests/SharedLibraryLoadingTest/test-apps/SharedLibraryLoadedAfter/AndroidManifest.xml
similarity index 69%
copy from packages/SystemUI/res/color/prv_color_surface.xml
copy to tests/SharedLibraryLoadingTest/test-apps/SharedLibraryLoadedAfter/AndroidManifest.xml
index b9d016c..efedfcf 100644
--- a/packages/SystemUI/res/color/prv_color_surface.xml
+++ b/tests/SharedLibraryLoadingTest/test-apps/SharedLibraryLoadedAfter/AndroidManifest.xml
@@ -14,7 +14,10 @@
~ See the License for the specific language governing permissions and
~ limitations under the License.
-->
-<selector xmlns:androidprv="http://schemas.android.com/apk/prv/res/android"
- xmlns:android="http://schemas.android.com/apk/res/android">
- <item android:color="?androidprv:attr/colorSurface" />
-</selector>
\ No newline at end of file
+
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+ package="com.android.sharedlibloadingtest.shared_library_after">
+ <application>
+ <library android:name="com.android.sharedlibloadingtest.shared_library_after" />
+ </application>
+</manifest>
\ No newline at end of file
diff --git a/packages/SystemUI/res/transition/tv_privacy_chip_expand.xml b/tests/SharedLibraryLoadingTest/test-apps/SharedLibraryLoadedAfter/res/values/values.xml
similarity index 80%
rename from packages/SystemUI/res/transition/tv_privacy_chip_expand.xml
rename to tests/SharedLibraryLoadingTest/test-apps/SharedLibraryLoadedAfter/res/values/values.xml
index 059ebc8..4525944 100644
--- a/packages/SystemUI/res/transition/tv_privacy_chip_expand.xml
+++ b/tests/SharedLibraryLoadingTest/test-apps/SharedLibraryLoadedAfter/res/values/values.xml
@@ -14,7 +14,7 @@
~ See the License for the specific language governing permissions and
~ limitations under the License.
-->
-<transitionSet xmlns:android="http://schemas.android.com/apk/res/android">
- <changeBounds/>
- <fade android:fadingMode="fade_out" />
-</transitionSet>
+
+<resources>
+ <string name="identical_resource_key">loaded after value</string>
+</resources>
\ No newline at end of file
diff --git a/core/java/android/companion/Association.aidl b/tests/SharedLibraryLoadingTest/test-apps/SharedLibraryLoadedAfter/src/com/android/sharedlibloadingtest/DuplicateClassB.java
similarity index 70%
copy from core/java/android/companion/Association.aidl
copy to tests/SharedLibraryLoadingTest/test-apps/SharedLibraryLoadedAfter/src/com/android/sharedlibloadingtest/DuplicateClassB.java
index 2a28f1f..1e1f5aa 100644
--- a/core/java/android/companion/Association.aidl
+++ b/tests/SharedLibraryLoadingTest/test-apps/SharedLibraryLoadedAfter/src/com/android/sharedlibloadingtest/DuplicateClassB.java
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2019 The Android Open Source Project
+ * Copyright (C) 2021 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.
@@ -13,6 +13,12 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-package android.companion;
-parcelable Association;
+package com.android.sharedlibloadingtest;
+
+public class DuplicateClassB {
+ @Override
+ public String toString() {
+ return "Loaded After Shared Lib's Version";
+ }
+}
diff --git a/tests/SharedLibraryLoadingTest/test-apps/SharedLibraryLoadedAfter/src/com/android/sharedlibloadingtest/SharedClassAfter.java b/tests/SharedLibraryLoadingTest/test-apps/SharedLibraryLoadedAfter/src/com/android/sharedlibloadingtest/SharedClassAfter.java
new file mode 100644
index 0000000..9e5b40f
--- /dev/null
+++ b/tests/SharedLibraryLoadingTest/test-apps/SharedLibraryLoadedAfter/src/com/android/sharedlibloadingtest/SharedClassAfter.java
@@ -0,0 +1,32 @@
+/*
+ * Copyright (C) 2021 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.sharedlibloadingtest;
+
+import android.content.Context;
+
+import com.android.sharedlibloadingtest.shared_library_after.R;
+
+public class SharedClassAfter {
+ @Override
+ public String toString() {
+ return "Also Nothing Special";
+ }
+
+ public static String getResString(Context context) {
+ return context.getResources().getString(R.string.identical_resource_key);
+ }
+}
diff --git a/tests/SharedLibraryLoadingTest/test-apps/StandardSharedLibrary/Android.bp b/tests/SharedLibraryLoadingTest/test-apps/StandardSharedLibrary/Android.bp
new file mode 100644
index 0000000..50456b0
--- /dev/null
+++ b/tests/SharedLibraryLoadingTest/test-apps/StandardSharedLibrary/Android.bp
@@ -0,0 +1,30 @@
+// Copyright (C) 2021 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 {
+ // See: http://go/android-license-faq
+ // A large-scale-change added 'default_applicable_licenses' to import
+ // all of the 'license_kinds' from "frameworks_base_license"
+ // to get the below license kinds:
+ // SPDX-license-identifier-Apache-2.0
+ default_applicable_licenses: ["frameworks_base_license"],
+}
+
+android_test_helper_app {
+ name: "SharedLibraryLoadingTests_StandardSharedLibrary",
+ srcs: ["**/*.java"],
+ resource_dirs: ["res"],
+ sdk_version: "current",
+ aaptflags: ["--shared-lib"],
+}
diff --git a/packages/SystemUI/res/color/prv_color_surface.xml b/tests/SharedLibraryLoadingTest/test-apps/StandardSharedLibrary/AndroidManifest.xml
similarity index 70%
rename from packages/SystemUI/res/color/prv_color_surface.xml
rename to tests/SharedLibraryLoadingTest/test-apps/StandardSharedLibrary/AndroidManifest.xml
index b9d016c..f1a079f 100644
--- a/packages/SystemUI/res/color/prv_color_surface.xml
+++ b/tests/SharedLibraryLoadingTest/test-apps/StandardSharedLibrary/AndroidManifest.xml
@@ -14,7 +14,10 @@
~ See the License for the specific language governing permissions and
~ limitations under the License.
-->
-<selector xmlns:androidprv="http://schemas.android.com/apk/prv/res/android"
- xmlns:android="http://schemas.android.com/apk/res/android">
- <item android:color="?androidprv:attr/colorSurface" />
-</selector>
\ No newline at end of file
+
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+ package="com.android.sharedlibloadingtest.shared_library">
+ <application>
+ <library android:name="com.android.sharedlibloadingtest.shared_library" />
+ </application>
+</manifest>
\ No newline at end of file
diff --git a/packages/SystemUI/res/transition/tv_privacy_chip_expand.xml b/tests/SharedLibraryLoadingTest/test-apps/StandardSharedLibrary/res/values/values.xml
similarity index 80%
copy from packages/SystemUI/res/transition/tv_privacy_chip_expand.xml
copy to tests/SharedLibraryLoadingTest/test-apps/StandardSharedLibrary/res/values/values.xml
index 059ebc8..941351a 100644
--- a/packages/SystemUI/res/transition/tv_privacy_chip_expand.xml
+++ b/tests/SharedLibraryLoadingTest/test-apps/StandardSharedLibrary/res/values/values.xml
@@ -14,7 +14,7 @@
~ See the License for the specific language governing permissions and
~ limitations under the License.
-->
-<transitionSet xmlns:android="http://schemas.android.com/apk/res/android">
- <changeBounds/>
- <fade android:fadingMode="fade_out" />
-</transitionSet>
+
+<resources>
+ <string name="identical_resource_key">std lib value</string>
+</resources>
\ No newline at end of file
diff --git a/core/java/android/companion/Association.aidl b/tests/SharedLibraryLoadingTest/test-apps/StandardSharedLibrary/src/com/android/sharedlibloadingtest/DuplicateClassA.java
similarity index 70%
copy from core/java/android/companion/Association.aidl
copy to tests/SharedLibraryLoadingTest/test-apps/StandardSharedLibrary/src/com/android/sharedlibloadingtest/DuplicateClassA.java
index 2a28f1f..a3874aa 100644
--- a/core/java/android/companion/Association.aidl
+++ b/tests/SharedLibraryLoadingTest/test-apps/StandardSharedLibrary/src/com/android/sharedlibloadingtest/DuplicateClassA.java
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2019 The Android Open Source Project
+ * Copyright (C) 2021 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.
@@ -13,6 +13,12 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-package android.companion;
-parcelable Association;
+package com.android.sharedlibloadingtest;
+
+public class DuplicateClassA {
+ @Override
+ public String toString() {
+ return "Standard Shared Lib's Version";
+ }
+}
diff --git a/tests/SharedLibraryLoadingTest/test-apps/StandardSharedLibrary/src/com/android/sharedlibloadingtest/StdSharedClass.java b/tests/SharedLibraryLoadingTest/test-apps/StandardSharedLibrary/src/com/android/sharedlibloadingtest/StdSharedClass.java
new file mode 100644
index 0000000..429d65c
--- /dev/null
+++ b/tests/SharedLibraryLoadingTest/test-apps/StandardSharedLibrary/src/com/android/sharedlibloadingtest/StdSharedClass.java
@@ -0,0 +1,32 @@
+/*
+ * Copyright (C) 2021 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.sharedlibloadingtest;
+
+import android.content.Context;
+
+import com.android.sharedlibloadingtest.shared_library.R;
+
+public class StdSharedClass {
+ @Override
+ public String toString() {
+ return "Nothing Special Lib";
+ }
+
+ public static String getResString(Context context) {
+ return context.getResources().getString(R.string.identical_resource_key);
+ }
+}
diff --git a/tools/aapt2/ResourceParser.cpp b/tools/aapt2/ResourceParser.cpp
index f49c254..792a306 100644
--- a/tools/aapt2/ResourceParser.cpp
+++ b/tools/aapt2/ResourceParser.cpp
@@ -460,8 +460,8 @@
ParsedResource parsed_resource;
parsed_resource.config = config_;
parsed_resource.source = source_.WithLine(parser->line_number());
- // NOLINTNEXTLINE(bugprone-use-after-move) move+reset comment
parsed_resource.comment = std::move(comment);
+ comment.clear();
if (options_.visibility) {
parsed_resource.visibility_level = options_.visibility.value();
}
@@ -1040,6 +1040,7 @@
.source = item_source,
.comment = std::move(comment),
});
+ comment.clear();
// Execute group specific code.
func(entry_res, next_id);
@@ -1788,8 +1789,8 @@
ParsedResource child_resource;
child_resource.name = child_ref.name.value();
child_resource.source = item_source;
- // NOLINTNEXTLINE(bugprone-use-after-move) move+reset comment
child_resource.comment = std::move(comment);
+ comment.clear();
if (options_.visibility) {
child_resource.visibility_level = options_.visibility.value();
}
diff --git a/tools/aapt2/format/binary/BinaryResourceParser.cpp b/tools/aapt2/format/binary/BinaryResourceParser.cpp
index 72eaa35..11d02f0 100644
--- a/tools/aapt2/format/binary/BinaryResourceParser.cpp
+++ b/tools/aapt2/format/binary/BinaryResourceParser.cpp
@@ -120,6 +120,13 @@
static_cast<int>(parser.chunk()->type)));
}
}
+
+ if (!staged_entries_to_remove_.empty()) {
+ diag_->Error(DiagMessage(source_) << "didn't find " << staged_entries_to_remove_.size()
+ << " original staged resources");
+ return false;
+ }
+
return true;
}
@@ -393,6 +400,12 @@
return false;
}
+ if (const auto to_remove_it = staged_entries_to_remove_.find({name, res_id});
+ to_remove_it != staged_entries_to_remove_.end()) {
+ staged_entries_to_remove_.erase(to_remove_it);
+ continue;
+ }
+
NewResourceBuilder res_builder(name);
res_builder.SetValue(std::move(resource_value), config)
.SetId(res_id, OnIdConflict::CREATE_ENTRY)
@@ -533,9 +546,8 @@
// Since a the finalized resource entry is cloned and added to the resource table under the
// staged resource id, remove the cloned resource entry from the table.
if (!table_->RemoveResource(resource_name, staged_id)) {
- diag_->Error(DiagMessage(source_) << "failed to find resource entry for staged "
- << " resource ID " << staged_id);
- return false;
+ // If we haven't seen this resource yet let's add a record to skip it when parsing.
+ staged_entries_to_remove_.insert({resource_name, staged_id});
}
}
return true;
@@ -565,6 +577,8 @@
const ResTable_map_entry* map) {
switch (name.type) {
case ResourceType::kStyle:
+ // fallthrough
+ case ResourceType::kConfigVarying: // legacy thing used in tests
return ParseStyle(name, config, map);
case ResourceType::kAttrPrivate:
// fallthrough
diff --git a/tools/aapt2/format/binary/BinaryResourceParser.h b/tools/aapt2/format/binary/BinaryResourceParser.h
index cd71d16..1c83166 100644
--- a/tools/aapt2/format/binary/BinaryResourceParser.h
+++ b/tools/aapt2/format/binary/BinaryResourceParser.h
@@ -119,6 +119,10 @@
// A mapping of resource ID to type spec flags.
std::unordered_map<ResourceId, uint32_t> entry_type_spec_flags_;
+
+ // A collection of staged resources that got finalized already and we're supposed to prune -
+ // but the original staged resource record hasn't been parsed yet.
+ std::set<std::pair<ResourceName, ResourceId>> staged_entries_to_remove_;
};
} // namespace aapt