Merge "Lint check for new broadcast receiver exported flags."
diff --git a/ProtoLibraries.bp b/ProtoLibraries.bp
index 67acfad..c12f5b4 100644
--- a/ProtoLibraries.bp
+++ b/ProtoLibraries.bp
@@ -35,7 +35,6 @@
"&& $(location soong_zip) -jar -o $(out) -C $(genDir)/$(in) -D $(genDir)/$(in)",
srcs: [
- ":framework-connectivity-protos",
":ipconnectivity-proto-src",
":libstats_atom_enum_protos",
":libstats_atom_message_protos",
@@ -68,7 +67,6 @@
" $(in)",
srcs: [
- ":framework-connectivity-protos",
":ipconnectivity-proto-src",
":libstats_atom_enum_protos",
":libstats_atom_message_protos",
@@ -84,7 +82,6 @@
java_library_host {
name: "platformprotos",
srcs: [
- ":framework-connectivity-protos",
":ipconnectivity-proto-src",
":libstats_atom_enum_protos",
":libstats_atom_message_protos",
@@ -124,7 +121,6 @@
],
sdk_version: "9",
srcs: [
- ":framework-connectivity-protos",
":ipconnectivity-proto-src",
":libstats_atom_enum_protos",
":libstats_atom_message_protos",
@@ -147,7 +143,6 @@
},
srcs: [
- ":framework-connectivity-protos",
":ipconnectivity-proto-src",
":libstats_atom_enum_protos",
":libstats_atom_message_protos",
@@ -185,7 +180,6 @@
],
srcs: [
- ":framework-connectivity-protos",
":ipconnectivity-proto-src",
":libstats_atom_enum_protos",
":libstats_atom_message_protos",
diff --git a/WEAR_OWNERS b/WEAR_OWNERS
new file mode 100644
index 0000000..4f3bc27
--- /dev/null
+++ b/WEAR_OWNERS
@@ -0,0 +1,6 @@
+yzj@google.com
+shreerag@google.com
+yeabkal@google.com
+adsule@google.com
+andriyn@google.com
+yfz@google.com
diff --git a/apex/jobscheduler/service/java/com/android/server/alarm/AlarmManagerService.java b/apex/jobscheduler/service/java/com/android/server/alarm/AlarmManagerService.java
index c0a9e67..b6d29aa 100644
--- a/apex/jobscheduler/service/java/com/android/server/alarm/AlarmManagerService.java
+++ b/apex/jobscheduler/service/java/com/android/server/alarm/AlarmManagerService.java
@@ -144,9 +144,9 @@
import com.android.server.LocalServices;
import com.android.server.SystemService;
import com.android.server.SystemServiceManager;
-import com.android.server.pm.parsing.pkg.AndroidPackage;
import com.android.server.pm.permission.PermissionManagerService;
import com.android.server.pm.permission.PermissionManagerServiceInternal;
+import com.android.server.pm.pkg.AndroidPackage;
import com.android.server.tare.AlarmManagerEconomicPolicy;
import com.android.server.tare.EconomyManagerInternal;
import com.android.server.usage.AppStandbyInternal;
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 235ce404..12ec9a4 100644
--- a/apex/jobscheduler/service/java/com/android/server/tare/Agent.java
+++ b/apex/jobscheduler/service/java/com/android/server/tare/Agent.java
@@ -822,37 +822,18 @@
@GuardedBy("mLock")
void onPackageRemovedLocked(final int userId, @NonNull final String pkgName) {
- reclaimAssetsLocked(userId, pkgName);
+ mScribe.discardLedgerLocked(userId, pkgName);
+ mCurrentOngoingEvents.delete(userId, pkgName);
mBalanceThresholdAlarmQueue.removeAlarmForKey(new Package(userId, pkgName));
}
- /**
- * Reclaims any ARCs granted to the app, making them available to other apps. Also deletes the
- * app's ledger and stops any ongoing event tracking.
- */
@GuardedBy("mLock")
- private void reclaimAssetsLocked(final int userId, @NonNull final String pkgName) {
- final Ledger ledger = mScribe.getLedgerLocked(userId, pkgName);
- if (ledger.getCurrentBalance() != 0) {
- mScribe.adjustRemainingConsumableCakesLocked(-ledger.getCurrentBalance());
- }
- mScribe.discardLedgerLocked(userId, pkgName);
- mCurrentOngoingEvents.delete(userId, pkgName);
- }
-
- @GuardedBy("mLock")
- void onUserRemovedLocked(final int userId, @NonNull final List<String> pkgNames) {
- reclaimAssetsLocked(userId, pkgNames);
+ void onUserRemovedLocked(final int userId) {
+ mScribe.discardLedgersLocked(userId);
+ mCurrentOngoingEvents.delete(userId);
mBalanceThresholdAlarmQueue.removeAlarmsForUserId(userId);
}
- @GuardedBy("mLock")
- private void reclaimAssetsLocked(final int userId, @NonNull final List<String> pkgNames) {
- for (int i = 0; i < pkgNames.size(); ++i) {
- reclaimAssetsLocked(userId, pkgNames.get(i));
- }
- }
-
@VisibleForTesting
static class TrendCalculator implements Consumer<OngoingEvent> {
static final long WILL_NOT_CROSS_THRESHOLD = -1;
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 c10a890..59d4ded 100644
--- a/apex/jobscheduler/service/java/com/android/server/tare/InternalResourceService.java
+++ b/apex/jobscheduler/service/java/com/android/server/tare/InternalResourceService.java
@@ -578,17 +578,15 @@
void onUserRemoved(final int userId) {
synchronized (mLock) {
mVipOverrides.delete(userId);
- ArrayList<String> removedPkgs = new ArrayList<>();
final int uIdx = mPkgCache.indexOfKey(userId);
if (uIdx >= 0) {
for (int p = mPkgCache.numElementsForKeyAt(uIdx) - 1; p >= 0; --p) {
final InstalledPackageInfo pkgInfo = mPkgCache.valueAt(uIdx, p);
- removedPkgs.add(pkgInfo.packageName);
mUidToPackageCache.remove(pkgInfo.uid);
}
}
mPkgCache.delete(userId);
- mAgent.onUserRemovedLocked(userId, removedPkgs);
+ mAgent.onUserRemovedLocked(userId);
}
}
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 29478d0..bd4fd72 100644
--- a/apex/jobscheduler/service/java/com/android/server/tare/Scribe.java
+++ b/apex/jobscheduler/service/java/com/android/server/tare/Scribe.java
@@ -157,6 +157,12 @@
}
@GuardedBy("mIrs.getLock()")
+ void discardLedgersLocked(final int userId) {
+ mLedgers.delete(userId);
+ postWrite();
+ }
+
+ @GuardedBy("mIrs.getLock()")
long getSatiatedConsumptionLimitLocked() {
return mSatiatedConsumptionLimit;
}
diff --git a/apex/jobscheduler/service/java/com/android/server/usage/AppStandbyController.java b/apex/jobscheduler/service/java/com/android/server/usage/AppStandbyController.java
index f1c4eb4..67d711c 100644
--- a/apex/jobscheduler/service/java/com/android/server/usage/AppStandbyController.java
+++ b/apex/jobscheduler/service/java/com/android/server/usage/AppStandbyController.java
@@ -122,7 +122,7 @@
import com.android.server.AlarmManagerInternal;
import com.android.server.JobSchedulerBackgroundThread;
import com.android.server.LocalServices;
-import com.android.server.pm.parsing.pkg.AndroidPackage;
+import com.android.server.pm.pkg.AndroidPackage;
import com.android.server.usage.AppIdleHistory.AppUsageHistory;
import libcore.util.EmptyArray;
diff --git a/core/api/current.txt b/core/api/current.txt
index 20d8a26..4d25ad7 100644
--- a/core/api/current.txt
+++ b/core/api/current.txt
@@ -16896,6 +16896,7 @@
field public static final int DATASPACE_DEPTH = 4096; // 0x1000
field public static final int DATASPACE_DISPLAY_P3 = 143261696; // 0x88a0000
field public static final int DATASPACE_DYNAMIC_DEPTH = 4098; // 0x1002
+ field public static final int DATASPACE_HEIF = 4100; // 0x1004
field public static final int DATASPACE_JFIF = 146931712; // 0x8c20000
field public static final int DATASPACE_SCRGB = 411107328; // 0x18810000
field public static final int DATASPACE_SCRGB_LINEAR = 406913024; // 0x18410000
@@ -53160,7 +53161,9 @@
method @Nullable public String getFallbackText();
field public static final int GESTURE_TYPE_DELETE = 4; // 0x4
field public static final int GESTURE_TYPE_INSERT = 2; // 0x2
+ field public static final int GESTURE_TYPE_JOIN_OR_SPLIT = 16; // 0x10
field public static final int GESTURE_TYPE_NONE = 0; // 0x0
+ field public static final int GESTURE_TYPE_REMOVE_SPACE = 8; // 0x8
field public static final int GESTURE_TYPE_SELECT = 1; // 0x1
field public static final int GRANULARITY_CHARACTER = 2; // 0x2
field public static final int GRANULARITY_WORD = 1; // 0x1
@@ -53501,6 +53504,35 @@
method @NonNull public android.view.inputmethod.InsertGesture.Builder setTextToInsert(@NonNull String);
}
+ public final class JoinOrSplitGesture extends android.view.inputmethod.HandwritingGesture implements android.os.Parcelable {
+ method public int describeContents();
+ method @NonNull public android.graphics.PointF getJoinOrSplitPoint();
+ method public void writeToParcel(@NonNull android.os.Parcel, int);
+ field @NonNull public static final android.os.Parcelable.Creator<android.view.inputmethod.JoinOrSplitGesture> CREATOR;
+ }
+
+ public static final class JoinOrSplitGesture.Builder {
+ ctor public JoinOrSplitGesture.Builder();
+ method @NonNull public android.view.inputmethod.JoinOrSplitGesture build();
+ method @NonNull public android.view.inputmethod.JoinOrSplitGesture.Builder setFallbackText(@Nullable String);
+ method @NonNull public android.view.inputmethod.JoinOrSplitGesture.Builder setJoinOrSplitPoint(@NonNull android.graphics.PointF);
+ }
+
+ public final class RemoveSpaceGesture extends android.view.inputmethod.HandwritingGesture implements android.os.Parcelable {
+ method public int describeContents();
+ method @NonNull public android.graphics.PointF getEndPoint();
+ method @NonNull public android.graphics.PointF getStartPoint();
+ method public void writeToParcel(@NonNull android.os.Parcel, int);
+ field @NonNull public static final android.os.Parcelable.Creator<android.view.inputmethod.RemoveSpaceGesture> CREATOR;
+ }
+
+ public static final class RemoveSpaceGesture.Builder {
+ ctor public RemoveSpaceGesture.Builder();
+ method @NonNull public android.view.inputmethod.RemoveSpaceGesture build();
+ method @NonNull public android.view.inputmethod.RemoveSpaceGesture.Builder setFallbackText(@Nullable String);
+ method @NonNull public android.view.inputmethod.RemoveSpaceGesture.Builder setPoints(@NonNull android.graphics.PointF, @NonNull android.graphics.PointF);
+ }
+
public final class SelectGesture extends android.view.inputmethod.HandwritingGesture implements android.os.Parcelable {
method public int describeContents();
method public int getGranularity();
diff --git a/core/api/test-current.txt b/core/api/test-current.txt
index 8c53733..deb5aca 100644
--- a/core/api/test-current.txt
+++ b/core/api/test-current.txt
@@ -2160,10 +2160,15 @@
field public static final String NAMESPACE_APP_COMPAT_OVERRIDES = "app_compat_overrides";
field public static final String NAMESPACE_CONSTRAIN_DISPLAY_APIS = "constrain_display_apis";
field public static final String NAMESPACE_DEVICE_IDLE = "device_idle";
+ field public static final String NAMESPACE_INPUT_METHOD_MANAGER = "input_method_manager";
field public static final String NAMESPACE_JOB_SCHEDULER = "jobscheduler";
field public static final String NAMESPACE_SELECTION_TOOLBAR = "selection_toolbar";
}
+ public interface InputMethodManagerDeviceConfig {
+ field public static final String KEY_HIDE_IME_WHEN_NO_EDITOR_FOCUS = "hide_ime_when_no_editor_focus";
+ }
+
public final class Settings {
field public static final int RESET_MODE_PACKAGE_DEFAULTS = 1; // 0x1
}
diff --git a/core/java/android/hardware/DataSpace.java b/core/java/android/hardware/DataSpace.java
index 01ed132..6c42776 100644
--- a/core/java/android/hardware/DataSpace.java
+++ b/core/java/android/hardware/DataSpace.java
@@ -410,6 +410,22 @@
/** @hide */
@Retention(RetentionPolicy.SOURCE)
@IntDef(flag = true, value = {
+ DATASPACE_HEIF,
+ })
+ public @interface DataSpaceFileFormat {};
+
+ /**
+ * High Efficiency Image File Format (HEIF).
+ *
+ * <p>This value is valid with {@link android.hardware.HardwareBuffer#BLOB HardwareBuffer.BLOB}
+ * format. The combination is an HEIC image encoded by HEIC or HEVC encoder according to
+ * ISO/IEC 23008-12.</p>
+ */
+ public static final int DATASPACE_HEIF = 4100;
+
+ /** @hide */
+ @Retention(RetentionPolicy.SOURCE)
+ @IntDef(flag = true, value = {
DATASPACE_UNKNOWN,
DATASPACE_SCRGB_LINEAR,
DATASPACE_SRGB,
diff --git a/core/java/android/inputmethodservice/IRemoteInputConnectionInvoker.java b/core/java/android/inputmethodservice/IRemoteInputConnectionInvoker.java
index 84c3623..5ce38e9 100644
--- a/core/java/android/inputmethodservice/IRemoteInputConnectionInvoker.java
+++ b/core/java/android/inputmethodservice/IRemoteInputConnectionInvoker.java
@@ -33,6 +33,8 @@
import android.view.inputmethod.InputConnection;
import android.view.inputmethod.InputContentInfo;
import android.view.inputmethod.InsertGesture;
+import android.view.inputmethod.JoinOrSplitGesture;
+import android.view.inputmethod.RemoveSpaceGesture;
import android.view.inputmethod.SelectGesture;
import android.view.inputmethod.SurroundingText;
import android.view.inputmethod.TextAttribute;
@@ -633,16 +635,11 @@
}
/**
- * Invokes one of {@link IRemoteInputConnection#performHandwritingSelectGesture(
- * InputConnectionCommandHeader, SelectGesture, AndroidFuture)},
- * {@link IRemoteInputConnection#performHandwritingDeleteGesture(InputConnectionCommandHeader,
- * DeleteGesture, AndroidFuture)},
- * {@link IRemoteInputConnection#performHandwritingInsertGesture(InputConnectionCommandHeader,
- * InsertGesture, AndroidFuture)}
- *
- * @param {@code gesture} parameter {@link HandwritingGesture}.
- * @return {@link AndroidFuture<Integer>} that can be used to retrieve the invocation
- * result. {@link RemoteException} will be treated as an error.
+ * Invokes one of {@link IRemoteInputConnection#performHandwritingSelectGesture},
+ * {@link IRemoteInputConnection#performHandwritingDeleteGesture},
+ * {@link IRemoteInputConnection#performHandwritingInsertGesture},
+ * {@link IRemoteInputConnection#performHandwritingRemoveSpaceGesture},
+ * {@link IRemoteInputConnection#performHandwritingJoinOrSplitGesture}.
*/
@AnyThread
public void performHandwritingGesture(
@@ -664,6 +661,12 @@
} else if (gesture instanceof DeleteGesture) {
mConnection.performHandwritingDeleteGesture(
createHeader(), (DeleteGesture) gesture, resultReceiver);
+ } else if (gesture instanceof RemoveSpaceGesture) {
+ mConnection.performHandwritingRemoveSpaceGesture(
+ createHeader(), (RemoveSpaceGesture) gesture, resultReceiver);
+ } else if (gesture instanceof JoinOrSplitGesture) {
+ mConnection.performHandwritingJoinOrSplitGesture(
+ createHeader(), (JoinOrSplitGesture) gesture, resultReceiver);
} else if (consumer != null && executor != null) {
executor.execute(()
-> consumer.accept(InputConnection.HANDWRITING_GESTURE_RESULT_UNSUPPORTED));
diff --git a/core/java/android/os/BaseBundle.java b/core/java/android/os/BaseBundle.java
index 87579eb..4e3adfb 100644
--- a/core/java/android/os/BaseBundle.java
+++ b/core/java/android/os/BaseBundle.java
@@ -27,6 +27,7 @@
import android.util.Slog;
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.internal.util.Preconditions;
@@ -396,6 +397,20 @@
final <T> T getValueAt(int i, @Nullable Class<T> clazz, @Nullable Class<?>... itemTypes) {
Object object = mMap.valueAt(i);
if (object instanceof BiFunction<?, ?, ?>) {
+ synchronized (this) {
+ object = unwrapLazyValueFromMapLocked(i, clazz, itemTypes);
+ }
+ }
+ return (clazz != null) ? clazz.cast(object) : (T) object;
+ }
+
+ @SuppressWarnings("unchecked")
+ @Nullable
+ @GuardedBy("this")
+ private Object unwrapLazyValueFromMapLocked(int i, @Nullable Class<?> clazz,
+ @Nullable Class<?>... itemTypes) {
+ Object object = mMap.valueAt(i);
+ if (object instanceof BiFunction<?, ?, ?>) {
try {
object = ((BiFunction<Class<?>, Class<?>[], ?>) object).apply(clazz, itemTypes);
} catch (BadParcelableException e) {
@@ -409,7 +424,8 @@
mMap.setValueAt(i, object);
mLazyValues--;
if (mOwnsLazyValues) {
- Preconditions.checkState(mLazyValues >= 0, "Lazy values ref count below 0");
+ Preconditions.checkState(mLazyValues >= 0,
+ "Lazy values ref count below 0");
// No more lazy values in mMap, so we can recycle the parcel early rather than
// waiting for the next GC run
if (mLazyValues == 0) {
@@ -420,7 +436,7 @@
}
}
}
- return (clazz != null) ? clazz.cast(object) : (T) object;
+ return object;
}
private void initializeFromParcelLocked(@NonNull Parcel parcelledData, boolean ownsParcel,
diff --git a/core/java/android/os/BatteryStats.java b/core/java/android/os/BatteryStats.java
index 0ad596b..d71b023 100644
--- a/core/java/android/os/BatteryStats.java
+++ b/core/java/android/os/BatteryStats.java
@@ -961,7 +961,7 @@
* also be bumped.
*/
static final String[] USER_ACTIVITY_TYPES = {
- "other", "button", "touch", "accessibility", "attention"
+ "other", "button", "touch", "accessibility", "attention", "faceDown", "deviceState"
};
public static final int NUM_USER_ACTIVITY_TYPES = USER_ACTIVITY_TYPES.length;
diff --git a/core/java/android/os/Binder.java b/core/java/android/os/Binder.java
index 80cf2f8..4f26ad2 100644
--- a/core/java/android/os/Binder.java
+++ b/core/java/android/os/Binder.java
@@ -1262,8 +1262,15 @@
// Log any exceptions as warnings, don't silently suppress them.
// If the call was {@link IBinder#FLAG_ONEWAY} then these exceptions
// disappear into the ether.
- final boolean tracingEnabled = Trace.isTagEnabled(Trace.TRACE_TAG_AIDL) &&
- (Binder.isStackTrackingEnabled() || Binder.isTracingEnabled(callingUid));
+ final boolean tagEnabled = Trace.isTagEnabled(Trace.TRACE_TAG_AIDL);
+ final String transactionTraceName;
+ if (tagEnabled) {
+ transactionTraceName = getTransactionTraceName(code);
+ } else {
+ transactionTraceName = null;
+ }
+
+ final boolean tracingEnabled = tagEnabled && transactionTraceName != null;
try {
final BinderCallHeavyHitterWatcher heavyHitterWatcher = sHeavyHitterWatcher;
if (heavyHitterWatcher != null) {
@@ -1271,7 +1278,7 @@
heavyHitterWatcher.onTransaction(callingUid, getClass(), code);
}
if (tracingEnabled) {
- Trace.traceBegin(Trace.TRACE_TAG_AIDL, getTransactionTraceName(code));
+ Trace.traceBegin(Trace.TRACE_TAG_AIDL, transactionTraceName);
}
if ((flags & FLAG_COLLECT_NOTED_APP_OPS) != 0) {
diff --git a/core/java/android/os/PowerManager.java b/core/java/android/os/PowerManager.java
index 01b75d1..c0e2864 100644
--- a/core/java/android/os/PowerManager.java
+++ b/core/java/android/os/PowerManager.java
@@ -348,6 +348,39 @@
public static final int USER_ACTIVITY_EVENT_DEVICE_STATE = 6;
/**
+ * @hide
+ */
+ @IntDef(prefix = { "USER_ACTIVITY_EVENT_" }, value = {
+ USER_ACTIVITY_EVENT_OTHER,
+ USER_ACTIVITY_EVENT_BUTTON,
+ USER_ACTIVITY_EVENT_TOUCH,
+ USER_ACTIVITY_EVENT_ACCESSIBILITY,
+ USER_ACTIVITY_EVENT_ATTENTION,
+ USER_ACTIVITY_EVENT_FACE_DOWN,
+ USER_ACTIVITY_EVENT_DEVICE_STATE,
+ })
+ @Retention(RetentionPolicy.SOURCE)
+ public @interface UserActivityEvent{}
+
+ /**
+ *
+ * Convert the user activity event to a string for debugging purposes.
+ * @hide
+ */
+ public static String userActivityEventToString(@UserActivityEvent int userActivityEvent) {
+ switch (userActivityEvent) {
+ case USER_ACTIVITY_EVENT_OTHER: return "other";
+ case USER_ACTIVITY_EVENT_BUTTON: return "button";
+ case USER_ACTIVITY_EVENT_TOUCH: return "touch";
+ case USER_ACTIVITY_EVENT_ACCESSIBILITY: return "accessibility";
+ case USER_ACTIVITY_EVENT_ATTENTION: return "attention";
+ case USER_ACTIVITY_EVENT_FACE_DOWN: return "faceDown";
+ case USER_ACTIVITY_EVENT_DEVICE_STATE: return "deviceState";
+ default: return Integer.toString(userActivityEvent);
+ }
+ }
+
+ /**
* User activity flag: If already dimmed, extend the dim timeout
* but do not brighten. This flag is useful for keeping the screen on
* a little longer without causing a visible change such as when
diff --git a/core/java/android/provider/DeviceConfig.java b/core/java/android/provider/DeviceConfig.java
index b7adcb8..d125cbb 100644
--- a/core/java/android/provider/DeviceConfig.java
+++ b/core/java/android/provider/DeviceConfig.java
@@ -775,6 +775,14 @@
*/
public static final String NAMESPACE_WEAR = "wear";
+ /**
+ * Namespace for the input method manager platform features.
+ *
+ * @hide
+ */
+ @TestApi
+ public static final String NAMESPACE_INPUT_METHOD_MANAGER = "input_method_manager";
+
private static final Object sLock = new Object();
@GuardedBy("sLock")
private static ArrayMap<OnPropertiesChangedListener, Pair<String, Executor>> sListeners =
diff --git a/core/java/android/provider/InputMethodManagerDeviceConfig.java b/core/java/android/provider/InputMethodManagerDeviceConfig.java
new file mode 100644
index 0000000..906b133
--- /dev/null
+++ b/core/java/android/provider/InputMethodManagerDeviceConfig.java
@@ -0,0 +1,31 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.provider;
+
+import android.annotation.TestApi;
+
+/**
+ * Interface for accessing keys belonging to {@link DeviceConfig#NAMESPACE_INPUT_METHOD_MANAGER}.
+ * @hide
+ */
+@TestApi
+public interface InputMethodManagerDeviceConfig {
+ /**
+ * Whether the IME should be hidden when the window gained focus without an editor focused.
+ */
+ String KEY_HIDE_IME_WHEN_NO_EDITOR_FOCUS = "hide_ime_when_no_editor_focus";
+}
diff --git a/core/java/android/service/wallpaper/WallpaperService.java b/core/java/android/service/wallpaper/WallpaperService.java
index bc8822c..be8c140 100644
--- a/core/java/android/service/wallpaper/WallpaperService.java
+++ b/core/java/android/service/wallpaper/WallpaperService.java
@@ -518,7 +518,7 @@
* {@link #addLocalColorsAreas(List)}
* {@link #removeLocalColorsAreas(List)}
* When local colors change, call {@link #notifyLocalColorsChanged(List, List)}
- * See {@link com.android.systemui.ImageWallpaper} for an example
+ * See {@link com.android.systemui.wallpapers.ImageWallpaper} for an example
* @hide
*/
public boolean supportsLocalColorExtraction() {
diff --git a/core/java/android/view/Choreographer.java b/core/java/android/view/Choreographer.java
index cc68ddd..91febcd 100644
--- a/core/java/android/view/Choreographer.java
+++ b/core/java/android/view/Choreographer.java
@@ -765,11 +765,12 @@
startNanos = System.nanoTime();
final long jitterNanos = startNanos - frameTimeNanos;
if (jitterNanos >= frameIntervalNanos) {
- long lastFrameOffset = 0;
+ frameTimeNanos = startNanos;
if (frameIntervalNanos == 0) {
Log.i(TAG, "Vsync data empty due to timeout");
} else {
- lastFrameOffset = jitterNanos % frameIntervalNanos;
+ long lastFrameOffset = jitterNanos % frameIntervalNanos;
+ frameTimeNanos = frameTimeNanos - lastFrameOffset;
final long skippedFrames = jitterNanos / frameIntervalNanos;
if (skippedFrames >= SKIPPED_FRAME_WARNING_LIMIT) {
Log.i(TAG, "Skipped " + skippedFrames + " frames! "
@@ -785,8 +786,7 @@
+ " ms in the past.");
}
}
- frameTimeNanos = startNanos - lastFrameOffset;
- frameData.updateFrameData(frameTimeNanos);
+ frameData = getUpdatedFrameData(frameTimeNanos, frameData, jitterNanos);
}
if (frameTimeNanos < mLastFrameTimeNanos) {
@@ -884,7 +884,7 @@
}
frameTimeNanos = now - lastFrameOffset;
mLastFrameTimeNanos = frameTimeNanos;
- frameData.updateFrameData(frameTimeNanos);
+ frameData = getUpdatedFrameData(frameTimeNanos, frameData, jitterNanos);
}
}
}
@@ -998,9 +998,6 @@
/** Holds data that describes one possible VSync frame event to render at. */
public static class FrameTimeline {
- static final FrameTimeline INVALID_FRAME_TIMELINE = new FrameTimeline(
- FrameInfo.INVALID_VSYNC_ID, Long.MAX_VALUE, Long.MAX_VALUE);
-
FrameTimeline(long vsyncId, long expectedPresentTimeNanos, long deadlineNanos) {
this.mVsyncId = vsyncId;
this.mExpectedPresentTimeNanos = expectedPresentTimeNanos;
@@ -1019,11 +1016,6 @@
return mVsyncId;
}
- /** Reset the vsync ID to invalid. */
- void resetVsyncId() {
- mVsyncId = FrameInfo.INVALID_VSYNC_ID;
- }
-
/**
* The time in {@link System#nanoTime()} timebase which this frame is expected to be
* presented.
@@ -1046,39 +1038,20 @@
* information including deadline and expected present time.
*/
public static class FrameData {
- static final FrameTimeline[] INVALID_FRAME_TIMELINES = new FrameTimeline[0];
- FrameData() {
- this.mFrameTimelines = INVALID_FRAME_TIMELINES;
- this.mPreferredFrameTimeline = FrameTimeline.INVALID_FRAME_TIMELINE;
- }
-
FrameData(long frameTimeNanos, DisplayEventReceiver.VsyncEventData vsyncEventData) {
- FrameTimeline[] frameTimelines =
- new FrameTimeline[vsyncEventData.frameTimelines.length];
- for (int i = 0; i < vsyncEventData.frameTimelines.length; i++) {
- DisplayEventReceiver.VsyncEventData.FrameTimeline frameTimeline =
- vsyncEventData.frameTimelines[i];
- frameTimelines[i] = new FrameTimeline(frameTimeline.vsyncId,
- frameTimeline.expectedPresentTime, frameTimeline.deadline);
- }
this.mFrameTimeNanos = frameTimeNanos;
- this.mFrameTimelines = frameTimelines;
- this.mPreferredFrameTimeline =
- frameTimelines[vsyncEventData.preferredFrameTimelineIndex];
+ this.mFrameTimelines = convertFrameTimelines(vsyncEventData);
+ this.mPreferredFrameTimelineIndex =
+ vsyncEventData.preferredFrameTimelineIndex;
}
private long mFrameTimeNanos;
- private FrameTimeline[] mFrameTimelines;
- private FrameTimeline mPreferredFrameTimeline;
+ private final FrameTimeline[] mFrameTimelines;
+ private int mPreferredFrameTimelineIndex;
- void updateFrameData(long frameTimeNanos) {
+ void updateFrameData(long frameTimeNanos, int newPreferredFrameTimelineIndex) {
mFrameTimeNanos = frameTimeNanos;
- for (FrameTimeline ft : mFrameTimelines) {
- // The ID is no longer valid because the frame time that was registered with the ID
- // no longer matches.
- // TODO(b/205721584): Ask SF for valid vsync information.
- ft.resetVsyncId();
- }
+ mPreferredFrameTimelineIndex = newPreferredFrameTimelineIndex;
}
/** The time in nanoseconds when the frame started being rendered. */
@@ -1096,7 +1069,7 @@
/** The platform-preferred frame timeline. */
@NonNull
public FrameTimeline getPreferredFrameTimeline() {
- return mPreferredFrameTimeline;
+ return mFrameTimelines[mPreferredFrameTimelineIndex];
}
private FrameTimeline[] convertFrameTimelines(
@@ -1114,6 +1087,38 @@
}
/**
+ * Update the frame data when the frame is late.
+ *
+ * @param jitterNanos currentTime - frameTime
+ */
+ private FrameData getUpdatedFrameData(long frameTimeNanos, FrameData frameData,
+ long jitterNanos) {
+ int newPreferredIndex = 0;
+ FrameTimeline[] frameTimelines = frameData.getFrameTimelines();
+ final long minimumDeadline =
+ frameData.getPreferredFrameTimeline().getDeadlineNanos() + jitterNanos;
+ // Look for a non-past deadline timestamp in the existing frame data. Otherwise, binder
+ // query for new frame data. Note that binder is relatively slow, O(ms), so it is
+ // only called when the existing frame data does not hold a valid frame.
+ while (newPreferredIndex < frameTimelines.length - 1
+ && frameTimelines[newPreferredIndex].getDeadlineNanos()
+ < minimumDeadline) {
+ newPreferredIndex++;
+ }
+
+ long newPreferredDeadline =
+ frameData.getFrameTimelines()[newPreferredIndex].getDeadlineNanos();
+ if (newPreferredDeadline < minimumDeadline) {
+ DisplayEventReceiver.VsyncEventData latestVsyncEventData =
+ mDisplayEventReceiver.getLatestVsyncEventData();
+ return new FrameData(frameTimeNanos, latestVsyncEventData);
+ } else {
+ frameData.updateFrameData(frameTimeNanos, newPreferredIndex);
+ return frameData;
+ }
+ }
+
+ /**
* Implement this interface to receive a callback to start the next frame. The callback is
* invoked on the {@link Looper} thread to which the {@link Choreographer} is attached. The
* callback payload contains information about multiple possible frames, allowing choice of
diff --git a/core/java/android/view/inputmethod/DeleteGesture.java b/core/java/android/view/inputmethod/DeleteGesture.java
index 1395578..9fadabf 100644
--- a/core/java/android/view/inputmethod/DeleteGesture.java
+++ b/core/java/android/view/inputmethod/DeleteGesture.java
@@ -64,7 +64,6 @@
* Returns the deletion area {@link RectF} in screen coordinates.
*
* Getter for deletion area set with {@link DeleteGesture.Builder#setDeletionArea(RectF)}.
- * {@code null} if area was not set.
*/
@NonNull
public RectF getDeletionArea() {
@@ -145,7 +144,8 @@
/**
* Used to make this class parcelable.
*/
- public static final @android.annotation.NonNull Creator<DeleteGesture> CREATOR =
+ @NonNull
+ public static final Creator<DeleteGesture> CREATOR =
new Creator<DeleteGesture>() {
@Override
public DeleteGesture createFromParcel(Parcel source) {
diff --git a/core/java/android/view/inputmethod/EditorInfo.java b/core/java/android/view/inputmethod/EditorInfo.java
index 36b0334..c3b32c9 100644
--- a/core/java/android/view/inputmethod/EditorInfo.java
+++ b/core/java/android/view/inputmethod/EditorInfo.java
@@ -561,6 +561,10 @@
supportedTypes |= HandwritingGesture.GESTURE_TYPE_INSERT;
} else if (gesture.equals(DeleteGesture.class)) {
supportedTypes |= HandwritingGesture.GESTURE_TYPE_DELETE;
+ } else if (gesture.equals(RemoveSpaceGesture.class)) {
+ supportedTypes |= HandwritingGesture.GESTURE_TYPE_REMOVE_SPACE;
+ } else if (gesture.equals(JoinOrSplitGesture.class)) {
+ supportedTypes |= HandwritingGesture.GESTURE_TYPE_JOIN_OR_SPLIT;
} else {
throw new IllegalArgumentException("Unknown gesture type: " + gesture);
}
@@ -595,6 +599,14 @@
== HandwritingGesture.GESTURE_TYPE_DELETE) {
list.add(DeleteGesture.class);
}
+ if ((mSupportedHandwritingGestureTypes & HandwritingGesture.GESTURE_TYPE_REMOVE_SPACE)
+ == HandwritingGesture.GESTURE_TYPE_REMOVE_SPACE) {
+ list.add(RemoveSpaceGesture.class);
+ }
+ if ((mSupportedHandwritingGestureTypes & HandwritingGesture.GESTURE_TYPE_JOIN_OR_SPLIT)
+ == HandwritingGesture.GESTURE_TYPE_JOIN_OR_SPLIT) {
+ list.add(JoinOrSplitGesture.class);
+ }
return list;
}
diff --git a/core/java/android/view/inputmethod/HandwritingGesture.java b/core/java/android/view/inputmethod/HandwritingGesture.java
index a659333..494aaaa 100644
--- a/core/java/android/view/inputmethod/HandwritingGesture.java
+++ b/core/java/android/view/inputmethod/HandwritingGesture.java
@@ -99,15 +99,23 @@
*/
public static final int GESTURE_TYPE_DELETE = 1 << 2;
+ /** Gesture of type {@link RemoveSpaceGesture} to remove whitespace from text. */
+ public static final int GESTURE_TYPE_REMOVE_SPACE = 1 << 3;
+
+ /** Gesture of type {@link JoinOrSplitGesture} to join or split text. */
+ public static final int GESTURE_TYPE_JOIN_OR_SPLIT = 1 << 4;
+
/**
* Type of gesture like {@link #GESTURE_TYPE_SELECT}, {@link #GESTURE_TYPE_INSERT},
* or {@link #GESTURE_TYPE_DELETE}.
*/
@IntDef(prefix = {"GESTURE_TYPE_"}, value = {
- GESTURE_TYPE_NONE,
- GESTURE_TYPE_SELECT,
- GESTURE_TYPE_INSERT,
- GESTURE_TYPE_DELETE})
+ GESTURE_TYPE_NONE,
+ GESTURE_TYPE_SELECT,
+ GESTURE_TYPE_INSERT,
+ GESTURE_TYPE_DELETE,
+ GESTURE_TYPE_REMOVE_SPACE,
+ GESTURE_TYPE_JOIN_OR_SPLIT})
@Retention(RetentionPolicy.SOURCE)
@interface GestureType{}
@@ -121,7 +129,9 @@
@IntDef(flag = true, prefix = {"GESTURE_TYPE_"}, value = {
GESTURE_TYPE_SELECT,
GESTURE_TYPE_INSERT,
- GESTURE_TYPE_DELETE})
+ GESTURE_TYPE_DELETE,
+ GESTURE_TYPE_REMOVE_SPACE,
+ GESTURE_TYPE_JOIN_OR_SPLIT})
@Retention(RetentionPolicy.SOURCE)
public @interface GestureTypeFlags{}
diff --git a/core/java/android/view/inputmethod/InsertGesture.java b/core/java/android/view/inputmethod/InsertGesture.java
index cffdf35..8b8359e 100644
--- a/core/java/android/view/inputmethod/InsertGesture.java
+++ b/core/java/android/view/inputmethod/InsertGesture.java
@@ -124,7 +124,8 @@
/**
* Used to make this class parcelable.
*/
- public static final @android.annotation.NonNull Creator<InsertGesture> CREATOR =
+ @NonNull
+ public static final Creator<InsertGesture> CREATOR =
new Creator<InsertGesture>() {
@Override
public InsertGesture createFromParcel(Parcel source) {
diff --git a/core/java/android/view/inputmethod/JoinOrSplitGesture.aidl b/core/java/android/view/inputmethod/JoinOrSplitGesture.aidl
new file mode 100644
index 0000000..e339b55
--- /dev/null
+++ b/core/java/android/view/inputmethod/JoinOrSplitGesture.aidl
@@ -0,0 +1,19 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.view.inputmethod;
+
+parcelable JoinOrSplitGesture;
diff --git a/core/java/android/view/inputmethod/JoinOrSplitGesture.java b/core/java/android/view/inputmethod/JoinOrSplitGesture.java
new file mode 100644
index 0000000..2fa8063
--- /dev/null
+++ b/core/java/android/view/inputmethod/JoinOrSplitGesture.java
@@ -0,0 +1,145 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.view.inputmethod;
+
+import android.annotation.NonNull;
+import android.annotation.Nullable;
+import android.graphics.PointF;
+import android.os.Parcel;
+import android.os.Parcelable;
+
+import java.util.Objects;
+
+/**
+ * A subclass of {@link HandwritingGesture} for deleting or inserting whitespace in text. If the
+ * gesture is drawn over whitespace, then the whitespace will be deleted. Otherwise, a space will be
+ * inserted.
+ */
+public final class JoinOrSplitGesture extends HandwritingGesture implements Parcelable {
+
+ private final PointF mPoint;
+
+ private JoinOrSplitGesture(PointF point, String fallbackText) {
+ mType = GESTURE_TYPE_JOIN_OR_SPLIT;
+ mPoint = point;
+ mFallbackText = fallbackText;
+ }
+
+ private JoinOrSplitGesture(@NonNull Parcel source) {
+ mType = GESTURE_TYPE_JOIN_OR_SPLIT;
+ mPoint = source.readTypedObject(PointF.CREATOR);
+ mFallbackText = source.readString8();
+ }
+
+ /**
+ * Returns the gesture point in screen coordinates set with {@link Builder#setJoinOrSplitPoint}.
+ */
+ @NonNull
+ public PointF getJoinOrSplitPoint() {
+ return mPoint;
+ }
+
+ /** Builder for {@link JoinOrSplitGesture}. This class is not designed to be thread-safe. */
+ public static final class Builder {
+ private PointF mPoint;
+ private String mFallbackText;
+
+ /**
+ * Sets the point to apply the join or split operation in screen coordinates.
+ *
+ * <p>If the text cursor position closest to the point is inside or on the boundary of
+ * whitespace, then the whitespace will be deleted, joining the text on either side of the
+ * whitespace. If there are multiple consecutive whitespace characters, then the entire
+ * whitespace block will be deleted.
+ *
+ * <p>Otherwise, if the text cursor position closest to the point is not touching
+ * whitespace, then a space will be inserted at that position.
+ */
+ @NonNull
+ public Builder setJoinOrSplitPoint(@NonNull PointF point) {
+ mPoint = point;
+ return this;
+ }
+
+ /**
+ * Sets fallback text that will be committed at current cursor position if there is no
+ * applicable text beneath the gesture point.
+ */
+ @NonNull
+ public Builder setFallbackText(@Nullable String fallbackText) {
+ mFallbackText = fallbackText;
+ return this;
+ }
+
+ /**
+ * @return {@link JoinOrSplitGesture} using parameters in this {@link Builder}.
+ * @throws IllegalArgumentException if one or more positional parameters are not specified.
+ */
+ @NonNull
+ public JoinOrSplitGesture build() {
+ if (mPoint == null) {
+ throw new IllegalArgumentException("Point must be set.");
+ }
+ return new JoinOrSplitGesture(mPoint, mFallbackText);
+ }
+ }
+
+ /** Used to make this class parcelable. */
+ @NonNull
+ public static final Parcelable.Creator<JoinOrSplitGesture> CREATOR =
+ new Parcelable.Creator<JoinOrSplitGesture>() {
+ @Override
+ public JoinOrSplitGesture createFromParcel(Parcel source) {
+ return new JoinOrSplitGesture(source);
+ }
+
+ @Override
+ public JoinOrSplitGesture[] newArray(int size) {
+ return new JoinOrSplitGesture[size];
+ }
+ };
+
+ @Override
+ public int hashCode() {
+ return Objects.hash(mPoint, mFallbackText);
+ }
+
+ @Override
+ public boolean equals(Object o) {
+ if (!(o instanceof JoinOrSplitGesture)) return false;
+ JoinOrSplitGesture that = (JoinOrSplitGesture) o;
+ return Objects.equals(mPoint, that.mPoint)
+ && Objects.equals(mFallbackText, that.mFallbackText);
+ }
+
+ @Override
+ public int describeContents() {
+ return 0;
+ }
+
+ /**
+ * Used to package this object into a {@link Parcel}.
+ *
+ * @param dest {@link Parcel} to be written
+ * @param flags flags used for parceling
+ */
+ @Override
+ public void writeToParcel(@NonNull Parcel dest, int flags) {
+ dest.writeTypedObject(mPoint, flags);
+ dest.writeString8(mFallbackText);
+ }
+}
diff --git a/core/java/android/view/inputmethod/RemoveSpaceGesture.aidl b/core/java/android/view/inputmethod/RemoveSpaceGesture.aidl
new file mode 100644
index 0000000..7aab528
--- /dev/null
+++ b/core/java/android/view/inputmethod/RemoveSpaceGesture.aidl
@@ -0,0 +1,19 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.view.inputmethod;
+
+parcelable RemoveSpaceGesture;
diff --git a/core/java/android/view/inputmethod/RemoveSpaceGesture.java b/core/java/android/view/inputmethod/RemoveSpaceGesture.java
new file mode 100644
index 0000000..936f259
--- /dev/null
+++ b/core/java/android/view/inputmethod/RemoveSpaceGesture.java
@@ -0,0 +1,152 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.view.inputmethod;
+
+import android.annotation.NonNull;
+import android.annotation.Nullable;
+import android.annotation.SuppressLint;
+import android.graphics.PointF;
+import android.os.Parcel;
+import android.os.Parcelable;
+
+import java.util.Objects;
+
+/** A subclass of {@link HandwritingGesture} for removing whitespace from text. */
+public final class RemoveSpaceGesture extends HandwritingGesture implements Parcelable {
+
+ private final PointF mStartPoint;
+ private final PointF mEndPoint;
+
+ private RemoveSpaceGesture(PointF startPoint, PointF endPoint, String fallbackText) {
+ mType = GESTURE_TYPE_REMOVE_SPACE;
+ mStartPoint = startPoint;
+ mEndPoint = endPoint;
+ mFallbackText = fallbackText;
+ }
+
+ private RemoveSpaceGesture(@NonNull Parcel source) {
+ mType = GESTURE_TYPE_REMOVE_SPACE;
+ mStartPoint = source.readTypedObject(PointF.CREATOR);
+ mEndPoint = source.readTypedObject(PointF.CREATOR);
+ mFallbackText = source.readString8();
+ }
+
+ /** Returns the start point in screen coordinates set with {@link Builder#setPoints}. */
+ @NonNull
+ public PointF getStartPoint() {
+ return mStartPoint;
+ }
+
+ /** Returns the end point in screen coordinates set with {@link Builder#setPoints}. */
+ @NonNull
+ public PointF getEndPoint() {
+ return mEndPoint;
+ }
+
+ /** Builder for {@link RemoveSpaceGesture}. This class is not designed to be thread-safe. */
+ public static final class Builder {
+ private PointF mStartPoint;
+ private PointF mEndPoint;
+ private String mFallbackText;
+
+ /**
+ * Sets the start and end points in screen coordinates of the line to apply the remove space
+ * operation. All whitespace characters touched by the line joining the points will be
+ * deleted.
+ *
+ * <p>The operation will only be performed on a single line of text. If the start and end
+ * points are on different lines of text, the line will be adjusted to cover only the first
+ * line of text containing one of the points.
+ */
+ @NonNull
+ @SuppressLint("MissingGetterMatchingBuilder")
+ public Builder setPoints(@NonNull PointF startPoint, @NonNull PointF endPoint) {
+ mStartPoint = startPoint;
+ mEndPoint = endPoint;
+ return this;
+ }
+
+ /**
+ * Sets fallback text that will be committed at current cursor position if there is no
+ * whitespace beneath the gesture line.
+ */
+ @NonNull
+ public Builder setFallbackText(@Nullable String fallbackText) {
+ mFallbackText = fallbackText;
+ return this;
+ }
+
+ /**
+ * @return {@link RemoveSpaceGesture} using parameters in this {@link Builder}.
+ * @throws IllegalArgumentException if one or more positional parameters are not specified.
+ */
+ @NonNull
+ public RemoveSpaceGesture build() {
+ if (mStartPoint == null || mEndPoint == null) {
+ throw new IllegalArgumentException("Start and end points must be set.");
+ }
+ return new RemoveSpaceGesture(mStartPoint, mEndPoint, mFallbackText);
+ }
+ }
+
+ /** Used to make this class parcelable. */
+ @NonNull
+ public static final Parcelable.Creator<RemoveSpaceGesture> CREATOR =
+ new Parcelable.Creator<RemoveSpaceGesture>() {
+ @Override
+ public RemoveSpaceGesture createFromParcel(Parcel source) {
+ return new RemoveSpaceGesture(source);
+ }
+
+ @Override
+ public RemoveSpaceGesture[] newArray(int size) {
+ return new RemoveSpaceGesture[size];
+ }
+ };
+
+ @Override
+ public int hashCode() {
+ return Objects.hash(mStartPoint, mEndPoint, mFallbackText);
+ }
+
+ @Override
+ public boolean equals(Object o) {
+ if (!(o instanceof RemoveSpaceGesture)) return false;
+ RemoveSpaceGesture that = (RemoveSpaceGesture) o;
+ return Objects.equals(mStartPoint, that.mStartPoint)
+ && Objects.equals(mEndPoint, that.mEndPoint)
+ && Objects.equals(mFallbackText, that.mFallbackText);
+ }
+
+ @Override
+ public int describeContents() {
+ return 0;
+ }
+
+ /**
+ * Used to package this object into a {@link Parcel}.
+ *
+ * @param dest {@link Parcel} to be written
+ * @param flags flags used for parceling
+ */
+ @Override
+ public void writeToParcel(@NonNull Parcel dest, int flags) {
+ dest.writeTypedObject(mStartPoint, flags);
+ dest.writeTypedObject(mEndPoint, flags);
+ dest.writeString8(mFallbackText);
+ }
+}
diff --git a/core/java/android/view/inputmethod/SelectGesture.java b/core/java/android/view/inputmethod/SelectGesture.java
index 5b68517..2f02e66 100644
--- a/core/java/android/view/inputmethod/SelectGesture.java
+++ b/core/java/android/view/inputmethod/SelectGesture.java
@@ -63,8 +63,7 @@
/**
* Returns the Selection area {@link RectF} in screen coordinates.
*
- * Getter for selection area set with {@link Builder#setSelectionArea(RectF)}. {@code null}
- * if area was not set.
+ * Getter for selection area set with {@link Builder#setSelectionArea(RectF)}.
*/
@NonNull
public RectF getSelectionArea() {
@@ -126,7 +125,7 @@
}
/**
- * @return {@link SelectGesture} using parameters in this {@link InsertGesture.Builder}.
+ * @return {@link SelectGesture} using parameters in this {@link Builder}.
* @throws IllegalArgumentException if one or more positional parameters are not specified.
*/
@NonNull
@@ -144,7 +143,8 @@
/**
* Used to make this class parcelable.
*/
- public static final @android.annotation.NonNull Parcelable.Creator<SelectGesture> CREATOR =
+ @NonNull
+ public static final Parcelable.Creator<SelectGesture> CREATOR =
new Parcelable.Creator<SelectGesture>() {
@Override
public SelectGesture createFromParcel(Parcel source) {
diff --git a/core/java/android/widget/SelectionActionModeHelper.java b/core/java/android/widget/SelectionActionModeHelper.java
index be6b08f..075aa6c 100644
--- a/core/java/android/widget/SelectionActionModeHelper.java
+++ b/core/java/android/widget/SelectionActionModeHelper.java
@@ -148,6 +148,9 @@
startSelectionActionMode(null);
} else {
resetTextClassificationHelper();
+ if (mSmartSelectSprite != null && mSmartSelectSprite.isAnimationActive()) {
+ mSmartSelectSprite.cancelAnimation();
+ }
mTextClassificationAsyncTask = new TextClassificationAsyncTask(
mTextView,
mTextClassificationHelper.getTimeoutDuration(),
diff --git a/core/java/com/android/internal/app/ChooserActivity.java b/core/java/com/android/internal/app/ChooserActivity.java
index 8bb8714..5cf7e36 100644
--- a/core/java/com/android/internal/app/ChooserActivity.java
+++ b/core/java/com/android/internal/app/ChooserActivity.java
@@ -2953,12 +2953,14 @@
private void startFinishAnimation() {
View rootView = findRootView();
- rootView.startAnimation(new FinishAnimation(this, rootView));
+ if (rootView != null) {
+ rootView.startAnimation(new FinishAnimation(this, rootView));
+ }
}
private boolean maybeCancelFinishAnimation() {
View rootView = findRootView();
- Animation animation = rootView.getAnimation();
+ Animation animation = rootView == null ? null : rootView.getAnimation();
if (animation instanceof FinishAnimation) {
boolean hasEnded = animation.hasEnded();
animation.cancel();
@@ -4086,11 +4088,13 @@
*/
private static class FinishAnimation extends AlphaAnimation implements
Animation.AnimationListener {
+ @Nullable
private Activity mActivity;
+ @Nullable
private View mRootView;
private final float mFromAlpha;
- FinishAnimation(Activity activity, View rootView) {
+ FinishAnimation(@NonNull Activity activity, @NonNull View rootView) {
super(rootView.getAlpha(), 0.0f);
mActivity = activity;
mRootView = rootView;
@@ -4114,7 +4118,9 @@
@Override
public void cancel() {
- mRootView.setAlpha(mFromAlpha);
+ if (mRootView != null) {
+ mRootView.setAlpha(mFromAlpha);
+ }
cleanup();
super.cancel();
}
@@ -4125,9 +4131,10 @@
@Override
public void onAnimationEnd(Animation animation) {
- if (mActivity != null) {
- mActivity.finish();
- cleanup();
+ Activity activity = mActivity;
+ cleanup();
+ if (activity != null) {
+ activity.finish();
}
}
diff --git a/core/java/com/android/internal/inputmethod/IRemoteInputConnection.aidl b/core/java/com/android/internal/inputmethod/IRemoteInputConnection.aidl
index 7a219c6..f456e85 100644
--- a/core/java/com/android/internal/inputmethod/IRemoteInputConnection.aidl
+++ b/core/java/com/android/internal/inputmethod/IRemoteInputConnection.aidl
@@ -25,6 +25,8 @@
import android.view.inputmethod.ExtractedTextRequest;
import android.view.inputmethod.InputContentInfo;
import android.view.inputmethod.InsertGesture;
+import android.view.inputmethod.JoinOrSplitGesture;
+import android.view.inputmethod.RemoveSpaceGesture;
import android.view.inputmethod.SelectGesture;
import android.view.inputmethod.TextAttribute;
@@ -99,6 +101,12 @@
void performHandwritingDeleteGesture(in InputConnectionCommandHeader header,
in DeleteGesture gesture, in ResultReceiver resultReceiver);
+ void performHandwritingRemoveSpaceGesture(in InputConnectionCommandHeader header,
+ in RemoveSpaceGesture gesture, in ResultReceiver resultReceiver);
+
+ void performHandwritingJoinOrSplitGesture(in InputConnectionCommandHeader header,
+ in JoinOrSplitGesture gesture, in ResultReceiver resultReceiver);
+
void setComposingRegion(in InputConnectionCommandHeader header, int start, int end);
void setComposingRegionWithTextAttribute(in InputConnectionCommandHeader header, int start,
diff --git a/core/java/com/android/internal/inputmethod/InputMethodDebug.java b/core/java/com/android/internal/inputmethod/InputMethodDebug.java
index 1852c59..bbf0a76 100644
--- a/core/java/com/android/internal/inputmethod/InputMethodDebug.java
+++ b/core/java/com/android/internal/inputmethod/InputMethodDebug.java
@@ -20,7 +20,6 @@
import android.view.View;
import android.view.WindowManager;
import android.view.WindowManager.LayoutParams.SoftInputModeFlags;
-import android.view.autofill.AutofillManager;
import android.view.inputmethod.HandwritingGesture;
import java.util.StringJoiner;
@@ -254,6 +253,8 @@
return "HIDE_SOFT_INPUT_EXTRACT_INPUT_CHANGED";
case SoftInputShowHideReason.HIDE_SOFT_INPUT_IMM_DEPRECATION:
return "HIDE_SOFT_INPUT_IMM_DEPRECATION";
+ case SoftInputShowHideReason.HIDE_WINDOW_GAINED_FOCUS_WITHOUT_EDITOR:
+ return "HIDE_WINDOW_GAINED_FOCUS_WITHOUT_EDITOR";
default:
return "Unknown=" + reason;
}
@@ -277,6 +278,12 @@
if ((gestureTypeFlags & HandwritingGesture.GESTURE_TYPE_DELETE) != 0) {
joiner.add("DELETE");
}
+ if ((gestureTypeFlags & HandwritingGesture.GESTURE_TYPE_REMOVE_SPACE) != 0) {
+ joiner.add("REMOVE_SPACE");
+ }
+ if ((gestureTypeFlags & HandwritingGesture.GESTURE_TYPE_JOIN_OR_SPLIT) != 0) {
+ joiner.add("JOIN_OR_SPLIT");
+ }
return joiner.setEmptyValue("(none)").toString();
}
diff --git a/core/java/com/android/internal/inputmethod/RemoteInputConnectionImpl.java b/core/java/com/android/internal/inputmethod/RemoteInputConnectionImpl.java
index dd173a6..6a7028d 100644
--- a/core/java/com/android/internal/inputmethod/RemoteInputConnectionImpl.java
+++ b/core/java/com/android/internal/inputmethod/RemoteInputConnectionImpl.java
@@ -48,6 +48,8 @@
import android.view.inputmethod.InputContentInfo;
import android.view.inputmethod.InputMethodManager;
import android.view.inputmethod.InsertGesture;
+import android.view.inputmethod.JoinOrSplitGesture;
+import android.view.inputmethod.RemoveSpaceGesture;
import android.view.inputmethod.SelectGesture;
import android.view.inputmethod.TextAttribute;
import android.view.inputmethod.TextSnapshot;
@@ -997,6 +999,22 @@
performHandwritingGestureInternal(header, gesture, resultReceiver);
}
+ @Dispatching(cancellable = true)
+ @Override
+ public void performHandwritingRemoveSpaceGesture(
+ InputConnectionCommandHeader header, RemoveSpaceGesture gesture,
+ ResultReceiver resultReceiver) {
+ performHandwritingGestureInternal(header, gesture, resultReceiver);
+ }
+
+ @Dispatching(cancellable = true)
+ @Override
+ public void performHandwritingJoinOrSplitGesture(
+ InputConnectionCommandHeader header, JoinOrSplitGesture gesture,
+ ResultReceiver resultReceiver) {
+ performHandwritingGestureInternal(header, gesture, resultReceiver);
+ }
+
private <T extends HandwritingGesture> void performHandwritingGestureInternal(
InputConnectionCommandHeader header, T gesture, ResultReceiver resultReceiver) {
dispatchWithTracing("performHandwritingGesture", () -> {
diff --git a/core/java/com/android/internal/inputmethod/SoftInputShowHideReason.java b/core/java/com/android/internal/inputmethod/SoftInputShowHideReason.java
index f5b58c0..f1635eb 100644
--- a/core/java/com/android/internal/inputmethod/SoftInputShowHideReason.java
+++ b/core/java/com/android/internal/inputmethod/SoftInputShowHideReason.java
@@ -63,7 +63,8 @@
SoftInputShowHideReason.HIDE_SOFT_INPUT_BY_BACK_KEY,
SoftInputShowHideReason.HIDE_SOFT_INPUT_IME_TOGGLE_SOFT_INPUT,
SoftInputShowHideReason.HIDE_SOFT_INPUT_EXTRACT_INPUT_CHANGED,
- SoftInputShowHideReason.HIDE_SOFT_INPUT_IMM_DEPRECATION})
+ SoftInputShowHideReason.HIDE_SOFT_INPUT_IMM_DEPRECATION,
+ SoftInputShowHideReason.HIDE_WINDOW_GAINED_FOCUS_WITHOUT_EDITOR})
public @interface SoftInputShowHideReason {
/** Show soft input by {@link android.view.inputmethod.InputMethodManager#showSoftInput}. */
int SHOW_SOFT_INPUT = 0;
@@ -247,4 +248,9 @@
* {@link InputMethodManager#hideSoftInputFromInputMethod(IBinder, int)}.
*/
int HIDE_SOFT_INPUT_IMM_DEPRECATION = 31;
+
+ /**
+ * Hide soft input when the window gained focus without an editor from the IME shown window.
+ */
+ int HIDE_WINDOW_GAINED_FOCUS_WITHOUT_EDITOR = 32;
}
diff --git a/core/java/com/android/internal/jank/DisplayResolutionTracker.java b/core/java/com/android/internal/jank/DisplayResolutionTracker.java
new file mode 100644
index 0000000..fd58468
--- /dev/null
+++ b/core/java/com/android/internal/jank/DisplayResolutionTracker.java
@@ -0,0 +1,162 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.internal.jank;
+
+import static com.android.internal.util.FrameworkStatsLog.UIINTERACTION_FRAME_INFO_REPORTED__DISPLAY_RESOLUTION__FHD;
+import static com.android.internal.util.FrameworkStatsLog.UIINTERACTION_FRAME_INFO_REPORTED__DISPLAY_RESOLUTION__HD;
+import static com.android.internal.util.FrameworkStatsLog.UIINTERACTION_FRAME_INFO_REPORTED__DISPLAY_RESOLUTION__QHD;
+import static com.android.internal.util.FrameworkStatsLog.UIINTERACTION_FRAME_INFO_REPORTED__DISPLAY_RESOLUTION__SD;
+import static com.android.internal.util.FrameworkStatsLog.UIINTERACTION_FRAME_INFO_REPORTED__DISPLAY_RESOLUTION__UNKNOWN_RESOLUTION;
+
+import android.annotation.IntDef;
+import android.annotation.Nullable;
+import android.hardware.display.DisplayManager;
+import android.hardware.display.DisplayManagerGlobal;
+import android.os.Handler;
+import android.util.SparseArray;
+import android.view.DisplayInfo;
+
+import com.android.internal.annotations.VisibleForTesting;
+
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+
+/**
+* A class that tracks the display resolutions.
+* @hide
+*/
+public class DisplayResolutionTracker {
+ private static final String TAG = DisplayResolutionTracker.class.getSimpleName();
+
+ public static final int RESOLUTION_UNKNOWN =
+ UIINTERACTION_FRAME_INFO_REPORTED__DISPLAY_RESOLUTION__UNKNOWN_RESOLUTION;
+ public static final int RESOLUTION_SD =
+ UIINTERACTION_FRAME_INFO_REPORTED__DISPLAY_RESOLUTION__SD;
+ public static final int RESOLUTION_HD =
+ UIINTERACTION_FRAME_INFO_REPORTED__DISPLAY_RESOLUTION__HD;
+ public static final int RESOLUTION_FHD =
+ UIINTERACTION_FRAME_INFO_REPORTED__DISPLAY_RESOLUTION__FHD;
+ public static final int RESOLUTION_QHD =
+ UIINTERACTION_FRAME_INFO_REPORTED__DISPLAY_RESOLUTION__QHD;
+
+ /** @hide */
+ @IntDef({
+ RESOLUTION_UNKNOWN,
+ RESOLUTION_SD,
+ RESOLUTION_HD,
+ RESOLUTION_FHD,
+ RESOLUTION_QHD,
+ })
+ @Retention(RetentionPolicy.SOURCE)
+ public @interface Resolution {
+ }
+
+ private final DisplayInterface mManager;
+ private final SparseArray<Integer> mResolutions = new SparseArray<>();
+ private final Object mLock = new Object();
+
+ public DisplayResolutionTracker(@Nullable Handler handler) {
+ this(DisplayInterface.getDefault(handler));
+ }
+
+ @VisibleForTesting
+ public DisplayResolutionTracker(DisplayInterface manager) {
+ mManager = manager;
+ mManager.registerDisplayListener(new DisplayManager.DisplayListener() {
+ @Override
+ public void onDisplayAdded(int displayId) {
+ updateDisplay(displayId);
+ }
+
+ @Override
+ public void onDisplayChanged(int displayId) {
+ updateDisplay(displayId);
+ }
+
+ @Override
+ public void onDisplayRemoved(int displayId) {
+ // Not in the event mask below, won't be called.
+ }
+ });
+ }
+
+ private void updateDisplay(int displayId) {
+ DisplayInfo info = mManager.getDisplayInfo(displayId);
+ @Resolution int resolution = getResolution(info);
+
+ synchronized (mLock) {
+ mResolutions.put(displayId, resolution);
+ }
+ }
+
+ /**
+ * Returns the (cached) resolution of the display with the given ID.
+ */
+ @Resolution
+ public int getResolution(int displayId) {
+ return mResolutions.get(displayId, RESOLUTION_UNKNOWN);
+ }
+
+ /**
+ * Returns the resolution of the given {@link DisplayInfo}.
+ */
+ @VisibleForTesting
+ @Resolution
+ public static int getResolution(DisplayInfo info) {
+ int smaller = Math.min(info.logicalWidth, info.logicalHeight);
+ int larger = Math.max(info.logicalWidth, info.logicalHeight);
+ if (smaller < 720 || larger < 1280) {
+ return RESOLUTION_SD;
+ } else if (smaller < 1080 || larger < 1920) {
+ return RESOLUTION_HD;
+ } else if (smaller < 1440 || larger < 2560) {
+ return RESOLUTION_FHD;
+ } else {
+ return RESOLUTION_QHD;
+ }
+ }
+
+ /**
+ * Wrapper around the final {@link DisplayManagerGlobal} class.
+ * @hide
+ */
+ @VisibleForTesting
+ public interface DisplayInterface {
+ /** Reurns an implementation wrapping {@link DisplayManagerGlobal}. */
+ static DisplayInterface getDefault(@Nullable Handler handler) {
+ DisplayManagerGlobal manager = DisplayManagerGlobal.getInstance();
+ return new DisplayInterface() {
+ @Override
+ public void registerDisplayListener(DisplayManager.DisplayListener listener) {
+ manager.registerDisplayListener(listener, handler,
+ DisplayManager.EVENT_FLAG_DISPLAY_ADDED
+ | DisplayManager.EVENT_FLAG_DISPLAY_CHANGED);
+ }
+
+ @Override
+ public DisplayInfo getDisplayInfo(int displayId) {
+ return manager.getDisplayInfo(displayId);
+ }
+ };
+ }
+
+ /** {@see DisplayManagerGlobal#registerDisplayListener} */
+ void registerDisplayListener(DisplayManager.DisplayListener listener);
+ /** {@see DisplayManagerGlobal#getDisplayInfo} */
+ DisplayInfo getDisplayInfo(int displayId);
+ }
+}
diff --git a/core/java/com/android/internal/jank/FrameTracker.java b/core/java/com/android/internal/jank/FrameTracker.java
index 48343803..e4195d2 100644
--- a/core/java/com/android/internal/jank/FrameTracker.java
+++ b/core/java/com/android/internal/jank/FrameTracker.java
@@ -100,6 +100,7 @@
private final Session mSession;
private final ViewRootWrapper mViewRoot;
private final SurfaceControlWrapper mSurfaceControlWrapper;
+ private final int mDisplayId;
private final ViewRootImpl.SurfaceChangedCallback mSurfaceChangedCallback;
private final Handler mHandler;
private final ChoreographerWrapper mChoreographer;
@@ -213,6 +214,7 @@
mTraceThresholdMissedFrames = traceThresholdMissedFrames;
mTraceThresholdFrameTimeMillis = traceThresholdFrameTimeMillis;
mListener = listener;
+ mDisplayId = config.getDisplayId();
if (mSurfaceOnly) {
mSurfaceControl = config.getSurfaceControl();
@@ -625,6 +627,7 @@
if (mSession.logToStatsd()) {
mStatsLog.write(
FrameworkStatsLog.UI_INTERACTION_FRAME_INFO_REPORTED,
+ mDisplayId,
mSession.getStatsdInteractionType(),
totalFramesCount,
missedFramesCount,
@@ -785,9 +788,17 @@
}
public static class StatsLogWrapper {
- public void write(int code,
+ private final DisplayResolutionTracker mDisplayResolutionTracker;
+
+ public StatsLogWrapper(DisplayResolutionTracker displayResolutionTracker) {
+ mDisplayResolutionTracker = displayResolutionTracker;
+ }
+
+ /** {@see FrameworkStatsLog#write) */
+ public void write(int code, int displayId,
int arg1, long arg2, long arg3, long arg4, long arg5, long arg6, long arg7) {
- FrameworkStatsLog.write(code, arg1, arg2, arg3, arg4, arg5, arg6, arg7);
+ FrameworkStatsLog.write(code, arg1, arg2, arg3, arg4, arg5, arg6, arg7,
+ mDisplayResolutionTracker.getResolution(displayId));
}
}
diff --git a/core/java/com/android/internal/jank/InteractionJankMonitor.java b/core/java/com/android/internal/jank/InteractionJankMonitor.java
index fc4e041..b5991b3 100644
--- a/core/java/com/android/internal/jank/InteractionJankMonitor.java
+++ b/core/java/com/android/internal/jank/InteractionJankMonitor.java
@@ -306,6 +306,7 @@
@GuardedBy("mLock")
private final SparseArray<Runnable> mTimeoutActions;
private final HandlerThread mWorker;
+ private final DisplayResolutionTracker mDisplayResolutionTracker;
private final Object mLock = new Object();
private volatile boolean mEnabled = DEFAULT_ENABLED;
@@ -408,6 +409,7 @@
mWorker = worker;
mWorker.start();
mSamplingInterval = DEFAULT_SAMPLING_INTERVAL;
+ mDisplayResolutionTracker = new DisplayResolutionTracker(worker.getThreadHandler());
// Post initialization to the background in case we're running on the main
// thread.
@@ -443,7 +445,8 @@
final FrameMetricsWrapper frameMetrics = new FrameMetricsWrapper();
return new FrameTracker(this, session, config.getHandler(), threadedRenderer, viewRoot,
- surfaceControl, choreographer, frameMetrics, new FrameTracker.StatsLogWrapper(),
+ surfaceControl, choreographer, frameMetrics,
+ new FrameTracker.StatsLogWrapper(mDisplayResolutionTracker),
mTraceThresholdMissedFrames, mTraceThresholdFrameTimeMillis,
eventsListener, config);
}
@@ -1098,6 +1101,14 @@
public Handler getHandler() {
return mHandler;
}
+
+ /**
+ * @return the ID of the display this interaction in on.
+ */
+ @VisibleForTesting
+ public int getDisplayId() {
+ return (mSurfaceOnly ? mContext.getDisplay() : mView.getDisplay()).getDisplayId();
+ }
}
/**
diff --git a/core/java/com/android/internal/os/Zygote.java b/core/java/com/android/internal/os/Zygote.java
index b1e7d15..ea5f0b2 100644
--- a/core/java/com/android/internal/os/Zygote.java
+++ b/core/java/com/android/internal/os/Zygote.java
@@ -1001,16 +1001,24 @@
}
/**
+ * This will enable jdwp by default for all apps. It is OK to cache this property
+ * because we expect to reboot the system whenever this property changes
+ */
+ private static final boolean ENABLE_JDWP = SystemProperties.get(
+ "persist.debuggable.dalvik.vm.jdwp.enabled").equals("1");
+
+ /**
* Applies debugger system properties to the zygote arguments.
*
- * If "ro.debuggable" is "1", all apps are debuggable. Otherwise,
- * the debugger state is specified via the "--enable-jdwp" flag
- * in the spawn request.
+ * For eng builds all apps are debuggable. On userdebug and user builds
+ * if persist.debuggable.dalvik.vm.jdwp.enabled is 1 all apps are
+ * debuggable. Otherwise, the debugger state is specified via the
+ * "--enable-jdwp" flag in the spawn request.
*
* @param args non-null; zygote spawner args
*/
static void applyDebuggerSystemProperty(ZygoteArguments args) {
- if (RoSystemProperties.DEBUGGABLE) {
+ if (Build.IS_ENG || ENABLE_JDWP) {
args.mRuntimeFlags |= Zygote.DEBUG_ENABLE_JDWP;
}
}
diff --git a/core/jni/com_android_internal_os_Zygote.cpp b/core/jni/com_android_internal_os_Zygote.cpp
index cbc3462..550259f 100644
--- a/core/jni/com_android_internal_os_Zygote.cpp
+++ b/core/jni/com_android_internal_os_Zygote.cpp
@@ -1277,68 +1277,80 @@
}
closedir(dir);
- // Prepare default dirs for user 0 as user 0 always exists.
- int result = symlink("/data/data", "/data/user/0");
- if (result != 0) {
- fail_fn(CREATE_ERROR("Failed to create symlink /data/user/0 %s", strerror(errno)));
- }
- PrepareDirIfNotPresent("/data/user_de/0", DEFAULT_DATA_DIR_PERMISSION,
- AID_ROOT, AID_ROOT, fail_fn);
-
- for (int i = 0; i < size; i += 3) {
- std::string const & packageName = merged_data_info_list[i];
- std::string const & volUuid = merged_data_info_list[i + 1];
- std::string const & inode = merged_data_info_list[i + 2];
-
- std::string::size_type sz;
- long long ceDataInode = std::stoll(inode, &sz);
-
- std::string actualCePath, actualDePath;
- if (volUuid.compare("null") != 0) {
- // Volume that is stored in /mnt/expand
- char volPath[PATH_MAX];
- char volCePath[PATH_MAX];
- char volDePath[PATH_MAX];
- char volCeUserPath[PATH_MAX];
- char volDeUserPath[PATH_MAX];
-
- snprintf(volPath, PATH_MAX, "/mnt/expand/%s", volUuid.c_str());
- snprintf(volCePath, PATH_MAX, "%s/user", volPath);
- snprintf(volDePath, PATH_MAX, "%s/user_de", volPath);
- snprintf(volCeUserPath, PATH_MAX, "%s/%d", volCePath, userId);
- snprintf(volDeUserPath, PATH_MAX, "%s/%d", volDePath, userId);
-
- PrepareDirIfNotPresent(volPath, DEFAULT_DATA_DIR_PERMISSION, AID_ROOT, AID_ROOT, fail_fn);
- PrepareDirIfNotPresent(volCePath, DEFAULT_DATA_DIR_PERMISSION, AID_ROOT, AID_ROOT, fail_fn);
- PrepareDirIfNotPresent(volDePath, DEFAULT_DATA_DIR_PERMISSION, AID_ROOT, AID_ROOT, fail_fn);
- PrepareDirIfNotPresent(volCeUserPath, DEFAULT_DATA_DIR_PERMISSION, AID_ROOT, AID_ROOT,
- fail_fn);
- PrepareDirIfNotPresent(volDeUserPath, DEFAULT_DATA_DIR_PERMISSION, AID_ROOT, AID_ROOT,
- fail_fn);
-
- actualCePath = volCeUserPath;
- actualDePath = volDeUserPath;
- } else {
- // Internal volume that stored in /data
- char internalCeUserPath[PATH_MAX];
- char internalDeUserPath[PATH_MAX];
- snprintf(internalCeUserPath, PATH_MAX, "/data/user/%d", userId);
- snprintf(internalDeUserPath, PATH_MAX, "/data/user_de/%d", userId);
- // If it's not user 0, create /data/user/$USER.
- if (userId == 0) {
- actualCePath = internalLegacyCePath;
- } else {
- PrepareDirIfNotPresent(internalCeUserPath, DEFAULT_DATA_DIR_PERMISSION,
- AID_ROOT, AID_ROOT, fail_fn);
- actualCePath = internalCeUserPath;
+ // No bind mounting of app data should occur in the case of a sandbox process since SDK sandboxes
+ // should not be able to read app data. Tmpfs was mounted however since a sandbox should not have
+ // access to app data.
+ appid_t appId = multiuser_get_app_id(uid);
+ bool isSdkSandboxProcess =
+ (appId >= AID_SDK_SANDBOX_PROCESS_START && appId <= AID_SDK_SANDBOX_PROCESS_END);
+ if (!isSdkSandboxProcess) {
+ // Prepare default dirs for user 0 as user 0 always exists.
+ int result = symlink("/data/data", "/data/user/0");
+ if (result != 0) {
+ fail_fn(CREATE_ERROR("Failed to create symlink /data/user/0 %s", strerror(errno)));
}
- PrepareDirIfNotPresent(internalDeUserPath, DEFAULT_DATA_DIR_PERMISSION,
- AID_ROOT, AID_ROOT, fail_fn);
- actualDePath = internalDeUserPath;
- }
- isolateAppDataPerPackage(userId, packageName, volUuid, ceDataInode,
- actualCePath, actualDePath, fail_fn);
+ PrepareDirIfNotPresent("/data/user_de/0", DEFAULT_DATA_DIR_PERMISSION, AID_ROOT, AID_ROOT,
+ fail_fn);
+
+ for (int i = 0; i < size; i += 3) {
+ std::string const& packageName = merged_data_info_list[i];
+ std::string const& volUuid = merged_data_info_list[i + 1];
+ std::string const& inode = merged_data_info_list[i + 2];
+
+ std::string::size_type sz;
+ long long ceDataInode = std::stoll(inode, &sz);
+
+ std::string actualCePath, actualDePath;
+ if (volUuid.compare("null") != 0) {
+ // Volume that is stored in /mnt/expand
+ char volPath[PATH_MAX];
+ char volCePath[PATH_MAX];
+ char volDePath[PATH_MAX];
+ char volCeUserPath[PATH_MAX];
+ char volDeUserPath[PATH_MAX];
+
+ snprintf(volPath, PATH_MAX, "/mnt/expand/%s", volUuid.c_str());
+ snprintf(volCePath, PATH_MAX, "%s/user", volPath);
+ snprintf(volDePath, PATH_MAX, "%s/user_de", volPath);
+ snprintf(volCeUserPath, PATH_MAX, "%s/%d", volCePath, userId);
+ snprintf(volDeUserPath, PATH_MAX, "%s/%d", volDePath, userId);
+
+ PrepareDirIfNotPresent(volPath, DEFAULT_DATA_DIR_PERMISSION, AID_ROOT, AID_ROOT,
+ fail_fn);
+ PrepareDirIfNotPresent(volCePath, DEFAULT_DATA_DIR_PERMISSION, AID_ROOT, AID_ROOT,
+ fail_fn);
+ PrepareDirIfNotPresent(volDePath, DEFAULT_DATA_DIR_PERMISSION, AID_ROOT, AID_ROOT,
+ fail_fn);
+ PrepareDirIfNotPresent(volCeUserPath, DEFAULT_DATA_DIR_PERMISSION, AID_ROOT, AID_ROOT,
+ fail_fn);
+ PrepareDirIfNotPresent(volDeUserPath, DEFAULT_DATA_DIR_PERMISSION, AID_ROOT, AID_ROOT,
+ fail_fn);
+
+ actualCePath = volCeUserPath;
+ actualDePath = volDeUserPath;
+ } else {
+ // Internal volume that stored in /data
+ char internalCeUserPath[PATH_MAX];
+ char internalDeUserPath[PATH_MAX];
+ snprintf(internalCeUserPath, PATH_MAX, "/data/user/%d", userId);
+ snprintf(internalDeUserPath, PATH_MAX, "/data/user_de/%d", userId);
+ // If it's not user 0, create /data/user/$USER.
+ if (userId == 0) {
+ actualCePath = internalLegacyCePath;
+ } else {
+ PrepareDirIfNotPresent(internalCeUserPath, DEFAULT_DATA_DIR_PERMISSION, AID_ROOT,
+ AID_ROOT, fail_fn);
+ actualCePath = internalCeUserPath;
+ }
+ PrepareDirIfNotPresent(internalDeUserPath, DEFAULT_DATA_DIR_PERMISSION, AID_ROOT,
+ AID_ROOT, fail_fn);
+ actualDePath = internalDeUserPath;
+ }
+ isolateAppDataPerPackage(userId, packageName, volUuid, ceDataInode, actualCePath,
+ actualDePath, fail_fn);
+ }
}
+
// We set the label AFTER everything is done, as we are applying
// the file operations on tmpfs. If we set the label when we mount
// tmpfs, SELinux will not happy as we are changing system_data_files.
@@ -1379,6 +1391,167 @@
freecon(dataFileContext);
}
+/**
+ * Without sdk sandbox data isolation, the sandbox could detect if another app is installed on the
+ * system by "touching" other data directories like /data/misc_ce/0/sdksandbox/com.whatsapp, similar
+ * to apps without app data isolation (see {@link #isolateAppData()}).
+ *
+ * To prevent this, tmpfs is mounted onto misc_ce and misc_de directories on all possible volumes in
+ * a separate mount namespace. The sandbox directory path is then created containing the name of the
+ * client app package associated with the sdk sandbox. The contents for this (sdk level storage and
+ * shared sdk storage) are bind mounted from the sandbox data mirror.
+ */
+static void isolateSdkSandboxData(JNIEnv* env, jobjectArray pkg_data_info_list, uid_t uid,
+ const char* process_name, jstring managed_nice_name,
+ fail_fn_t fail_fn) {
+ const userid_t userId = multiuser_get_user_id(uid);
+
+ int size = (pkg_data_info_list != nullptr) ? env->GetArrayLength(pkg_data_info_list) : 0;
+ // The sandbox should only have information of one associated client app (package, uuid, inode)
+ if (size != 3) {
+ fail_fn(CREATE_ERROR(
+ "Unable to isolate sandbox data, incorrect associated app information"));
+ }
+
+ auto extract_fn = [env, process_name, managed_nice_name,
+ pkg_data_info_list](int info_list_idx) {
+ jstring jstr = (jstring)(env->GetObjectArrayElement(pkg_data_info_list, info_list_idx));
+ return ExtractJString(env, process_name, managed_nice_name, jstr).value();
+ };
+ std::string packageName = extract_fn(0);
+ std::string volUuid = extract_fn(1);
+
+ char internalCePath[PATH_MAX];
+ char internalDePath[PATH_MAX];
+ char externalPrivateMountPath[PATH_MAX];
+ snprintf(internalCePath, PATH_MAX, "/data/misc_ce");
+ snprintf(internalDePath, PATH_MAX, "/data/misc_de");
+ snprintf(externalPrivateMountPath, PATH_MAX, "/mnt/expand");
+
+ char ceUserPath[PATH_MAX];
+ char deUserPath[PATH_MAX];
+ if (volUuid != "null") {
+ snprintf(ceUserPath, PATH_MAX, "%s/%s/misc_ce/%d", externalPrivateMountPath,
+ volUuid.c_str(), userId);
+ snprintf(deUserPath, PATH_MAX, "%s/%s/misc_de/%d", externalPrivateMountPath,
+ volUuid.c_str(), userId);
+ } else {
+ snprintf(ceUserPath, PATH_MAX, "%s/%d", internalCePath, userId);
+ snprintf(deUserPath, PATH_MAX, "%s/%d", internalDePath, userId);
+ }
+
+ char ceSandboxPath[PATH_MAX];
+ char deSandboxPath[PATH_MAX];
+ snprintf(ceSandboxPath, PATH_MAX, "%s/sdksandbox", ceUserPath);
+ snprintf(deSandboxPath, PATH_MAX, "%s/sdksandbox", deUserPath);
+
+ // If the client app using the sandbox has been installed when the device is locked and the
+ // sandbox starts up when the device is locked, sandbox storage might not have been created.
+ // In that case, mount tmpfs for data isolation, but don't bind mount.
+ bool bindMountCeSandboxDataDirs = true;
+ bool bindMountDeSandboxDataDirs = true;
+ if (access(ceSandboxPath, F_OK) != 0) {
+ bindMountCeSandboxDataDirs = false;
+ }
+ if (access(deSandboxPath, F_OK) != 0) {
+ bindMountDeSandboxDataDirs = false;
+ }
+
+ char* context = nullptr;
+ char* userContext = nullptr;
+ char* sandboxContext = nullptr;
+ if (getfilecon(internalDePath, &context) < 0) {
+ fail_fn(CREATE_ERROR("Unable to getfilecon on %s %s", internalDePath, strerror(errno)));
+ }
+ if (bindMountDeSandboxDataDirs) {
+ if (getfilecon(deUserPath, &userContext) < 0) {
+ fail_fn(CREATE_ERROR("Unable to getfilecon on %s %s", deUserPath, strerror(errno)));
+ }
+ if (getfilecon(deSandboxPath, &sandboxContext) < 0) {
+ fail_fn(CREATE_ERROR("Unable to getfilecon on %s %s", deSandboxPath, strerror(errno)));
+ }
+ }
+
+ MountAppDataTmpFs(internalCePath, fail_fn);
+ MountAppDataTmpFs(internalDePath, fail_fn);
+
+ // Mount tmpfs on all external volumes
+ DIR* dir = opendir(externalPrivateMountPath);
+ if (dir == nullptr) {
+ fail_fn(CREATE_ERROR("Failed to opendir %s", externalPrivateMountPath));
+ }
+ struct dirent* ent;
+ while ((ent = readdir(dir))) {
+ if (strcmp(ent->d_name, ".") == 0 || strcmp(ent->d_name, "..") == 0) continue;
+ if (ent->d_type != DT_DIR) {
+ fail_fn(CREATE_ERROR("Unexpected type: %d %s", ent->d_type, ent->d_name));
+ }
+ auto volPath = StringPrintf("%s/%s", externalPrivateMountPath, ent->d_name);
+ auto externalCePath = StringPrintf("%s/misc_ce", volPath.c_str());
+ auto externalDePath = StringPrintf("%s/misc_de", volPath.c_str());
+
+ WaitUntilDirReady(externalCePath.c_str(), fail_fn);
+ MountAppDataTmpFs(externalCePath.c_str(), fail_fn);
+ WaitUntilDirReady(externalDePath.c_str(), fail_fn);
+ MountAppDataTmpFs(externalDePath.c_str(), fail_fn);
+ }
+ closedir(dir);
+
+ char mirrorCeSandboxPath[PATH_MAX];
+ char mirrorDeSandboxPath[PATH_MAX];
+ snprintf(mirrorCeSandboxPath, PATH_MAX, "/data_mirror/misc_ce/%s/%d/sdksandbox",
+ volUuid.c_str(), userId);
+ snprintf(mirrorDeSandboxPath, PATH_MAX, "/data_mirror/misc_de/%s/%d/sdksandbox",
+ volUuid.c_str(), userId);
+
+ if (bindMountCeSandboxDataDirs) {
+ PrepareDir(ceUserPath, DEFAULT_DATA_DIR_PERMISSION, AID_ROOT, AID_ROOT, fail_fn);
+ PrepareDir(ceSandboxPath, DEFAULT_DATA_DIR_PERMISSION, AID_ROOT, AID_ROOT, fail_fn);
+ // TODO(b/231322885): Use inode numbers to find the correct app path when the device locked.
+ createAndMountAppData(packageName, packageName, mirrorCeSandboxPath, ceSandboxPath, fail_fn,
+ true /*call_fail_fn*/);
+
+ relabelDir(ceSandboxPath, sandboxContext, fail_fn);
+ relabelDir(ceUserPath, userContext, fail_fn);
+ }
+ if (bindMountDeSandboxDataDirs) {
+ PrepareDir(deUserPath, DEFAULT_DATA_DIR_PERMISSION, AID_ROOT, AID_ROOT, fail_fn);
+ PrepareDir(deSandboxPath, DEFAULT_DATA_DIR_PERMISSION, AID_ROOT, AID_ROOT, fail_fn);
+ createAndMountAppData(packageName, packageName, mirrorDeSandboxPath, deSandboxPath, fail_fn,
+ true /*call_fail_fn*/);
+
+ relabelDir(deSandboxPath, sandboxContext, fail_fn);
+ relabelDir(deUserPath, userContext, fail_fn);
+ }
+
+ // We set the label AFTER everything is done, as we are applying
+ // the file operations on tmpfs. If we set the label when we mount
+ // tmpfs, SELinux will not happy as we are changing system_data_files.
+ relabelDir(internalCePath, context, fail_fn);
+ relabelDir(internalDePath, context, fail_fn);
+
+ // Relabel CE and DE dirs under /mnt/expand
+ dir = opendir(externalPrivateMountPath);
+ if (dir == nullptr) {
+ fail_fn(CREATE_ERROR("Failed to opendir %s", externalPrivateMountPath));
+ }
+ while ((ent = readdir(dir))) {
+ if (strcmp(ent->d_name, ".") == 0 || strcmp(ent->d_name, "..") == 0) continue;
+ auto volPath = StringPrintf("%s/%s", externalPrivateMountPath, ent->d_name);
+ auto externalCePath = StringPrintf("%s/misc_ce", volPath.c_str());
+ auto externalDePath = StringPrintf("%s/misc_de", volPath.c_str());
+ relabelDir(externalCePath.c_str(), context, fail_fn);
+ relabelDir(externalDePath.c_str(), context, fail_fn);
+ }
+ closedir(dir);
+
+ if (bindMountDeSandboxDataDirs) {
+ freecon(sandboxContext);
+ freecon(userContext);
+ }
+ freecon(context);
+}
+
static void insertPackagesToMergedList(JNIEnv* env,
std::vector<std::string>& merged_data_info_list,
jobjectArray data_info_list, const char* process_name,
@@ -1444,6 +1617,13 @@
MountAppDataTmpFs(kCurProfileDirPath, fail_fn);
MountAppDataTmpFs(kRefProfileDirPath, fail_fn);
+ // Sandbox processes do not have JIT profile, so no data needs to be bind mounted. However, it
+ // should still not have access to JIT profile, so tmpfs is mounted.
+ appid_t appId = multiuser_get_app_id(uid);
+ if (appId >= AID_SDK_SANDBOX_PROCESS_START && appId <= AID_SDK_SANDBOX_PROCESS_END) {
+ return;
+ }
+
// Create profile directory for this user.
std::string actualCurUserProfile = StringPrintf("%s/%d", kCurProfileDirPath, user_id);
PrepareDir(actualCurUserProfile, DEFAULT_DATA_DIR_PERMISSION, AID_ROOT, AID_ROOT, fail_fn);
@@ -1596,9 +1776,16 @@
// Make sure app is running in its own mount namespace before isolating its data directories.
ensureInAppMountNamespace(fail_fn);
- // Sandbox data and jit profile directories by overlaying a tmpfs on those dirs and bind
- // mount all related packages separately.
+ // Isolate app data, jit profile and sandbox data directories by overlaying a tmpfs on those
+ // dirs and bind mount all related packages separately.
if (mount_data_dirs) {
+ // Sdk sandbox data isolation does not need to occur for app processes since sepolicy
+ // prevents access to sandbox data anyway.
+ appid_t appId = multiuser_get_app_id(uid);
+ if (appId >= AID_SDK_SANDBOX_PROCESS_START && appId <= AID_SDK_SANDBOX_PROCESS_END) {
+ isolateSdkSandboxData(env, pkg_data_info_list, uid, process_name, managed_nice_name,
+ fail_fn);
+ }
isolateAppData(env, pkg_data_info_list, allowlisted_data_info_list, uid, process_name,
managed_nice_name, fail_fn);
isolateJitProfile(env, pkg_data_info_list, uid, process_name, managed_nice_name, fail_fn);
diff --git a/core/proto/android/os/incident.proto b/core/proto/android/os/incident.proto
index 57026d9..4bbfee2 100644
--- a/core/proto/android/os/incident.proto
+++ b/core/proto/android/os/incident.proto
@@ -61,7 +61,6 @@
import "frameworks/base/core/proto/android/privacy.proto";
import "frameworks/base/core/proto/android/section.proto";
import "frameworks/base/proto/src/ipconnectivity.proto";
-import "packages/modules/Connectivity/framework/proto/netstats.proto";
import "packages/modules/Permission/service/proto/role_service.proto";
package android.os;
@@ -247,11 +246,7 @@
(section).args = "fingerprint --proto --incident"
];
- optional android.service.NetworkStatsServiceDumpProto netstats = 3001 [
- (section).type = SECTION_DUMPSYS,
- (section).args = "netstats --proto",
- (section).userdebug_and_eng_only = true
- ];
+ reserved 3001;
optional android.providers.settings.SettingsServiceDumpProto settings = 3002 [
(section).type = SECTION_DUMPSYS,
diff --git a/core/res/OWNERS b/core/res/OWNERS
index c54638a..d8fc218 100644
--- a/core/res/OWNERS
+++ b/core/res/OWNERS
@@ -37,7 +37,7 @@
per-file res/values/dimens_car.xml = file:/platform/packages/services/Car:/OWNERS
# Wear
-per-file res/*-watch/* = file:/platform/frameworks/opt/wear:/OWNERS
+per-file res/*-watch/* = file:/WEAR_OWNERS
# PowerProfile
per-file res/xml/power_profile.xml = file:/BATTERY_STATS_OWNERS
diff --git a/core/res/res/values-af/strings.xml b/core/res/res/values-af/strings.xml
index e5b97f7..9b997bf 100644
--- a/core/res/res/values-af/strings.xml
+++ b/core/res/res/values-af/strings.xml
@@ -1611,7 +1611,7 @@
<string name="default_audio_route_name" product="tv" msgid="4908971385068087367">"TV"</string>
<string name="default_audio_route_name" product="default" msgid="9213546147739983977">"Foon"</string>
<string name="default_audio_route_name_dock_speakers" msgid="1551166029093995289">"Dokluidsprekers"</string>
- <string name="default_audio_route_name_hdmi" msgid="5474470558160717850">"HDMI"</string>
+ <string name="default_audio_route_name_external_device" msgid="5474470558160717850">"HDMI"</string>
<string name="default_audio_route_name_headphones" msgid="6954070994792640762">"Oorfone"</string>
<string name="default_audio_route_name_usb" msgid="895668743163316932">"USB"</string>
<string name="default_audio_route_category_name" msgid="5241740395748134483">"Stelsel"</string>
diff --git a/core/res/res/values-am/strings.xml b/core/res/res/values-am/strings.xml
index c291d9b..698bce4 100644
--- a/core/res/res/values-am/strings.xml
+++ b/core/res/res/values-am/strings.xml
@@ -1611,7 +1611,7 @@
<string name="default_audio_route_name" product="tv" msgid="4908971385068087367">"ቴሌቪዥን"</string>
<string name="default_audio_route_name" product="default" msgid="9213546147739983977">"ስልክ"</string>
<string name="default_audio_route_name_dock_speakers" msgid="1551166029093995289">"የትከል ድምፅ ማጉያዎች"</string>
- <string name="default_audio_route_name_hdmi" msgid="5474470558160717850">"ኤችዲኤምአይ"</string>
+ <string name="default_audio_route_name_external_device" msgid="5474470558160717850">"ኤችዲኤምአይ"</string>
<string name="default_audio_route_name_headphones" msgid="6954070994792640762">"የጆሮ ማዳመጫዎች"</string>
<string name="default_audio_route_name_usb" msgid="895668743163316932">"ዩ ኤስ ቢ"</string>
<string name="default_audio_route_category_name" msgid="5241740395748134483">"ስርዓት"</string>
diff --git a/core/res/res/values-ar/strings.xml b/core/res/res/values-ar/strings.xml
index 39f6872..82fc943 100644
--- a/core/res/res/values-ar/strings.xml
+++ b/core/res/res/values-ar/strings.xml
@@ -1615,7 +1615,7 @@
<string name="default_audio_route_name" product="tv" msgid="4908971385068087367">"التلفزيون"</string>
<string name="default_audio_route_name" product="default" msgid="9213546147739983977">"الهاتف"</string>
<string name="default_audio_route_name_dock_speakers" msgid="1551166029093995289">"مكبرات صوت للإرساء"</string>
- <string name="default_audio_route_name_hdmi" msgid="5474470558160717850">"HDMI"</string>
+ <string name="default_audio_route_name_external_device" msgid="5474470558160717850">"HDMI"</string>
<string name="default_audio_route_name_headphones" msgid="6954070994792640762">"سماعات رأس"</string>
<string name="default_audio_route_name_usb" msgid="895668743163316932">"USB"</string>
<string name="default_audio_route_category_name" msgid="5241740395748134483">"النظام"</string>
diff --git a/core/res/res/values-as/strings.xml b/core/res/res/values-as/strings.xml
index d6a4bb0..93957e5 100644
--- a/core/res/res/values-as/strings.xml
+++ b/core/res/res/values-as/strings.xml
@@ -1611,7 +1611,7 @@
<string name="default_audio_route_name" product="tv" msgid="4908971385068087367">"টিভি"</string>
<string name="default_audio_route_name" product="default" msgid="9213546147739983977">"ফ\'ন"</string>
<string name="default_audio_route_name_dock_speakers" msgid="1551166029093995289">"ড\'ক স্পীকাৰসমূহ"</string>
- <string name="default_audio_route_name_hdmi" msgid="5474470558160717850">"HDMI"</string>
+ <string name="default_audio_route_name_external_device" msgid="5474470558160717850">"HDMI"</string>
<string name="default_audio_route_name_headphones" msgid="6954070994792640762">"হেডফ\'নবোৰ"</string>
<string name="default_audio_route_name_usb" msgid="895668743163316932">"ইউএছবি"</string>
<string name="default_audio_route_category_name" msgid="5241740395748134483">"ছিষ্টেম"</string>
diff --git a/core/res/res/values-az/strings.xml b/core/res/res/values-az/strings.xml
index 370fc6d..c4f3d75 100644
--- a/core/res/res/values-az/strings.xml
+++ b/core/res/res/values-az/strings.xml
@@ -1611,7 +1611,7 @@
<string name="default_audio_route_name" product="tv" msgid="4908971385068087367">"TV"</string>
<string name="default_audio_route_name" product="default" msgid="9213546147739983977">"Telefon"</string>
<string name="default_audio_route_name_dock_speakers" msgid="1551166029093995289">"Dok spikerlər"</string>
- <string name="default_audio_route_name_hdmi" msgid="5474470558160717850">"HDMI"</string>
+ <string name="default_audio_route_name_external_device" msgid="5474470558160717850">"HDMI"</string>
<string name="default_audio_route_name_headphones" msgid="6954070994792640762">"Qulaqlıq"</string>
<string name="default_audio_route_name_usb" msgid="895668743163316932">"USB"</string>
<string name="default_audio_route_category_name" msgid="5241740395748134483">"Sistem"</string>
diff --git a/core/res/res/values-b+sr+Latn/strings.xml b/core/res/res/values-b+sr+Latn/strings.xml
index ef2a68c..bf9c57b 100644
--- a/core/res/res/values-b+sr+Latn/strings.xml
+++ b/core/res/res/values-b+sr+Latn/strings.xml
@@ -1612,7 +1612,7 @@
<string name="default_audio_route_name" product="tv" msgid="4908971385068087367">"TV"</string>
<string name="default_audio_route_name" product="default" msgid="9213546147739983977">"Telefon"</string>
<string name="default_audio_route_name_dock_speakers" msgid="1551166029093995289">"Zvučnici bazne stanice"</string>
- <string name="default_audio_route_name_hdmi" msgid="5474470558160717850">"HDMI"</string>
+ <string name="default_audio_route_name_external_device" msgid="5474470558160717850">"HDMI"</string>
<string name="default_audio_route_name_headphones" msgid="6954070994792640762">"Slušalice"</string>
<string name="default_audio_route_name_usb" msgid="895668743163316932">"USB"</string>
<string name="default_audio_route_category_name" msgid="5241740395748134483">"Sistem"</string>
diff --git a/core/res/res/values-be/strings.xml b/core/res/res/values-be/strings.xml
index 1212c02..1af3c7d 100644
--- a/core/res/res/values-be/strings.xml
+++ b/core/res/res/values-be/strings.xml
@@ -1613,7 +1613,7 @@
<string name="default_audio_route_name" product="tv" msgid="4908971385068087367">"ТБ"</string>
<string name="default_audio_route_name" product="default" msgid="9213546147739983977">"Тэлефон"</string>
<string name="default_audio_route_name_dock_speakers" msgid="1551166029093995289">"Дынамікі станцыi"</string>
- <string name="default_audio_route_name_hdmi" msgid="5474470558160717850">"HDMI"</string>
+ <string name="default_audio_route_name_external_device" msgid="5474470558160717850">"HDMI"</string>
<string name="default_audio_route_name_headphones" msgid="6954070994792640762">"Навушнікі"</string>
<string name="default_audio_route_name_usb" msgid="895668743163316932">"USB"</string>
<string name="default_audio_route_category_name" msgid="5241740395748134483">"Сістэма"</string>
diff --git a/core/res/res/values-bg/strings.xml b/core/res/res/values-bg/strings.xml
index 1007746..4ae1f21 100644
--- a/core/res/res/values-bg/strings.xml
+++ b/core/res/res/values-bg/strings.xml
@@ -1611,7 +1611,7 @@
<string name="default_audio_route_name" product="tv" msgid="4908971385068087367">"Телевизор"</string>
<string name="default_audio_route_name" product="default" msgid="9213546147739983977">"Телефон"</string>
<string name="default_audio_route_name_dock_speakers" msgid="1551166029093995289">"Докинг станц.: Високогов."</string>
- <string name="default_audio_route_name_hdmi" msgid="5474470558160717850">"HDMI"</string>
+ <string name="default_audio_route_name_external_device" msgid="5474470558160717850">"HDMI"</string>
<string name="default_audio_route_name_headphones" msgid="6954070994792640762">"Слушалки"</string>
<string name="default_audio_route_name_usb" msgid="895668743163316932">"USB"</string>
<string name="default_audio_route_category_name" msgid="5241740395748134483">"Система"</string>
diff --git a/core/res/res/values-bn/strings.xml b/core/res/res/values-bn/strings.xml
index 96acf7f..2aac0c9 100644
--- a/core/res/res/values-bn/strings.xml
+++ b/core/res/res/values-bn/strings.xml
@@ -1611,7 +1611,7 @@
<string name="default_audio_route_name" product="tv" msgid="4908971385068087367">"টিভি"</string>
<string name="default_audio_route_name" product="default" msgid="9213546147739983977">"ফোন"</string>
<string name="default_audio_route_name_dock_speakers" msgid="1551166029093995289">"ডক স্পিকার"</string>
- <string name="default_audio_route_name_hdmi" msgid="5474470558160717850">"HDMI"</string>
+ <string name="default_audio_route_name_external_device" msgid="5474470558160717850">"HDMI"</string>
<string name="default_audio_route_name_headphones" msgid="6954070994792640762">"হেডফোন"</string>
<string name="default_audio_route_name_usb" msgid="895668743163316932">"USB"</string>
<string name="default_audio_route_category_name" msgid="5241740395748134483">"সিস্টেম"</string>
diff --git a/core/res/res/values-bs/strings.xml b/core/res/res/values-bs/strings.xml
index f7a5f38..3c87b0d 100644
--- a/core/res/res/values-bs/strings.xml
+++ b/core/res/res/values-bs/strings.xml
@@ -1612,7 +1612,7 @@
<string name="default_audio_route_name" product="tv" msgid="4908971385068087367">"TV"</string>
<string name="default_audio_route_name" product="default" msgid="9213546147739983977">"Telefon"</string>
<string name="default_audio_route_name_dock_speakers" msgid="1551166029093995289">"Zvučnici priključne stanice"</string>
- <string name="default_audio_route_name_hdmi" msgid="5474470558160717850">"HDMI"</string>
+ <string name="default_audio_route_name_external_device" msgid="5474470558160717850">"HDMI"</string>
<string name="default_audio_route_name_headphones" msgid="6954070994792640762">"Slušalice"</string>
<string name="default_audio_route_name_usb" msgid="895668743163316932">"USB"</string>
<string name="default_audio_route_category_name" msgid="5241740395748134483">"Sistem"</string>
diff --git a/core/res/res/values-ca/strings.xml b/core/res/res/values-ca/strings.xml
index 4819c9eb..317c004 100644
--- a/core/res/res/values-ca/strings.xml
+++ b/core/res/res/values-ca/strings.xml
@@ -1611,7 +1611,7 @@
<string name="default_audio_route_name" product="tv" msgid="4908971385068087367">"Televisor"</string>
<string name="default_audio_route_name" product="default" msgid="9213546147739983977">"Telèfon"</string>
<string name="default_audio_route_name_dock_speakers" msgid="1551166029093995289">"Altaveus de la base"</string>
- <string name="default_audio_route_name_hdmi" msgid="5474470558160717850">"HDMI"</string>
+ <string name="default_audio_route_name_external_device" msgid="5474470558160717850">"HDMI"</string>
<string name="default_audio_route_name_headphones" msgid="6954070994792640762">"Auriculars"</string>
<string name="default_audio_route_name_usb" msgid="895668743163316932">"USB"</string>
<string name="default_audio_route_category_name" msgid="5241740395748134483">"Sistema"</string>
diff --git a/core/res/res/values-cs/strings.xml b/core/res/res/values-cs/strings.xml
index 83c4afb..cbd2df6 100644
--- a/core/res/res/values-cs/strings.xml
+++ b/core/res/res/values-cs/strings.xml
@@ -1613,7 +1613,7 @@
<string name="default_audio_route_name" product="tv" msgid="4908971385068087367">"Televize"</string>
<string name="default_audio_route_name" product="default" msgid="9213546147739983977">"Telefon"</string>
<string name="default_audio_route_name_dock_speakers" msgid="1551166029093995289">"Reproduktory doku"</string>
- <string name="default_audio_route_name_hdmi" msgid="5474470558160717850">"HDMI"</string>
+ <string name="default_audio_route_name_external_device" msgid="5474470558160717850">"HDMI"</string>
<string name="default_audio_route_name_headphones" msgid="6954070994792640762">"Sluchátka"</string>
<string name="default_audio_route_name_usb" msgid="895668743163316932">"USB"</string>
<string name="default_audio_route_category_name" msgid="5241740395748134483">"Systém"</string>
diff --git a/core/res/res/values-da/strings.xml b/core/res/res/values-da/strings.xml
index 672e7c7..083c42c 100644
--- a/core/res/res/values-da/strings.xml
+++ b/core/res/res/values-da/strings.xml
@@ -1611,7 +1611,7 @@
<string name="default_audio_route_name" product="tv" msgid="4908971385068087367">"Tv"</string>
<string name="default_audio_route_name" product="default" msgid="9213546147739983977">"Telefon"</string>
<string name="default_audio_route_name_dock_speakers" msgid="1551166029093995289">"Dockstationens højttalere"</string>
- <string name="default_audio_route_name_hdmi" msgid="5474470558160717850">"HDMI"</string>
+ <string name="default_audio_route_name_external_device" msgid="5474470558160717850">"HDMI"</string>
<string name="default_audio_route_name_headphones" msgid="6954070994792640762">"Hovedtelefoner"</string>
<string name="default_audio_route_name_usb" msgid="895668743163316932">"USB"</string>
<string name="default_audio_route_category_name" msgid="5241740395748134483">"System"</string>
diff --git a/core/res/res/values-de/strings.xml b/core/res/res/values-de/strings.xml
index 01e3d45..fc8eadaf 100644
--- a/core/res/res/values-de/strings.xml
+++ b/core/res/res/values-de/strings.xml
@@ -1611,7 +1611,7 @@
<string name="default_audio_route_name" product="tv" msgid="4908971385068087367">"TV"</string>
<string name="default_audio_route_name" product="default" msgid="9213546147739983977">"Telefon"</string>
<string name="default_audio_route_name_dock_speakers" msgid="1551166029093995289">"Dock-Lautsprecher"</string>
- <string name="default_audio_route_name_hdmi" msgid="5474470558160717850">"HDMI"</string>
+ <string name="default_audio_route_name_external_device" msgid="5474470558160717850">"HDMI"</string>
<string name="default_audio_route_name_headphones" msgid="6954070994792640762">"Kopfhörer"</string>
<string name="default_audio_route_name_usb" msgid="895668743163316932">"USB"</string>
<string name="default_audio_route_category_name" msgid="5241740395748134483">"System"</string>
diff --git a/core/res/res/values-el/strings.xml b/core/res/res/values-el/strings.xml
index 0e3c0a1..c76b2b0 100644
--- a/core/res/res/values-el/strings.xml
+++ b/core/res/res/values-el/strings.xml
@@ -1611,7 +1611,7 @@
<string name="default_audio_route_name" product="tv" msgid="4908971385068087367">"Τηλεόραση"</string>
<string name="default_audio_route_name" product="default" msgid="9213546147739983977">"Τηλέφωνο"</string>
<string name="default_audio_route_name_dock_speakers" msgid="1551166029093995289">"Ηχεία βάσης σύνδεσης"</string>
- <string name="default_audio_route_name_hdmi" msgid="5474470558160717850">"HDMI"</string>
+ <string name="default_audio_route_name_external_device" msgid="5474470558160717850">"HDMI"</string>
<string name="default_audio_route_name_headphones" msgid="6954070994792640762">"Ακουστικά"</string>
<string name="default_audio_route_name_usb" msgid="895668743163316932">"USB"</string>
<string name="default_audio_route_category_name" msgid="5241740395748134483">"Σύστημα"</string>
diff --git a/core/res/res/values-en-rAU/strings.xml b/core/res/res/values-en-rAU/strings.xml
index 805e014..8591467 100644
--- a/core/res/res/values-en-rAU/strings.xml
+++ b/core/res/res/values-en-rAU/strings.xml
@@ -1611,7 +1611,7 @@
<string name="default_audio_route_name" product="tv" msgid="4908971385068087367">"TV"</string>
<string name="default_audio_route_name" product="default" msgid="9213546147739983977">"Phone"</string>
<string name="default_audio_route_name_dock_speakers" msgid="1551166029093995289">"Dock speakers"</string>
- <string name="default_audio_route_name_hdmi" msgid="5474470558160717850">"HDMI"</string>
+ <string name="default_audio_route_name_external_device" msgid="5474470558160717850">"HDMI"</string>
<string name="default_audio_route_name_headphones" msgid="6954070994792640762">"Headphones"</string>
<string name="default_audio_route_name_usb" msgid="895668743163316932">"USB"</string>
<string name="default_audio_route_category_name" msgid="5241740395748134483">"System"</string>
diff --git a/core/res/res/values-en-rCA/strings.xml b/core/res/res/values-en-rCA/strings.xml
index 79d3923..08097a5 100644
--- a/core/res/res/values-en-rCA/strings.xml
+++ b/core/res/res/values-en-rCA/strings.xml
@@ -1611,7 +1611,7 @@
<string name="default_audio_route_name" product="tv" msgid="4908971385068087367">"TV"</string>
<string name="default_audio_route_name" product="default" msgid="9213546147739983977">"Phone"</string>
<string name="default_audio_route_name_dock_speakers" msgid="1551166029093995289">"Dock speakers"</string>
- <string name="default_audio_route_name_hdmi" msgid="5474470558160717850">"HDMI"</string>
+ <string name="default_audio_route_name_external_device" msgid="5474470558160717850">"HDMI"</string>
<string name="default_audio_route_name_headphones" msgid="6954070994792640762">"Headphones"</string>
<string name="default_audio_route_name_usb" msgid="895668743163316932">"USB"</string>
<string name="default_audio_route_category_name" msgid="5241740395748134483">"System"</string>
diff --git a/core/res/res/values-en-rGB/strings.xml b/core/res/res/values-en-rGB/strings.xml
index 8054969..bf82587 100644
--- a/core/res/res/values-en-rGB/strings.xml
+++ b/core/res/res/values-en-rGB/strings.xml
@@ -1611,7 +1611,7 @@
<string name="default_audio_route_name" product="tv" msgid="4908971385068087367">"TV"</string>
<string name="default_audio_route_name" product="default" msgid="9213546147739983977">"Phone"</string>
<string name="default_audio_route_name_dock_speakers" msgid="1551166029093995289">"Dock speakers"</string>
- <string name="default_audio_route_name_hdmi" msgid="5474470558160717850">"HDMI"</string>
+ <string name="default_audio_route_name_external_device" msgid="5474470558160717850">"HDMI"</string>
<string name="default_audio_route_name_headphones" msgid="6954070994792640762">"Headphones"</string>
<string name="default_audio_route_name_usb" msgid="895668743163316932">"USB"</string>
<string name="default_audio_route_category_name" msgid="5241740395748134483">"System"</string>
diff --git a/core/res/res/values-en-rIN/strings.xml b/core/res/res/values-en-rIN/strings.xml
index 9d1c6a4..110e68f 100644
--- a/core/res/res/values-en-rIN/strings.xml
+++ b/core/res/res/values-en-rIN/strings.xml
@@ -1611,7 +1611,7 @@
<string name="default_audio_route_name" product="tv" msgid="4908971385068087367">"TV"</string>
<string name="default_audio_route_name" product="default" msgid="9213546147739983977">"Phone"</string>
<string name="default_audio_route_name_dock_speakers" msgid="1551166029093995289">"Dock speakers"</string>
- <string name="default_audio_route_name_hdmi" msgid="5474470558160717850">"HDMI"</string>
+ <string name="default_audio_route_name_external_device" msgid="5474470558160717850">"HDMI"</string>
<string name="default_audio_route_name_headphones" msgid="6954070994792640762">"Headphones"</string>
<string name="default_audio_route_name_usb" msgid="895668743163316932">"USB"</string>
<string name="default_audio_route_category_name" msgid="5241740395748134483">"System"</string>
diff --git a/core/res/res/values-en-rXC/strings.xml b/core/res/res/values-en-rXC/strings.xml
index eae7c27a..ddb93a8 100644
--- a/core/res/res/values-en-rXC/strings.xml
+++ b/core/res/res/values-en-rXC/strings.xml
@@ -1610,7 +1610,7 @@
<string name="default_audio_route_name" product="tv" msgid="4908971385068087367">"TV"</string>
<string name="default_audio_route_name" product="default" msgid="9213546147739983977">"Phone"</string>
<string name="default_audio_route_name_dock_speakers" msgid="1551166029093995289">"Dock speakers"</string>
- <string name="default_audio_route_name_hdmi" msgid="5474470558160717850">"HDMI"</string>
+ <string name="default_audio_route_name_external_device" msgid="5474470558160717850">"HDMI"</string>
<string name="default_audio_route_name_headphones" msgid="6954070994792640762">"Headphones"</string>
<string name="default_audio_route_name_usb" msgid="895668743163316932">"USB"</string>
<string name="default_audio_route_category_name" msgid="5241740395748134483">"System"</string>
diff --git a/core/res/res/values-es-rUS/strings.xml b/core/res/res/values-es-rUS/strings.xml
index f06903b5..933ccfb 100644
--- a/core/res/res/values-es-rUS/strings.xml
+++ b/core/res/res/values-es-rUS/strings.xml
@@ -1612,7 +1612,7 @@
<string name="default_audio_route_name" product="tv" msgid="4908971385068087367">"TV"</string>
<string name="default_audio_route_name" product="default" msgid="9213546147739983977">"Dispositivo"</string>
<string name="default_audio_route_name_dock_speakers" msgid="1551166029093995289">"Altavoces del conector"</string>
- <string name="default_audio_route_name_hdmi" msgid="5474470558160717850">"HDMI"</string>
+ <string name="default_audio_route_name_external_device" msgid="5474470558160717850">"HDMI"</string>
<string name="default_audio_route_name_headphones" msgid="6954070994792640762">"Auriculares"</string>
<string name="default_audio_route_name_usb" msgid="895668743163316932">"USB"</string>
<string name="default_audio_route_category_name" msgid="5241740395748134483">"Sistema"</string>
diff --git a/core/res/res/values-es/strings.xml b/core/res/res/values-es/strings.xml
index 5423512..9795e23 100644
--- a/core/res/res/values-es/strings.xml
+++ b/core/res/res/values-es/strings.xml
@@ -1612,7 +1612,7 @@
<string name="default_audio_route_name" product="tv" msgid="4908971385068087367">"TV"</string>
<string name="default_audio_route_name" product="default" msgid="9213546147739983977">"Teléfono"</string>
<string name="default_audio_route_name_dock_speakers" msgid="1551166029093995289">"Altavoces de la base"</string>
- <string name="default_audio_route_name_hdmi" msgid="5474470558160717850">"HDMI"</string>
+ <string name="default_audio_route_name_external_device" msgid="5474470558160717850">"HDMI"</string>
<string name="default_audio_route_name_headphones" msgid="6954070994792640762">"Auriculares"</string>
<string name="default_audio_route_name_usb" msgid="895668743163316932">"USB"</string>
<string name="default_audio_route_category_name" msgid="5241740395748134483">"Sistema"</string>
diff --git a/core/res/res/values-et/strings.xml b/core/res/res/values-et/strings.xml
index bfb6aad..fe7549e 100644
--- a/core/res/res/values-et/strings.xml
+++ b/core/res/res/values-et/strings.xml
@@ -1611,7 +1611,7 @@
<string name="default_audio_route_name" product="tv" msgid="4908971385068087367">"Teler"</string>
<string name="default_audio_route_name" product="default" msgid="9213546147739983977">"Telefon"</string>
<string name="default_audio_route_name_dock_speakers" msgid="1551166029093995289">"Doki kõlarid"</string>
- <string name="default_audio_route_name_hdmi" msgid="5474470558160717850">"HDMI"</string>
+ <string name="default_audio_route_name_external_device" msgid="5474470558160717850">"HDMI"</string>
<string name="default_audio_route_name_headphones" msgid="6954070994792640762">"Kõrvaklapid"</string>
<string name="default_audio_route_name_usb" msgid="895668743163316932">"USB"</string>
<string name="default_audio_route_category_name" msgid="5241740395748134483">"Süsteem"</string>
diff --git a/core/res/res/values-eu/strings.xml b/core/res/res/values-eu/strings.xml
index 4a56b59..7f424eb 100644
--- a/core/res/res/values-eu/strings.xml
+++ b/core/res/res/values-eu/strings.xml
@@ -1611,7 +1611,7 @@
<string name="default_audio_route_name" product="tv" msgid="4908971385068087367">"Telebista"</string>
<string name="default_audio_route_name" product="default" msgid="9213546147739983977">"Telefonoa"</string>
<string name="default_audio_route_name_dock_speakers" msgid="1551166029093995289">"Konektatu bozgorailuak oinarrira"</string>
- <string name="default_audio_route_name_hdmi" msgid="5474470558160717850">"HDMI"</string>
+ <string name="default_audio_route_name_external_device" msgid="5474470558160717850">"HDMI"</string>
<string name="default_audio_route_name_headphones" msgid="6954070994792640762">"Entzungailuak"</string>
<string name="default_audio_route_name_usb" msgid="895668743163316932">"USB"</string>
<string name="default_audio_route_category_name" msgid="5241740395748134483">"Sistema"</string>
diff --git a/core/res/res/values-fa/strings.xml b/core/res/res/values-fa/strings.xml
index ea3b8591..83821a3 100644
--- a/core/res/res/values-fa/strings.xml
+++ b/core/res/res/values-fa/strings.xml
@@ -1611,7 +1611,7 @@
<string name="default_audio_route_name" product="tv" msgid="4908971385068087367">"تلویزیون"</string>
<string name="default_audio_route_name" product="default" msgid="9213546147739983977">"تلفن"</string>
<string name="default_audio_route_name_dock_speakers" msgid="1551166029093995289">"بلندگوهای جایگاه"</string>
- <string name="default_audio_route_name_hdmi" msgid="5474470558160717850">"HDMI"</string>
+ <string name="default_audio_route_name_external_device" msgid="5474470558160717850">"HDMI"</string>
<string name="default_audio_route_name_headphones" msgid="6954070994792640762">"هدفونها"</string>
<string name="default_audio_route_name_usb" msgid="895668743163316932">"USB"</string>
<string name="default_audio_route_category_name" msgid="5241740395748134483">"سیستم"</string>
diff --git a/core/res/res/values-fi/strings.xml b/core/res/res/values-fi/strings.xml
index ff9e620..8798ffc 100644
--- a/core/res/res/values-fi/strings.xml
+++ b/core/res/res/values-fi/strings.xml
@@ -1611,7 +1611,7 @@
<string name="default_audio_route_name" product="tv" msgid="4908971385068087367">"TV"</string>
<string name="default_audio_route_name" product="default" msgid="9213546147739983977">"Puhelin"</string>
<string name="default_audio_route_name_dock_speakers" msgid="1551166029093995289">"Telineen kaiuttimet"</string>
- <string name="default_audio_route_name_hdmi" msgid="5474470558160717850">"HDMI"</string>
+ <string name="default_audio_route_name_external_device" msgid="5474470558160717850">"HDMI"</string>
<string name="default_audio_route_name_headphones" msgid="6954070994792640762">"Kuulokkeet"</string>
<string name="default_audio_route_name_usb" msgid="895668743163316932">"USB"</string>
<string name="default_audio_route_category_name" msgid="5241740395748134483">"Järjestelmä"</string>
diff --git a/core/res/res/values-fr-rCA/strings.xml b/core/res/res/values-fr-rCA/strings.xml
index 09ef190..87861ae 100644
--- a/core/res/res/values-fr-rCA/strings.xml
+++ b/core/res/res/values-fr-rCA/strings.xml
@@ -1612,7 +1612,7 @@
<string name="default_audio_route_name" product="tv" msgid="4908971385068087367">"Télévision"</string>
<string name="default_audio_route_name" product="default" msgid="9213546147739983977">"Téléphone"</string>
<string name="default_audio_route_name_dock_speakers" msgid="1551166029093995289">"Haut-parleurs de la station d\'accueil"</string>
- <string name="default_audio_route_name_hdmi" msgid="5474470558160717850">"HDMI"</string>
+ <string name="default_audio_route_name_external_device" msgid="5474470558160717850">"HDMI"</string>
<string name="default_audio_route_name_headphones" msgid="6954070994792640762">"Oreillettes"</string>
<string name="default_audio_route_name_usb" msgid="895668743163316932">"USB"</string>
<string name="default_audio_route_category_name" msgid="5241740395748134483">"Système"</string>
diff --git a/core/res/res/values-fr/strings.xml b/core/res/res/values-fr/strings.xml
index 487f290..a9dccbc 100644
--- a/core/res/res/values-fr/strings.xml
+++ b/core/res/res/values-fr/strings.xml
@@ -1612,7 +1612,7 @@
<string name="default_audio_route_name" product="tv" msgid="4908971385068087367">"Téléviseur"</string>
<string name="default_audio_route_name" product="default" msgid="9213546147739983977">"Téléphone"</string>
<string name="default_audio_route_name_dock_speakers" msgid="1551166029093995289">"Haut-parleurs de la station d\'accueil"</string>
- <string name="default_audio_route_name_hdmi" msgid="5474470558160717850">"HDMI"</string>
+ <string name="default_audio_route_name_external_device" msgid="5474470558160717850">"HDMI"</string>
<string name="default_audio_route_name_headphones" msgid="6954070994792640762">"Écouteurs"</string>
<string name="default_audio_route_name_usb" msgid="895668743163316932">"USB"</string>
<string name="default_audio_route_category_name" msgid="5241740395748134483">"Système"</string>
diff --git a/core/res/res/values-gl/strings.xml b/core/res/res/values-gl/strings.xml
index 1113926..ae29e50 100644
--- a/core/res/res/values-gl/strings.xml
+++ b/core/res/res/values-gl/strings.xml
@@ -1611,7 +1611,7 @@
<string name="default_audio_route_name" product="tv" msgid="4908971385068087367">"Televisión"</string>
<string name="default_audio_route_name" product="default" msgid="9213546147739983977">"Teléfono"</string>
<string name="default_audio_route_name_dock_speakers" msgid="1551166029093995289">"Conectar altofalantes á base"</string>
- <string name="default_audio_route_name_hdmi" msgid="5474470558160717850">"HDMI"</string>
+ <string name="default_audio_route_name_external_device" msgid="5474470558160717850">"HDMI"</string>
<string name="default_audio_route_name_headphones" msgid="6954070994792640762">"Auriculares"</string>
<string name="default_audio_route_name_usb" msgid="895668743163316932">"USB"</string>
<string name="default_audio_route_category_name" msgid="5241740395748134483">"Sistema"</string>
diff --git a/core/res/res/values-gu/strings.xml b/core/res/res/values-gu/strings.xml
index eec5272..36812e8 100644
--- a/core/res/res/values-gu/strings.xml
+++ b/core/res/res/values-gu/strings.xml
@@ -1611,7 +1611,7 @@
<string name="default_audio_route_name" product="tv" msgid="4908971385068087367">"TV"</string>
<string name="default_audio_route_name" product="default" msgid="9213546147739983977">"ફોન"</string>
<string name="default_audio_route_name_dock_speakers" msgid="1551166029093995289">"સ્પીકર્સ ડૉક કરો"</string>
- <string name="default_audio_route_name_hdmi" msgid="5474470558160717850">"HDMI"</string>
+ <string name="default_audio_route_name_external_device" msgid="5474470558160717850">"HDMI"</string>
<string name="default_audio_route_name_headphones" msgid="6954070994792640762">"હેડફોન"</string>
<string name="default_audio_route_name_usb" msgid="895668743163316932">"USB"</string>
<string name="default_audio_route_category_name" msgid="5241740395748134483">"સિસ્ટમ"</string>
diff --git a/core/res/res/values-hi/strings.xml b/core/res/res/values-hi/strings.xml
index 780616f..2a9a44a 100644
--- a/core/res/res/values-hi/strings.xml
+++ b/core/res/res/values-hi/strings.xml
@@ -1611,7 +1611,7 @@
<string name="default_audio_route_name" product="tv" msgid="4908971385068087367">"टीवी"</string>
<string name="default_audio_route_name" product="default" msgid="9213546147739983977">"फ़ोन"</string>
<string name="default_audio_route_name_dock_speakers" msgid="1551166029093995289">"डॉक स्पीकर"</string>
- <string name="default_audio_route_name_hdmi" msgid="5474470558160717850">"HDMI"</string>
+ <string name="default_audio_route_name_external_device" msgid="5474470558160717850">"HDMI"</string>
<string name="default_audio_route_name_headphones" msgid="6954070994792640762">"हेडफ़ोन"</string>
<string name="default_audio_route_name_usb" msgid="895668743163316932">"यूएसबी"</string>
<string name="default_audio_route_category_name" msgid="5241740395748134483">"सिस्टम"</string>
diff --git a/core/res/res/values-hr/strings.xml b/core/res/res/values-hr/strings.xml
index fbc47e2..0a2702a 100644
--- a/core/res/res/values-hr/strings.xml
+++ b/core/res/res/values-hr/strings.xml
@@ -1612,7 +1612,7 @@
<string name="default_audio_route_name" product="tv" msgid="4908971385068087367">"Televizor"</string>
<string name="default_audio_route_name" product="default" msgid="9213546147739983977">"Telefon"</string>
<string name="default_audio_route_name_dock_speakers" msgid="1551166029093995289">"Zvučnici postolja"</string>
- <string name="default_audio_route_name_hdmi" msgid="5474470558160717850">"HDMI"</string>
+ <string name="default_audio_route_name_external_device" msgid="5474470558160717850">"HDMI"</string>
<string name="default_audio_route_name_headphones" msgid="6954070994792640762">"Slušalice"</string>
<string name="default_audio_route_name_usb" msgid="895668743163316932">"USB"</string>
<string name="default_audio_route_category_name" msgid="5241740395748134483">"Sustav"</string>
diff --git a/core/res/res/values-hu/strings.xml b/core/res/res/values-hu/strings.xml
index 897904d..01b6f90 100644
--- a/core/res/res/values-hu/strings.xml
+++ b/core/res/res/values-hu/strings.xml
@@ -1611,7 +1611,7 @@
<string name="default_audio_route_name" product="tv" msgid="4908971385068087367">"TV"</string>
<string name="default_audio_route_name" product="default" msgid="9213546147739983977">"Telefon"</string>
<string name="default_audio_route_name_dock_speakers" msgid="1551166029093995289">"Dokkolóegység hangszórója"</string>
- <string name="default_audio_route_name_hdmi" msgid="5474470558160717850">"HDMI"</string>
+ <string name="default_audio_route_name_external_device" msgid="5474470558160717850">"HDMI"</string>
<string name="default_audio_route_name_headphones" msgid="6954070994792640762">"Fejhallgató"</string>
<string name="default_audio_route_name_usb" msgid="895668743163316932">"USB"</string>
<string name="default_audio_route_category_name" msgid="5241740395748134483">"Rendszer"</string>
diff --git a/core/res/res/values-hy/strings.xml b/core/res/res/values-hy/strings.xml
index fc8c3e1..86560be 100644
--- a/core/res/res/values-hy/strings.xml
+++ b/core/res/res/values-hy/strings.xml
@@ -1611,7 +1611,7 @@
<string name="default_audio_route_name" product="tv" msgid="4908971385068087367">"Հեռուստացույց"</string>
<string name="default_audio_route_name" product="default" msgid="9213546147739983977">"Հեռախոս"</string>
<string name="default_audio_route_name_dock_speakers" msgid="1551166029093995289">"Դոկ-կայանի բարձրախոսներ"</string>
- <string name="default_audio_route_name_hdmi" msgid="5474470558160717850">"HDMI"</string>
+ <string name="default_audio_route_name_external_device" msgid="5474470558160717850">"HDMI"</string>
<string name="default_audio_route_name_headphones" msgid="6954070994792640762">"Ականջակալներ"</string>
<string name="default_audio_route_name_usb" msgid="895668743163316932">"USB"</string>
<string name="default_audio_route_category_name" msgid="5241740395748134483">"Համակարգ"</string>
diff --git a/core/res/res/values-in/strings.xml b/core/res/res/values-in/strings.xml
index af1b0bd..b145e20 100644
--- a/core/res/res/values-in/strings.xml
+++ b/core/res/res/values-in/strings.xml
@@ -1611,7 +1611,7 @@
<string name="default_audio_route_name" product="tv" msgid="4908971385068087367">"TV"</string>
<string name="default_audio_route_name" product="default" msgid="9213546147739983977">"Ponsel"</string>
<string name="default_audio_route_name_dock_speakers" msgid="1551166029093995289">"Pengeras suara dok"</string>
- <string name="default_audio_route_name_hdmi" msgid="5474470558160717850">"HDMI"</string>
+ <string name="default_audio_route_name_external_device" msgid="5474470558160717850">"HDMI"</string>
<string name="default_audio_route_name_headphones" msgid="6954070994792640762">"Headphone"</string>
<string name="default_audio_route_name_usb" msgid="895668743163316932">"USB"</string>
<string name="default_audio_route_category_name" msgid="5241740395748134483">"Sistem"</string>
diff --git a/core/res/res/values-is/strings.xml b/core/res/res/values-is/strings.xml
index 69e3127..6f48de2 100644
--- a/core/res/res/values-is/strings.xml
+++ b/core/res/res/values-is/strings.xml
@@ -1611,7 +1611,7 @@
<string name="default_audio_route_name" product="tv" msgid="4908971385068087367">"Sjónvarp"</string>
<string name="default_audio_route_name" product="default" msgid="9213546147739983977">"Sími"</string>
<string name="default_audio_route_name_dock_speakers" msgid="1551166029093995289">"Dokkuhátalarar"</string>
- <string name="default_audio_route_name_hdmi" msgid="5474470558160717850">"HDMI"</string>
+ <string name="default_audio_route_name_external_device" msgid="5474470558160717850">"HDMI"</string>
<string name="default_audio_route_name_headphones" msgid="6954070994792640762">"Heyrnartól"</string>
<string name="default_audio_route_name_usb" msgid="895668743163316932">"USB"</string>
<string name="default_audio_route_category_name" msgid="5241740395748134483">"Kerfi"</string>
diff --git a/core/res/res/values-it/strings.xml b/core/res/res/values-it/strings.xml
index bf18581..fb7763a 100644
--- a/core/res/res/values-it/strings.xml
+++ b/core/res/res/values-it/strings.xml
@@ -1612,7 +1612,7 @@
<string name="default_audio_route_name" product="tv" msgid="4908971385068087367">"TV"</string>
<string name="default_audio_route_name" product="default" msgid="9213546147739983977">"Telefono"</string>
<string name="default_audio_route_name_dock_speakers" msgid="1551166029093995289">"Altoparlanti dock"</string>
- <string name="default_audio_route_name_hdmi" msgid="5474470558160717850">"HDMI"</string>
+ <string name="default_audio_route_name_external_device" msgid="5474470558160717850">"HDMI"</string>
<string name="default_audio_route_name_headphones" msgid="6954070994792640762">"Cuffie audio"</string>
<string name="default_audio_route_name_usb" msgid="895668743163316932">"USB"</string>
<string name="default_audio_route_category_name" msgid="5241740395748134483">"Sistema"</string>
diff --git a/core/res/res/values-iw/strings.xml b/core/res/res/values-iw/strings.xml
index 30c6942..7a460a3 100644
--- a/core/res/res/values-iw/strings.xml
+++ b/core/res/res/values-iw/strings.xml
@@ -1613,7 +1613,7 @@
<string name="default_audio_route_name" product="tv" msgid="4908971385068087367">"טלוויזיה"</string>
<string name="default_audio_route_name" product="default" msgid="9213546147739983977">"טלפון"</string>
<string name="default_audio_route_name_dock_speakers" msgid="1551166029093995289">"רמקולים של מעגן"</string>
- <string name="default_audio_route_name_hdmi" msgid="5474470558160717850">"HDMI"</string>
+ <string name="default_audio_route_name_external_device" msgid="5474470558160717850">"HDMI"</string>
<string name="default_audio_route_name_headphones" msgid="6954070994792640762">"אוזניות"</string>
<string name="default_audio_route_name_usb" msgid="895668743163316932">"USB"</string>
<string name="default_audio_route_category_name" msgid="5241740395748134483">"מערכת"</string>
diff --git a/core/res/res/values-ja/strings.xml b/core/res/res/values-ja/strings.xml
index 8733542..cf8521f 100644
--- a/core/res/res/values-ja/strings.xml
+++ b/core/res/res/values-ja/strings.xml
@@ -1610,7 +1610,7 @@
<string name="default_audio_route_name" product="tv" msgid="4908971385068087367">"テレビ"</string>
<string name="default_audio_route_name" product="default" msgid="9213546147739983977">"モバイル デバイス"</string>
<string name="default_audio_route_name_dock_speakers" msgid="1551166029093995289">"ホルダーのスピーカー"</string>
- <string name="default_audio_route_name_hdmi" msgid="5474470558160717850">"HDMI"</string>
+ <string name="default_audio_route_name_external_device" msgid="5474470558160717850">"HDMI"</string>
<string name="default_audio_route_name_headphones" msgid="6954070994792640762">"ヘッドホン"</string>
<string name="default_audio_route_name_usb" msgid="895668743163316932">"USB"</string>
<string name="default_audio_route_category_name" msgid="5241740395748134483">"システム"</string>
diff --git a/core/res/res/values-ka/strings.xml b/core/res/res/values-ka/strings.xml
index 2b4262c..ae14cc9 100644
--- a/core/res/res/values-ka/strings.xml
+++ b/core/res/res/values-ka/strings.xml
@@ -1611,7 +1611,7 @@
<string name="default_audio_route_name" product="tv" msgid="4908971385068087367">"ტელევიზია"</string>
<string name="default_audio_route_name" product="default" msgid="9213546147739983977">"ტელეფონი"</string>
<string name="default_audio_route_name_dock_speakers" msgid="1551166029093995289">"სპიკერების მიმაგრება"</string>
- <string name="default_audio_route_name_hdmi" msgid="5474470558160717850">"HDMI"</string>
+ <string name="default_audio_route_name_external_device" msgid="5474470558160717850">"HDMI"</string>
<string name="default_audio_route_name_headphones" msgid="6954070994792640762">"ყურსასმენები"</string>
<string name="default_audio_route_name_usb" msgid="895668743163316932">"USB"</string>
<string name="default_audio_route_category_name" msgid="5241740395748134483">"სისტემა"</string>
diff --git a/core/res/res/values-kk/strings.xml b/core/res/res/values-kk/strings.xml
index 4a37cc5..54edba3 100644
--- a/core/res/res/values-kk/strings.xml
+++ b/core/res/res/values-kk/strings.xml
@@ -1612,7 +1612,7 @@
<string name="default_audio_route_name" product="tv" msgid="4908971385068087367">"ТД"</string>
<string name="default_audio_route_name" product="default" msgid="9213546147739983977">"Телефон"</string>
<string name="default_audio_route_name_dock_speakers" msgid="1551166029093995289">"Үндеткіштерді қондыру"</string>
- <string name="default_audio_route_name_hdmi" msgid="5474470558160717850">"HDMI"</string>
+ <string name="default_audio_route_name_external_device" msgid="5474470558160717850">"HDMI"</string>
<string name="default_audio_route_name_headphones" msgid="6954070994792640762">"Құлақаспаптар"</string>
<string name="default_audio_route_name_usb" msgid="895668743163316932">"USB"</string>
<string name="default_audio_route_category_name" msgid="5241740395748134483">"Жүйе"</string>
diff --git a/core/res/res/values-km/strings.xml b/core/res/res/values-km/strings.xml
index 5738925..0d3d07d 100644
--- a/core/res/res/values-km/strings.xml
+++ b/core/res/res/values-km/strings.xml
@@ -1611,7 +1611,7 @@
<string name="default_audio_route_name" product="tv" msgid="4908971385068087367">"ទូរទស្សន៍"</string>
<string name="default_audio_route_name" product="default" msgid="9213546147739983977">"ទូរសព្ទ"</string>
<string name="default_audio_route_name_dock_speakers" msgid="1551166029093995289">"ភ្ជាប់អូប៉ាល័រ"</string>
- <string name="default_audio_route_name_hdmi" msgid="5474470558160717850">"HDMI"</string>
+ <string name="default_audio_route_name_external_device" msgid="5474470558160717850">"HDMI"</string>
<string name="default_audio_route_name_headphones" msgid="6954070994792640762">"កាស"</string>
<string name="default_audio_route_name_usb" msgid="895668743163316932">"USB"</string>
<string name="default_audio_route_category_name" msgid="5241740395748134483">"ប្រព័ន្ធ"</string>
diff --git a/core/res/res/values-kn/strings.xml b/core/res/res/values-kn/strings.xml
index 61c9415..9925a26 100644
--- a/core/res/res/values-kn/strings.xml
+++ b/core/res/res/values-kn/strings.xml
@@ -1611,7 +1611,7 @@
<string name="default_audio_route_name" product="tv" msgid="4908971385068087367">"ಟಿವಿ"</string>
<string name="default_audio_route_name" product="default" msgid="9213546147739983977">"ಫೋನ್"</string>
<string name="default_audio_route_name_dock_speakers" msgid="1551166029093995289">"ಡಾಕ್ ಸ್ಪೀಕರ್ಗಳು"</string>
- <string name="default_audio_route_name_hdmi" msgid="5474470558160717850">"HDMI"</string>
+ <string name="default_audio_route_name_external_device" msgid="5474470558160717850">"HDMI"</string>
<string name="default_audio_route_name_headphones" msgid="6954070994792640762">"ಹೆಡ್ಫೋನ್ಗಳು"</string>
<string name="default_audio_route_name_usb" msgid="895668743163316932">"USB"</string>
<string name="default_audio_route_category_name" msgid="5241740395748134483">"ಸಿಸ್ಟಂ"</string>
diff --git a/core/res/res/values-ko/strings.xml b/core/res/res/values-ko/strings.xml
index 32fbe92..40c545f 100644
--- a/core/res/res/values-ko/strings.xml
+++ b/core/res/res/values-ko/strings.xml
@@ -1611,7 +1611,7 @@
<string name="default_audio_route_name" product="tv" msgid="4908971385068087367">"TV"</string>
<string name="default_audio_route_name" product="default" msgid="9213546147739983977">"휴대전화"</string>
<string name="default_audio_route_name_dock_speakers" msgid="1551166029093995289">"도크 스피커"</string>
- <string name="default_audio_route_name_hdmi" msgid="5474470558160717850">"HDMI"</string>
+ <string name="default_audio_route_name_external_device" msgid="5474470558160717850">"HDMI"</string>
<string name="default_audio_route_name_headphones" msgid="6954070994792640762">"헤드폰"</string>
<string name="default_audio_route_name_usb" msgid="895668743163316932">"USB"</string>
<string name="default_audio_route_category_name" msgid="5241740395748134483">"시스템"</string>
diff --git a/core/res/res/values-ky/strings.xml b/core/res/res/values-ky/strings.xml
index b1673fd..f27b0d6 100644
--- a/core/res/res/values-ky/strings.xml
+++ b/core/res/res/values-ky/strings.xml
@@ -1611,7 +1611,7 @@
<string name="default_audio_route_name" product="tv" msgid="4908971385068087367">"Сыналгы"</string>
<string name="default_audio_route_name" product="default" msgid="9213546147739983977">"Телефон"</string>
<string name="default_audio_route_name_dock_speakers" msgid="1551166029093995289">"Аудио док бекет"</string>
- <string name="default_audio_route_name_hdmi" msgid="5474470558160717850">"HDMI"</string>
+ <string name="default_audio_route_name_external_device" msgid="5474470558160717850">"HDMI"</string>
<string name="default_audio_route_name_headphones" msgid="6954070994792640762">"Кулакчын"</string>
<string name="default_audio_route_name_usb" msgid="895668743163316932">"USB"</string>
<string name="default_audio_route_category_name" msgid="5241740395748134483">"Тутум"</string>
diff --git a/core/res/res/values-lo/strings.xml b/core/res/res/values-lo/strings.xml
index 3cdebdd..7c9f815 100644
--- a/core/res/res/values-lo/strings.xml
+++ b/core/res/res/values-lo/strings.xml
@@ -1611,7 +1611,7 @@
<string name="default_audio_route_name" product="tv" msgid="4908971385068087367">"ໂທລະພາບ"</string>
<string name="default_audio_route_name" product="default" msgid="9213546147739983977">"ໂທລະສັບ"</string>
<string name="default_audio_route_name_dock_speakers" msgid="1551166029093995289">"ບ່ອນຕັ້ງລຳໂພງ"</string>
- <string name="default_audio_route_name_hdmi" msgid="5474470558160717850">"HDMI"</string>
+ <string name="default_audio_route_name_external_device" msgid="5474470558160717850">"HDMI"</string>
<string name="default_audio_route_name_headphones" msgid="6954070994792640762">"ຫູຟັງ"</string>
<string name="default_audio_route_name_usb" msgid="895668743163316932">"USB"</string>
<string name="default_audio_route_category_name" msgid="5241740395748134483">"ລະບົບ"</string>
diff --git a/core/res/res/values-lt/strings.xml b/core/res/res/values-lt/strings.xml
index 73ce68a..2954f9c 100644
--- a/core/res/res/values-lt/strings.xml
+++ b/core/res/res/values-lt/strings.xml
@@ -1613,7 +1613,7 @@
<string name="default_audio_route_name" product="tv" msgid="4908971385068087367">"TV"</string>
<string name="default_audio_route_name" product="default" msgid="9213546147739983977">"Telefonas"</string>
<string name="default_audio_route_name_dock_speakers" msgid="1551166029093995289">"Doko garsiakalbiai"</string>
- <string name="default_audio_route_name_hdmi" msgid="5474470558160717850">"HDMI"</string>
+ <string name="default_audio_route_name_external_device" msgid="5474470558160717850">"HDMI"</string>
<string name="default_audio_route_name_headphones" msgid="6954070994792640762">"Ausinės"</string>
<string name="default_audio_route_name_usb" msgid="895668743163316932">"USB"</string>
<string name="default_audio_route_category_name" msgid="5241740395748134483">"Sistema"</string>
diff --git a/core/res/res/values-lv/strings.xml b/core/res/res/values-lv/strings.xml
index 8429919..853a490 100644
--- a/core/res/res/values-lv/strings.xml
+++ b/core/res/res/values-lv/strings.xml
@@ -1612,7 +1612,7 @@
<string name="default_audio_route_name" product="tv" msgid="4908971385068087367">"TV"</string>
<string name="default_audio_route_name" product="default" msgid="9213546147739983977">"Tālrunis"</string>
<string name="default_audio_route_name_dock_speakers" msgid="1551166029093995289">"Doka skaļruņi"</string>
- <string name="default_audio_route_name_hdmi" msgid="5474470558160717850">"HDMI"</string>
+ <string name="default_audio_route_name_external_device" msgid="5474470558160717850">"HDMI"</string>
<string name="default_audio_route_name_headphones" msgid="6954070994792640762">"Austiņas"</string>
<string name="default_audio_route_name_usb" msgid="895668743163316932">"USB"</string>
<string name="default_audio_route_category_name" msgid="5241740395748134483">"Sistēma"</string>
diff --git a/core/res/res/values-mk/strings.xml b/core/res/res/values-mk/strings.xml
index 80934d0..9ce43d1 100644
--- a/core/res/res/values-mk/strings.xml
+++ b/core/res/res/values-mk/strings.xml
@@ -1611,7 +1611,7 @@
<string name="default_audio_route_name" product="tv" msgid="4908971385068087367">"Телевизор"</string>
<string name="default_audio_route_name" product="default" msgid="9213546147739983977">"Телефон"</string>
<string name="default_audio_route_name_dock_speakers" msgid="1551166029093995289">"Приклучи звучници"</string>
- <string name="default_audio_route_name_hdmi" msgid="5474470558160717850">"HDMI"</string>
+ <string name="default_audio_route_name_external_device" msgid="5474470558160717850">"HDMI"</string>
<string name="default_audio_route_name_headphones" msgid="6954070994792640762">"Слушалки"</string>
<string name="default_audio_route_name_usb" msgid="895668743163316932">"USB"</string>
<string name="default_audio_route_category_name" msgid="5241740395748134483">"Систем"</string>
diff --git a/core/res/res/values-ml/strings.xml b/core/res/res/values-ml/strings.xml
index 7437725..c71047d 100644
--- a/core/res/res/values-ml/strings.xml
+++ b/core/res/res/values-ml/strings.xml
@@ -1611,7 +1611,7 @@
<string name="default_audio_route_name" product="tv" msgid="4908971385068087367">"ടിവി"</string>
<string name="default_audio_route_name" product="default" msgid="9213546147739983977">"ഫോണ്"</string>
<string name="default_audio_route_name_dock_speakers" msgid="1551166029093995289">"ഡോക്ക് സ്പീക്കറുകൾ"</string>
- <string name="default_audio_route_name_hdmi" msgid="5474470558160717850">"HDMI"</string>
+ <string name="default_audio_route_name_external_device" msgid="5474470558160717850">"HDMI"</string>
<string name="default_audio_route_name_headphones" msgid="6954070994792640762">"ഹെഡ്ഫോണുകൾ"</string>
<string name="default_audio_route_name_usb" msgid="895668743163316932">"USB"</string>
<string name="default_audio_route_category_name" msgid="5241740395748134483">"സിസ്റ്റം"</string>
diff --git a/core/res/res/values-mn/strings.xml b/core/res/res/values-mn/strings.xml
index 1935280..417500d 100644
--- a/core/res/res/values-mn/strings.xml
+++ b/core/res/res/values-mn/strings.xml
@@ -1611,7 +1611,7 @@
<string name="default_audio_route_name" product="tv" msgid="4908971385068087367">"Tелевиз"</string>
<string name="default_audio_route_name" product="default" msgid="9213546147739983977">"Утас"</string>
<string name="default_audio_route_name_dock_speakers" msgid="1551166029093995289">"Чанга яригчийг суулгах"</string>
- <string name="default_audio_route_name_hdmi" msgid="5474470558160717850">"HDMI"</string>
+ <string name="default_audio_route_name_external_device" msgid="5474470558160717850">"HDMI"</string>
<string name="default_audio_route_name_headphones" msgid="6954070994792640762">"Чихэвч"</string>
<string name="default_audio_route_name_usb" msgid="895668743163316932">"USB"</string>
<string name="default_audio_route_category_name" msgid="5241740395748134483">"Систем"</string>
diff --git a/core/res/res/values-mr/strings.xml b/core/res/res/values-mr/strings.xml
index ac9f289..f91a18f 100644
--- a/core/res/res/values-mr/strings.xml
+++ b/core/res/res/values-mr/strings.xml
@@ -1611,7 +1611,7 @@
<string name="default_audio_route_name" product="tv" msgid="4908971385068087367">"टीव्ही"</string>
<string name="default_audio_route_name" product="default" msgid="9213546147739983977">"फोन"</string>
<string name="default_audio_route_name_dock_speakers" msgid="1551166029093995289">"स्पीकर डॉक करा"</string>
- <string name="default_audio_route_name_hdmi" msgid="5474470558160717850">"HDMI"</string>
+ <string name="default_audio_route_name_external_device" msgid="5474470558160717850">"HDMI"</string>
<string name="default_audio_route_name_headphones" msgid="6954070994792640762">"हेडफोन"</string>
<string name="default_audio_route_name_usb" msgid="895668743163316932">"USB"</string>
<string name="default_audio_route_category_name" msgid="5241740395748134483">"सिस्टम"</string>
diff --git a/core/res/res/values-ms/strings.xml b/core/res/res/values-ms/strings.xml
index 94be0fc..9b76a16 100644
--- a/core/res/res/values-ms/strings.xml
+++ b/core/res/res/values-ms/strings.xml
@@ -1611,7 +1611,7 @@
<string name="default_audio_route_name" product="tv" msgid="4908971385068087367">"TV"</string>
<string name="default_audio_route_name" product="default" msgid="9213546147739983977">"Telefon"</string>
<string name="default_audio_route_name_dock_speakers" msgid="1551166029093995289">"Pembesar suara dok"</string>
- <string name="default_audio_route_name_hdmi" msgid="5474470558160717850">"HDMI"</string>
+ <string name="default_audio_route_name_external_device" msgid="5474470558160717850">"HDMI"</string>
<string name="default_audio_route_name_headphones" msgid="6954070994792640762">"Fon kepala"</string>
<string name="default_audio_route_name_usb" msgid="895668743163316932">"USB"</string>
<string name="default_audio_route_category_name" msgid="5241740395748134483">"Sistem"</string>
diff --git a/core/res/res/values-my/strings.xml b/core/res/res/values-my/strings.xml
index 0a11698..87916c4 100644
--- a/core/res/res/values-my/strings.xml
+++ b/core/res/res/values-my/strings.xml
@@ -1611,7 +1611,7 @@
<string name="default_audio_route_name" product="tv" msgid="4908971385068087367">"TV"</string>
<string name="default_audio_route_name" product="default" msgid="9213546147739983977">"ဖုန်း"</string>
<string name="default_audio_route_name_dock_speakers" msgid="1551166029093995289">"အထိုင်ရှိသော စပီကာများ"</string>
- <string name="default_audio_route_name_hdmi" msgid="5474470558160717850">"HDMI"</string>
+ <string name="default_audio_route_name_external_device" msgid="5474470558160717850">"HDMI"</string>
<string name="default_audio_route_name_headphones" msgid="6954070994792640762">"နားကြပ်"</string>
<string name="default_audio_route_name_usb" msgid="895668743163316932">"USB"</string>
<string name="default_audio_route_category_name" msgid="5241740395748134483">"စနစ်"</string>
diff --git a/core/res/res/values-nb/strings.xml b/core/res/res/values-nb/strings.xml
index e439859..e101548 100644
--- a/core/res/res/values-nb/strings.xml
+++ b/core/res/res/values-nb/strings.xml
@@ -1611,7 +1611,7 @@
<string name="default_audio_route_name" product="tv" msgid="4908971385068087367">"Google TV"</string>
<string name="default_audio_route_name" product="default" msgid="9213546147739983977">"Telefon"</string>
<string name="default_audio_route_name_dock_speakers" msgid="1551166029093995289">"Dokkhøyttalere"</string>
- <string name="default_audio_route_name_hdmi" msgid="5474470558160717850">"HDMI"</string>
+ <string name="default_audio_route_name_external_device" msgid="5474470558160717850">"HDMI"</string>
<string name="default_audio_route_name_headphones" msgid="6954070994792640762">"Hodetelefoner"</string>
<string name="default_audio_route_name_usb" msgid="895668743163316932">"USB"</string>
<string name="default_audio_route_category_name" msgid="5241740395748134483">"System"</string>
diff --git a/core/res/res/values-ne/strings.xml b/core/res/res/values-ne/strings.xml
index b3647ce..b2bf381 100644
--- a/core/res/res/values-ne/strings.xml
+++ b/core/res/res/values-ne/strings.xml
@@ -1611,7 +1611,7 @@
<string name="default_audio_route_name" product="tv" msgid="4908971385068087367">"टिभी"</string>
<string name="default_audio_route_name" product="default" msgid="9213546147739983977">"फोन"</string>
<string name="default_audio_route_name_dock_speakers" msgid="1551166029093995289">"डक स्पिकरहरू"</string>
- <string name="default_audio_route_name_hdmi" msgid="5474470558160717850">"HDMI"</string>
+ <string name="default_audio_route_name_external_device" msgid="5474470558160717850">"HDMI"</string>
<string name="default_audio_route_name_headphones" msgid="6954070994792640762">"हेडफोनहरू"</string>
<string name="default_audio_route_name_usb" msgid="895668743163316932">"USB"</string>
<string name="default_audio_route_category_name" msgid="5241740395748134483">"प्रणाली"</string>
diff --git a/core/res/res/values-nl/strings.xml b/core/res/res/values-nl/strings.xml
index 92ea1c4..9811e27 100644
--- a/core/res/res/values-nl/strings.xml
+++ b/core/res/res/values-nl/strings.xml
@@ -1611,7 +1611,7 @@
<string name="default_audio_route_name" product="tv" msgid="4908971385068087367">"Tv"</string>
<string name="default_audio_route_name" product="default" msgid="9213546147739983977">"Telefoon"</string>
<string name="default_audio_route_name_dock_speakers" msgid="1551166029093995289">"Dockluidsprekers"</string>
- <string name="default_audio_route_name_hdmi" msgid="5474470558160717850">"HDMI"</string>
+ <string name="default_audio_route_name_external_device" msgid="5474470558160717850">"HDMI"</string>
<string name="default_audio_route_name_headphones" msgid="6954070994792640762">"Hoofdtelefoon"</string>
<string name="default_audio_route_name_usb" msgid="895668743163316932">"USB"</string>
<string name="default_audio_route_category_name" msgid="5241740395748134483">"Systeem"</string>
diff --git a/core/res/res/values-or/strings.xml b/core/res/res/values-or/strings.xml
index e42a7e3..d3cbaec 100644
--- a/core/res/res/values-or/strings.xml
+++ b/core/res/res/values-or/strings.xml
@@ -1611,7 +1611,7 @@
<string name="default_audio_route_name" product="tv" msgid="4908971385068087367">"TV"</string>
<string name="default_audio_route_name" product="default" msgid="9213546147739983977">"ଫୋନ"</string>
<string name="default_audio_route_name_dock_speakers" msgid="1551166029093995289">"ଡକ୍ ସ୍ପିକର୍"</string>
- <string name="default_audio_route_name_hdmi" msgid="5474470558160717850">"HDMI"</string>
+ <string name="default_audio_route_name_external_device" msgid="5474470558160717850">"HDMI"</string>
<string name="default_audio_route_name_headphones" msgid="6954070994792640762">"ହେଡଫୋନ୍"</string>
<string name="default_audio_route_name_usb" msgid="895668743163316932">"USB"</string>
<string name="default_audio_route_category_name" msgid="5241740395748134483">"ସିଷ୍ଟମ"</string>
diff --git a/core/res/res/values-pa/strings.xml b/core/res/res/values-pa/strings.xml
index 500f37d..2ffeef4 100644
--- a/core/res/res/values-pa/strings.xml
+++ b/core/res/res/values-pa/strings.xml
@@ -1611,7 +1611,7 @@
<string name="default_audio_route_name" product="tv" msgid="4908971385068087367">"TV"</string>
<string name="default_audio_route_name" product="default" msgid="9213546147739983977">"ਫ਼ੋਨ ਕਰੋ"</string>
<string name="default_audio_route_name_dock_speakers" msgid="1551166029093995289">"ਡੌਕ ਸਪੀਕਰਸ"</string>
- <string name="default_audio_route_name_hdmi" msgid="5474470558160717850">"HDMI"</string>
+ <string name="default_audio_route_name_external_device" msgid="5474470558160717850">"HDMI"</string>
<string name="default_audio_route_name_headphones" msgid="6954070994792640762">"ਹੈੱਡਫ਼ੋਨ"</string>
<string name="default_audio_route_name_usb" msgid="895668743163316932">"USB"</string>
<string name="default_audio_route_category_name" msgid="5241740395748134483">"ਸਿਸਟਮ"</string>
diff --git a/core/res/res/values-pl/strings.xml b/core/res/res/values-pl/strings.xml
index be71f35..88b54b0 100644
--- a/core/res/res/values-pl/strings.xml
+++ b/core/res/res/values-pl/strings.xml
@@ -1613,7 +1613,7 @@
<string name="default_audio_route_name" product="tv" msgid="4908971385068087367">"Telewizor"</string>
<string name="default_audio_route_name" product="default" msgid="9213546147739983977">"Telefon"</string>
<string name="default_audio_route_name_dock_speakers" msgid="1551166029093995289">"Głośniki stacji dokującej"</string>
- <string name="default_audio_route_name_hdmi" msgid="5474470558160717850">"HDMI"</string>
+ <string name="default_audio_route_name_external_device" msgid="5474470558160717850">"HDMI"</string>
<string name="default_audio_route_name_headphones" msgid="6954070994792640762">"Słuchawki"</string>
<string name="default_audio_route_name_usb" msgid="895668743163316932">"USB"</string>
<string name="default_audio_route_category_name" msgid="5241740395748134483">"System"</string>
diff --git a/core/res/res/values-pt-rBR/strings.xml b/core/res/res/values-pt-rBR/strings.xml
index ad94450..7d5721a 100644
--- a/core/res/res/values-pt-rBR/strings.xml
+++ b/core/res/res/values-pt-rBR/strings.xml
@@ -1612,7 +1612,7 @@
<string name="default_audio_route_name" product="tv" msgid="4908971385068087367">"TV"</string>
<string name="default_audio_route_name" product="default" msgid="9213546147739983977">"Telefone"</string>
<string name="default_audio_route_name_dock_speakers" msgid="1551166029093995289">"Alto-falantes na base"</string>
- <string name="default_audio_route_name_hdmi" msgid="5474470558160717850">"HDMI"</string>
+ <string name="default_audio_route_name_external_device" msgid="5474470558160717850">"HDMI"</string>
<string name="default_audio_route_name_headphones" msgid="6954070994792640762">"Fones de ouvido"</string>
<string name="default_audio_route_name_usb" msgid="895668743163316932">"USB"</string>
<string name="default_audio_route_category_name" msgid="5241740395748134483">"Sistema"</string>
diff --git a/core/res/res/values-pt-rPT/strings.xml b/core/res/res/values-pt-rPT/strings.xml
index 000d3f7..1fe0db7a 100644
--- a/core/res/res/values-pt-rPT/strings.xml
+++ b/core/res/res/values-pt-rPT/strings.xml
@@ -1612,7 +1612,7 @@
<string name="default_audio_route_name" product="tv" msgid="4908971385068087367">"TV"</string>
<string name="default_audio_route_name" product="default" msgid="9213546147739983977">"Telemóvel"</string>
<string name="default_audio_route_name_dock_speakers" msgid="1551166029093995289">"Altif. estação ancoragem"</string>
- <string name="default_audio_route_name_hdmi" msgid="5474470558160717850">"HDMI"</string>
+ <string name="default_audio_route_name_external_device" msgid="5474470558160717850">"HDMI"</string>
<string name="default_audio_route_name_headphones" msgid="6954070994792640762">"Auscultadores"</string>
<string name="default_audio_route_name_usb" msgid="895668743163316932">"USB"</string>
<string name="default_audio_route_category_name" msgid="5241740395748134483">"Sistema"</string>
diff --git a/core/res/res/values-pt/strings.xml b/core/res/res/values-pt/strings.xml
index ad94450..7d5721a 100644
--- a/core/res/res/values-pt/strings.xml
+++ b/core/res/res/values-pt/strings.xml
@@ -1612,7 +1612,7 @@
<string name="default_audio_route_name" product="tv" msgid="4908971385068087367">"TV"</string>
<string name="default_audio_route_name" product="default" msgid="9213546147739983977">"Telefone"</string>
<string name="default_audio_route_name_dock_speakers" msgid="1551166029093995289">"Alto-falantes na base"</string>
- <string name="default_audio_route_name_hdmi" msgid="5474470558160717850">"HDMI"</string>
+ <string name="default_audio_route_name_external_device" msgid="5474470558160717850">"HDMI"</string>
<string name="default_audio_route_name_headphones" msgid="6954070994792640762">"Fones de ouvido"</string>
<string name="default_audio_route_name_usb" msgid="895668743163316932">"USB"</string>
<string name="default_audio_route_category_name" msgid="5241740395748134483">"Sistema"</string>
diff --git a/core/res/res/values-ro/strings.xml b/core/res/res/values-ro/strings.xml
index 142b278..27b04d6 100644
--- a/core/res/res/values-ro/strings.xml
+++ b/core/res/res/values-ro/strings.xml
@@ -1612,7 +1612,7 @@
<string name="default_audio_route_name" product="tv" msgid="4908971385068087367">"TV"</string>
<string name="default_audio_route_name" product="default" msgid="9213546147739983977">"Telefon"</string>
<string name="default_audio_route_name_dock_speakers" msgid="1551166029093995289">"Difuz. dispozit. andocare"</string>
- <string name="default_audio_route_name_hdmi" msgid="5474470558160717850">"HDMI"</string>
+ <string name="default_audio_route_name_external_device" msgid="5474470558160717850">"HDMI"</string>
<string name="default_audio_route_name_headphones" msgid="6954070994792640762">"Căști"</string>
<string name="default_audio_route_name_usb" msgid="895668743163316932">"USB"</string>
<string name="default_audio_route_category_name" msgid="5241740395748134483">"Sistem"</string>
diff --git a/core/res/res/values-ru/strings.xml b/core/res/res/values-ru/strings.xml
index 7b47179..2cceafc 100644
--- a/core/res/res/values-ru/strings.xml
+++ b/core/res/res/values-ru/strings.xml
@@ -1613,7 +1613,7 @@
<string name="default_audio_route_name" product="tv" msgid="4908971385068087367">"Телевизор"</string>
<string name="default_audio_route_name" product="default" msgid="9213546147739983977">"Телефон"</string>
<string name="default_audio_route_name_dock_speakers" msgid="1551166029093995289">"Динамики док-станции"</string>
- <string name="default_audio_route_name_hdmi" msgid="5474470558160717850">"HDMI"</string>
+ <string name="default_audio_route_name_external_device" msgid="5474470558160717850">"HDMI"</string>
<string name="default_audio_route_name_headphones" msgid="6954070994792640762">"Наушники"</string>
<string name="default_audio_route_name_usb" msgid="895668743163316932">"USB"</string>
<string name="default_audio_route_category_name" msgid="5241740395748134483">"Система"</string>
diff --git a/core/res/res/values-si/strings.xml b/core/res/res/values-si/strings.xml
index f1f8127..06ac0f8 100644
--- a/core/res/res/values-si/strings.xml
+++ b/core/res/res/values-si/strings.xml
@@ -1611,7 +1611,7 @@
<string name="default_audio_route_name" product="tv" msgid="4908971385068087367">"රූපවාහිනී"</string>
<string name="default_audio_route_name" product="default" msgid="9213546147739983977">"දුරකථනය"</string>
<string name="default_audio_route_name_dock_speakers" msgid="1551166029093995289">"නාදක ඩොක් කරන්න"</string>
- <string name="default_audio_route_name_hdmi" msgid="5474470558160717850">"HDMI"</string>
+ <string name="default_audio_route_name_external_device" msgid="5474470558160717850">"HDMI"</string>
<string name="default_audio_route_name_headphones" msgid="6954070994792640762">"ඉස් බණු"</string>
<string name="default_audio_route_name_usb" msgid="895668743163316932">"USB"</string>
<string name="default_audio_route_category_name" msgid="5241740395748134483">"පද්ධතිය"</string>
diff --git a/core/res/res/values-sk/strings.xml b/core/res/res/values-sk/strings.xml
index ce3137c..cdc6829 100644
--- a/core/res/res/values-sk/strings.xml
+++ b/core/res/res/values-sk/strings.xml
@@ -1613,7 +1613,7 @@
<string name="default_audio_route_name" product="tv" msgid="4908971385068087367">"Televízor"</string>
<string name="default_audio_route_name" product="default" msgid="9213546147739983977">"Telefón"</string>
<string name="default_audio_route_name_dock_speakers" msgid="1551166029093995289">"Reproduktory doku"</string>
- <string name="default_audio_route_name_hdmi" msgid="5474470558160717850">"HDMI"</string>
+ <string name="default_audio_route_name_external_device" msgid="5474470558160717850">"HDMI"</string>
<string name="default_audio_route_name_headphones" msgid="6954070994792640762">"Slúchadlá"</string>
<string name="default_audio_route_name_usb" msgid="895668743163316932">"USB"</string>
<string name="default_audio_route_category_name" msgid="5241740395748134483">"Systém"</string>
diff --git a/core/res/res/values-sl/strings.xml b/core/res/res/values-sl/strings.xml
index 3a56d6d..6da07f8 100644
--- a/core/res/res/values-sl/strings.xml
+++ b/core/res/res/values-sl/strings.xml
@@ -1613,7 +1613,7 @@
<string name="default_audio_route_name" product="tv" msgid="4908971385068087367">"Televizor"</string>
<string name="default_audio_route_name" product="default" msgid="9213546147739983977">"Telefon"</string>
<string name="default_audio_route_name_dock_speakers" msgid="1551166029093995289">"Zvočniki stojala"</string>
- <string name="default_audio_route_name_hdmi" msgid="5474470558160717850">"HDMI"</string>
+ <string name="default_audio_route_name_external_device" msgid="5474470558160717850">"HDMI"</string>
<string name="default_audio_route_name_headphones" msgid="6954070994792640762">"Slušalke"</string>
<string name="default_audio_route_name_usb" msgid="895668743163316932">"USB"</string>
<string name="default_audio_route_category_name" msgid="5241740395748134483">"Sistem"</string>
diff --git a/core/res/res/values-sq/strings.xml b/core/res/res/values-sq/strings.xml
index ab7c68b..587215a 100644
--- a/core/res/res/values-sq/strings.xml
+++ b/core/res/res/values-sq/strings.xml
@@ -1611,7 +1611,7 @@
<string name="default_audio_route_name" product="tv" msgid="4908971385068087367">"Televizori"</string>
<string name="default_audio_route_name" product="default" msgid="9213546147739983977">"Telefon"</string>
<string name="default_audio_route_name_dock_speakers" msgid="1551166029093995289">"Altoparlantët e stacionit"</string>
- <string name="default_audio_route_name_hdmi" msgid="5474470558160717850">"HDMI"</string>
+ <string name="default_audio_route_name_external_device" msgid="5474470558160717850">"HDMI"</string>
<string name="default_audio_route_name_headphones" msgid="6954070994792640762">"Kufjet"</string>
<string name="default_audio_route_name_usb" msgid="895668743163316932">"USB"</string>
<string name="default_audio_route_category_name" msgid="5241740395748134483">"Sistemi"</string>
diff --git a/core/res/res/values-sr/strings.xml b/core/res/res/values-sr/strings.xml
index 6220219..2acaf5c 100644
--- a/core/res/res/values-sr/strings.xml
+++ b/core/res/res/values-sr/strings.xml
@@ -1612,7 +1612,7 @@
<string name="default_audio_route_name" product="tv" msgid="4908971385068087367">"ТВ"</string>
<string name="default_audio_route_name" product="default" msgid="9213546147739983977">"Телефон"</string>
<string name="default_audio_route_name_dock_speakers" msgid="1551166029093995289">"Звучници базне станице"</string>
- <string name="default_audio_route_name_hdmi" msgid="5474470558160717850">"HDMI"</string>
+ <string name="default_audio_route_name_external_device" msgid="5474470558160717850">"HDMI"</string>
<string name="default_audio_route_name_headphones" msgid="6954070994792640762">"Слушалице"</string>
<string name="default_audio_route_name_usb" msgid="895668743163316932">"USB"</string>
<string name="default_audio_route_category_name" msgid="5241740395748134483">"Систем"</string>
diff --git a/core/res/res/values-sv/strings.xml b/core/res/res/values-sv/strings.xml
index 26a496d..a6c162a 100644
--- a/core/res/res/values-sv/strings.xml
+++ b/core/res/res/values-sv/strings.xml
@@ -1611,7 +1611,7 @@
<string name="default_audio_route_name" product="tv" msgid="4908971385068087367">"TV"</string>
<string name="default_audio_route_name" product="default" msgid="9213546147739983977">"Mobil"</string>
<string name="default_audio_route_name_dock_speakers" msgid="1551166029093995289">"Dockningsstationens högtalare"</string>
- <string name="default_audio_route_name_hdmi" msgid="5474470558160717850">"HDMI"</string>
+ <string name="default_audio_route_name_external_device" msgid="5474470558160717850">"HDMI"</string>
<string name="default_audio_route_name_headphones" msgid="6954070994792640762">"Hörlurar"</string>
<string name="default_audio_route_name_usb" msgid="895668743163316932">"USB"</string>
<string name="default_audio_route_category_name" msgid="5241740395748134483">"System"</string>
diff --git a/core/res/res/values-sw/strings.xml b/core/res/res/values-sw/strings.xml
index 09083ea..b17f58e 100644
--- a/core/res/res/values-sw/strings.xml
+++ b/core/res/res/values-sw/strings.xml
@@ -1611,7 +1611,7 @@
<string name="default_audio_route_name" product="tv" msgid="4908971385068087367">"Runinga"</string>
<string name="default_audio_route_name" product="default" msgid="9213546147739983977">"Simu"</string>
<string name="default_audio_route_name_dock_speakers" msgid="1551166029093995289">"Vipasa sauti vya kituo"</string>
- <string name="default_audio_route_name_hdmi" msgid="5474470558160717850">"HDMI"</string>
+ <string name="default_audio_route_name_external_device" msgid="5474470558160717850">"HDMI"</string>
<string name="default_audio_route_name_headphones" msgid="6954070994792640762">"Vipokeasauti"</string>
<string name="default_audio_route_name_usb" msgid="895668743163316932">"USB"</string>
<string name="default_audio_route_category_name" msgid="5241740395748134483">"Mfumo"</string>
diff --git a/core/res/res/values-ta/strings.xml b/core/res/res/values-ta/strings.xml
index ad49382..6a7973e 100644
--- a/core/res/res/values-ta/strings.xml
+++ b/core/res/res/values-ta/strings.xml
@@ -1611,7 +1611,7 @@
<string name="default_audio_route_name" product="tv" msgid="4908971385068087367">"டிவி"</string>
<string name="default_audio_route_name" product="default" msgid="9213546147739983977">"ஃபோன்"</string>
<string name="default_audio_route_name_dock_speakers" msgid="1551166029093995289">"மொபைல் வைக்கும் கருவியின் ஸ்பீக்கர்கள்"</string>
- <string name="default_audio_route_name_hdmi" msgid="5474470558160717850">"HDMI"</string>
+ <string name="default_audio_route_name_external_device" msgid="5474470558160717850">"HDMI"</string>
<string name="default_audio_route_name_headphones" msgid="6954070994792640762">"ஹெட்ஃபோன்கள்"</string>
<string name="default_audio_route_name_usb" msgid="895668743163316932">"USB"</string>
<string name="default_audio_route_category_name" msgid="5241740395748134483">"சிஸ்டம்"</string>
diff --git a/core/res/res/values-te/strings.xml b/core/res/res/values-te/strings.xml
index fe0efad..8c53b13 100644
--- a/core/res/res/values-te/strings.xml
+++ b/core/res/res/values-te/strings.xml
@@ -1611,7 +1611,7 @@
<string name="default_audio_route_name" product="tv" msgid="4908971385068087367">"టీవీ"</string>
<string name="default_audio_route_name" product="default" msgid="9213546147739983977">"ఫోన్"</string>
<string name="default_audio_route_name_dock_speakers" msgid="1551166029093995289">"డాక్ స్పీకర్లు"</string>
- <string name="default_audio_route_name_hdmi" msgid="5474470558160717850">"HDMI"</string>
+ <string name="default_audio_route_name_external_device" msgid="5474470558160717850">"HDMI"</string>
<string name="default_audio_route_name_headphones" msgid="6954070994792640762">"హెడ్ఫోన్లు"</string>
<string name="default_audio_route_name_usb" msgid="895668743163316932">"USB"</string>
<string name="default_audio_route_category_name" msgid="5241740395748134483">"సిస్టమ్"</string>
diff --git a/core/res/res/values-th/strings.xml b/core/res/res/values-th/strings.xml
index c60db37..7826774 100644
--- a/core/res/res/values-th/strings.xml
+++ b/core/res/res/values-th/strings.xml
@@ -1611,7 +1611,7 @@
<string name="default_audio_route_name" product="tv" msgid="4908971385068087367">"ทีวี"</string>
<string name="default_audio_route_name" product="default" msgid="9213546147739983977">"โทรศัพท์"</string>
<string name="default_audio_route_name_dock_speakers" msgid="1551166029093995289">"ลำโพงแท่นชาร์จ"</string>
- <string name="default_audio_route_name_hdmi" msgid="5474470558160717850">"HDMI"</string>
+ <string name="default_audio_route_name_external_device" msgid="5474470558160717850">"HDMI"</string>
<string name="default_audio_route_name_headphones" msgid="6954070994792640762">"หูฟัง"</string>
<string name="default_audio_route_name_usb" msgid="895668743163316932">"USB"</string>
<string name="default_audio_route_category_name" msgid="5241740395748134483">"ระบบ"</string>
diff --git a/core/res/res/values-tl/strings.xml b/core/res/res/values-tl/strings.xml
index 4f8e7a3e..e9d17a9 100644
--- a/core/res/res/values-tl/strings.xml
+++ b/core/res/res/values-tl/strings.xml
@@ -1611,7 +1611,7 @@
<string name="default_audio_route_name" product="tv" msgid="4908971385068087367">"TV"</string>
<string name="default_audio_route_name" product="default" msgid="9213546147739983977">"Telepono"</string>
<string name="default_audio_route_name_dock_speakers" msgid="1551166029093995289">"Mga speaker ng dock"</string>
- <string name="default_audio_route_name_hdmi" msgid="5474470558160717850">"HDMI"</string>
+ <string name="default_audio_route_name_external_device" msgid="5474470558160717850">"HDMI"</string>
<string name="default_audio_route_name_headphones" msgid="6954070994792640762">"Mga Headphone"</string>
<string name="default_audio_route_name_usb" msgid="895668743163316932">"USB"</string>
<string name="default_audio_route_category_name" msgid="5241740395748134483">"System"</string>
diff --git a/core/res/res/values-tr/strings.xml b/core/res/res/values-tr/strings.xml
index d2c7958..762b731 100644
--- a/core/res/res/values-tr/strings.xml
+++ b/core/res/res/values-tr/strings.xml
@@ -1611,7 +1611,7 @@
<string name="default_audio_route_name" product="tv" msgid="4908971385068087367">"TV"</string>
<string name="default_audio_route_name" product="default" msgid="9213546147739983977">"Telefon"</string>
<string name="default_audio_route_name_dock_speakers" msgid="1551166029093995289">"Yuva hoparlörleri"</string>
- <string name="default_audio_route_name_hdmi" msgid="5474470558160717850">"HDMI"</string>
+ <string name="default_audio_route_name_external_device" msgid="5474470558160717850">"HDMI"</string>
<string name="default_audio_route_name_headphones" msgid="6954070994792640762">"Kulaklıklar"</string>
<string name="default_audio_route_name_usb" msgid="895668743163316932">"USB"</string>
<string name="default_audio_route_category_name" msgid="5241740395748134483">"Sistem"</string>
diff --git a/core/res/res/values-uk/strings.xml b/core/res/res/values-uk/strings.xml
index 9223d9a..730cfac 100644
--- a/core/res/res/values-uk/strings.xml
+++ b/core/res/res/values-uk/strings.xml
@@ -1613,7 +1613,7 @@
<string name="default_audio_route_name" product="tv" msgid="4908971385068087367">"Телевізор"</string>
<string name="default_audio_route_name" product="default" msgid="9213546147739983977">"Телефон"</string>
<string name="default_audio_route_name_dock_speakers" msgid="1551166029093995289">"Динаміки док-станції"</string>
- <string name="default_audio_route_name_hdmi" msgid="5474470558160717850">"HDMI"</string>
+ <string name="default_audio_route_name_external_device" msgid="5474470558160717850">"HDMI"</string>
<string name="default_audio_route_name_headphones" msgid="6954070994792640762">"Навушники"</string>
<string name="default_audio_route_name_usb" msgid="895668743163316932">"USB"</string>
<string name="default_audio_route_category_name" msgid="5241740395748134483">"Система"</string>
diff --git a/core/res/res/values-ur/strings.xml b/core/res/res/values-ur/strings.xml
index 5c6c555..6fa0071 100644
--- a/core/res/res/values-ur/strings.xml
+++ b/core/res/res/values-ur/strings.xml
@@ -1611,7 +1611,7 @@
<string name="default_audio_route_name" product="tv" msgid="4908971385068087367">"TV"</string>
<string name="default_audio_route_name" product="default" msgid="9213546147739983977">"فون"</string>
<string name="default_audio_route_name_dock_speakers" msgid="1551166029093995289">"ڈاک اسپیکرز"</string>
- <string name="default_audio_route_name_hdmi" msgid="5474470558160717850">"HDMI"</string>
+ <string name="default_audio_route_name_external_device" msgid="5474470558160717850">"HDMI"</string>
<string name="default_audio_route_name_headphones" msgid="6954070994792640762">"ہیڈ فونز"</string>
<string name="default_audio_route_name_usb" msgid="895668743163316932">"USB"</string>
<string name="default_audio_route_category_name" msgid="5241740395748134483">"سسٹم"</string>
diff --git a/core/res/res/values-uz/strings.xml b/core/res/res/values-uz/strings.xml
index 99e2a57..b9a0ae5 100644
--- a/core/res/res/values-uz/strings.xml
+++ b/core/res/res/values-uz/strings.xml
@@ -1611,7 +1611,7 @@
<string name="default_audio_route_name" product="tv" msgid="4908971385068087367">"TV"</string>
<string name="default_audio_route_name" product="default" msgid="9213546147739983977">"Telefon"</string>
<string name="default_audio_route_name_dock_speakers" msgid="1551166029093995289">"Taglik karnaylar"</string>
- <string name="default_audio_route_name_hdmi" msgid="5474470558160717850">"HDMI"</string>
+ <string name="default_audio_route_name_external_device" msgid="5474470558160717850">"HDMI"</string>
<string name="default_audio_route_name_headphones" msgid="6954070994792640762">"Quloq karnaychalari"</string>
<string name="default_audio_route_name_usb" msgid="895668743163316932">"USB"</string>
<string name="default_audio_route_category_name" msgid="5241740395748134483">"Tizim"</string>
diff --git a/core/res/res/values-vi/strings.xml b/core/res/res/values-vi/strings.xml
index 965e520..ad4a3899 100644
--- a/core/res/res/values-vi/strings.xml
+++ b/core/res/res/values-vi/strings.xml
@@ -1611,7 +1611,7 @@
<string name="default_audio_route_name" product="tv" msgid="4908971385068087367">"TV"</string>
<string name="default_audio_route_name" product="default" msgid="9213546147739983977">"Điện thoại"</string>
<string name="default_audio_route_name_dock_speakers" msgid="1551166029093995289">"Loa đế"</string>
- <string name="default_audio_route_name_hdmi" msgid="5474470558160717850">"HDMI"</string>
+ <string name="default_audio_route_name_external_device" msgid="5474470558160717850">"HDMI"</string>
<string name="default_audio_route_name_headphones" msgid="6954070994792640762">"Tai nghe"</string>
<string name="default_audio_route_name_usb" msgid="895668743163316932">"USB"</string>
<string name="default_audio_route_category_name" msgid="5241740395748134483">"Hệ thống"</string>
diff --git a/core/res/res/values-zh-rCN/strings.xml b/core/res/res/values-zh-rCN/strings.xml
index 02f0ac8..ce5cd53 100644
--- a/core/res/res/values-zh-rCN/strings.xml
+++ b/core/res/res/values-zh-rCN/strings.xml
@@ -1611,7 +1611,7 @@
<string name="default_audio_route_name" product="tv" msgid="4908971385068087367">"电视"</string>
<string name="default_audio_route_name" product="default" msgid="9213546147739983977">"手机"</string>
<string name="default_audio_route_name_dock_speakers" msgid="1551166029093995289">"基座扬声器"</string>
- <string name="default_audio_route_name_hdmi" msgid="5474470558160717850">"HDMI"</string>
+ <string name="default_audio_route_name_external_device" msgid="5474470558160717850">"HDMI"</string>
<string name="default_audio_route_name_headphones" msgid="6954070994792640762">"耳机"</string>
<string name="default_audio_route_name_usb" msgid="895668743163316932">"USB"</string>
<string name="default_audio_route_category_name" msgid="5241740395748134483">"系统"</string>
diff --git a/core/res/res/values-zh-rHK/strings.xml b/core/res/res/values-zh-rHK/strings.xml
index 40e313c..96c7b0b 100644
--- a/core/res/res/values-zh-rHK/strings.xml
+++ b/core/res/res/values-zh-rHK/strings.xml
@@ -1611,7 +1611,7 @@
<string name="default_audio_route_name" product="tv" msgid="4908971385068087367">"電視"</string>
<string name="default_audio_route_name" product="default" msgid="9213546147739983977">"手機"</string>
<string name="default_audio_route_name_dock_speakers" msgid="1551166029093995289">"插座喇叭"</string>
- <string name="default_audio_route_name_hdmi" msgid="5474470558160717850">"HDMI"</string>
+ <string name="default_audio_route_name_external_device" msgid="5474470558160717850">"HDMI"</string>
<string name="default_audio_route_name_headphones" msgid="6954070994792640762">"耳機"</string>
<string name="default_audio_route_name_usb" msgid="895668743163316932">"USB"</string>
<string name="default_audio_route_category_name" msgid="5241740395748134483">"系統"</string>
diff --git a/core/res/res/values-zh-rTW/strings.xml b/core/res/res/values-zh-rTW/strings.xml
index 147b38b..46d95c7f 100644
--- a/core/res/res/values-zh-rTW/strings.xml
+++ b/core/res/res/values-zh-rTW/strings.xml
@@ -1611,7 +1611,7 @@
<string name="default_audio_route_name" product="tv" msgid="4908971385068087367">"電視"</string>
<string name="default_audio_route_name" product="default" msgid="9213546147739983977">"手機"</string>
<string name="default_audio_route_name_dock_speakers" msgid="1551166029093995289">"座架喇叭"</string>
- <string name="default_audio_route_name_hdmi" msgid="5474470558160717850">"HDMI"</string>
+ <string name="default_audio_route_name_external_device" msgid="5474470558160717850">"HDMI"</string>
<string name="default_audio_route_name_headphones" msgid="6954070994792640762">"耳機"</string>
<string name="default_audio_route_name_usb" msgid="895668743163316932">"USB"</string>
<string name="default_audio_route_category_name" msgid="5241740395748134483">"系統"</string>
diff --git a/core/res/res/values-zu/strings.xml b/core/res/res/values-zu/strings.xml
index 723e0b2..6e640c6 100644
--- a/core/res/res/values-zu/strings.xml
+++ b/core/res/res/values-zu/strings.xml
@@ -1611,7 +1611,7 @@
<string name="default_audio_route_name" product="tv" msgid="4908971385068087367">"I-TV"</string>
<string name="default_audio_route_name" product="default" msgid="9213546147739983977">"Ifoni"</string>
<string name="default_audio_route_name_dock_speakers" msgid="1551166029093995289">"Izipikha ze-Dock"</string>
- <string name="default_audio_route_name_hdmi" msgid="5474470558160717850">"HDMI"</string>
+ <string name="default_audio_route_name_external_device" msgid="5474470558160717850">"HDMI"</string>
<string name="default_audio_route_name_headphones" msgid="6954070994792640762">"Ama-headphone"</string>
<string name="default_audio_route_name_usb" msgid="895668743163316932">"I-USB"</string>
<string name="default_audio_route_category_name" msgid="5241740395748134483">"Isistimu"</string>
diff --git a/core/res/res/values/config.xml b/core/res/res/values/config.xml
index f685415..dfada13 100644
--- a/core/res/res/values/config.xml
+++ b/core/res/res/values/config.xml
@@ -1733,7 +1733,7 @@
<item name="default_lock_wallpaper" type="drawable">@null</item>
<!-- Component name of the built in wallpaper used to display bitmap wallpapers. This must not be null. -->
- <string name="image_wallpaper_component" translatable="false">com.android.systemui/com.android.systemui.ImageWallpaper</string>
+ <string name="image_wallpaper_component" translatable="false">com.android.systemui/com.android.systemui.wallpapers.ImageWallpaper</string>
<!-- True if WallpaperService is enabled -->
<bool name="config_enableWallpaperService">true</bool>
diff --git a/core/res/res/values/strings.xml b/core/res/res/values/strings.xml
index ef33a22..63eb83e 100644
--- a/core/res/res/values/strings.xml
+++ b/core/res/res/values/strings.xml
@@ -1689,7 +1689,7 @@
<!-- Message shown during fingerprint acquisision when the fingerprint cannot be recognized -->
<string name="fingerprint_acquired_partial">Press firmly on the sensor</string>
<!-- Message shown during fingerprint acquisision when the fingerprint cannot be recognized -->
- <string name="fingerprint_acquired_insufficient">Couldn\'t process fingerprint. Please try again.</string>
+ <string name="fingerprint_acquired_insufficient">Can\u2019t recognize fingerprint. Try again.</string>
<!-- Message shown during fingerprint acquisision when the fingerprint sensor needs cleaning -->
<string name="fingerprint_acquired_imager_dirty">Clean fingerprint sensor and try again</string>
<string name="fingerprint_acquired_imager_dirty_alt">Clean sensor and try again</string>
@@ -1725,17 +1725,17 @@
<!-- Error message shown when the fingerprint hardware has run out of room for storing fingerprints -->
<string name="fingerprint_error_no_space">Can\u2019t set up fingerprint</string>
<!-- Error message shown when the fingerprint hardware timer has expired and the user needs to restart the operation. -->
- <string name="fingerprint_error_timeout">Fingerprint time out reached. Try again.</string>
+ <string name="fingerprint_error_timeout">Fingerprint setup timed out. Try again.</string>
<!-- Generic error message shown when the fingerprint operation (e.g. enrollment or authentication) is canceled. Generally not shown to the user-->
<string name="fingerprint_error_canceled">Fingerprint operation canceled.</string>
<!-- Generic error message shown when the fingerprint authentication operation is canceled due to user input. Generally not shown to the user -->
<string name="fingerprint_error_user_canceled">Fingerprint operation canceled by user.</string>
<!-- Generic error message shown when the fingerprint operation fails because too many attempts have been made. -->
- <string name="fingerprint_error_lockout">Too many attempts. Try again later.</string>
+ <string name="fingerprint_error_lockout">Too many attempts. Use screen lock instead.</string>
<!-- Generic error message shown when the fingerprint operation fails because strong authentication is required -->
<string name="fingerprint_error_lockout_permanent">Too many attempts. Use screen lock instead.</string>
<!-- Generic error message shown when the fingerprint hardware can't recognize the fingerprint -->
- <string name="fingerprint_error_unable_to_process">Try again.</string>
+ <string name="fingerprint_error_unable_to_process">Can\u2019t process fingerprint. Try again.</string>
<!-- Generic error message shown when the user has no enrolled fingerprints -->
<string name="fingerprint_error_no_fingerprints">No fingerprints enrolled.</string>
<!-- Generic error message shown when the app requests fingerprint authentication on a device without a sensor -->
@@ -4525,8 +4525,8 @@
<!-- Name of the default audio route when an audio dock is connected. [CHAR LIMIT=50] -->
<string name="default_audio_route_name_dock_speakers">Dock speakers</string>
- <!-- Name of the default audio route when HDMI is connected. [CHAR LIMIT=50] -->
- <string name="default_audio_route_name_hdmi">HDMI</string>
+ <!-- Name of the default audio route when an external device is connected. [CHAR LIMIT=50] -->
+ <string name="default_audio_route_name_external_device">External Device</string>
<!-- Name of the default audio route when wired headphones are
connected. [CHAR LIMIT=50] -->
diff --git a/core/res/res/values/symbols.xml b/core/res/res/values/symbols.xml
index 9df1515..66bfbb6 100644
--- a/core/res/res/values/symbols.xml
+++ b/core/res/res/values/symbols.xml
@@ -1082,7 +1082,7 @@
<java-symbol type="string" name="default_audio_route_id" />
<java-symbol type="string" name="default_audio_route_name" />
<java-symbol type="string" name="default_audio_route_name_dock_speakers" />
- <java-symbol type="string" name="default_audio_route_name_hdmi" />
+ <java-symbol type="string" name="default_audio_route_name_external_device" />
<java-symbol type="string" name="default_audio_route_name_headphones" />
<java-symbol type="string" name="default_audio_route_name_usb" />
<java-symbol type="string" name="default_audio_route_category_name" />
diff --git a/core/tests/coretests/src/com/android/internal/jank/DisplayResolutionTrackerTest.java b/core/tests/coretests/src/com/android/internal/jank/DisplayResolutionTrackerTest.java
new file mode 100644
index 0000000..5021022
--- /dev/null
+++ b/core/tests/coretests/src/com/android/internal/jank/DisplayResolutionTrackerTest.java
@@ -0,0 +1,86 @@
+/*
+ * 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.internal.jank;
+
+import static com.android.internal.jank.DisplayResolutionTracker.getResolution;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+
+import android.hardware.display.DisplayManager;
+import android.view.DisplayInfo;
+
+import androidx.test.filters.SmallTest;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.mockito.ArgumentCaptor;
+
+@SmallTest
+public class DisplayResolutionTrackerTest {
+ private static final DisplayInfo SD = makeDisplayInfo(800, 600);
+ private static final DisplayInfo HD = makeDisplayInfo(720, 1280);
+ private static final DisplayInfo FHD = makeDisplayInfo(2340, 1080);
+ private static final DisplayInfo QHD = makeDisplayInfo(3120, 1440);
+
+ private DisplayResolutionTracker.DisplayInterface mDisplayManager;
+ private ArgumentCaptor<DisplayManager.DisplayListener> mListenerCaptor;
+ private DisplayResolutionTracker mTracker;
+
+ @Before
+ public void setup() throws Exception {
+ mDisplayManager = mock(DisplayResolutionTracker.DisplayInterface.class);
+ mListenerCaptor = ArgumentCaptor.forClass(DisplayManager.DisplayListener.class);
+
+ mTracker = new DisplayResolutionTracker(mDisplayManager);
+
+ verify(mDisplayManager).registerDisplayListener(mListenerCaptor.capture());
+ }
+
+ @Test
+ public void testResolutionMapping() {
+ assertThat(getResolution(SD)).isEqualTo(DisplayResolutionTracker.RESOLUTION_SD);
+ assertThat(getResolution(HD)).isEqualTo(DisplayResolutionTracker.RESOLUTION_HD);
+ assertThat(getResolution(FHD)).isEqualTo(DisplayResolutionTracker.RESOLUTION_FHD);
+ assertThat(getResolution(QHD)).isEqualTo(DisplayResolutionTracker.RESOLUTION_QHD);
+ }
+
+ @Test
+ public void testResolutionUpdatesOnDisplayChanges() throws Exception {
+ assertThat(mTracker.getResolution(42))
+ .isEqualTo(DisplayResolutionTracker.RESOLUTION_UNKNOWN);
+
+ when(mDisplayManager.getDisplayInfo(42)).thenReturn(FHD, QHD);
+
+ mListenerCaptor.getValue().onDisplayAdded(42);
+ assertThat(mTracker.getResolution(42))
+ .isEqualTo(DisplayResolutionTracker.RESOLUTION_FHD);
+ mListenerCaptor.getValue().onDisplayChanged(42);
+ assertThat(mTracker.getResolution(42))
+ .isEqualTo(DisplayResolutionTracker.RESOLUTION_QHD);
+ }
+
+ private static DisplayInfo makeDisplayInfo(int width, int height) {
+ DisplayInfo info = new DisplayInfo();
+ info.logicalWidth = width;
+ info.logicalHeight = height;
+ return info;
+ }
+}
diff --git a/core/tests/coretests/src/com/android/internal/jank/FrameTrackerTest.java b/core/tests/coretests/src/com/android/internal/jank/FrameTrackerTest.java
index e068730..dbbd705 100644
--- a/core/tests/coretests/src/com/android/internal/jank/FrameTrackerTest.java
+++ b/core/tests/coretests/src/com/android/internal/jank/FrameTrackerTest.java
@@ -124,6 +124,7 @@
when(config.isSurfaceOnly()).thenReturn(surfaceOnly);
when(config.getSurfaceControl()).thenReturn(mSurfaceControl);
when(config.shouldDeferMonitor()).thenReturn(true);
+ when(config.getDisplayId()).thenReturn(42);
View view = mRule.getActivity().getWindow().getDecorView();
Handler spyHandler = spy(new Handler(handler.getLooper()));
when(config.getView()).thenReturn(surfaceOnly ? null : view);
@@ -168,6 +169,7 @@
verify(tracker).removeObservers();
verify(tracker, never()).triggerPerfetto();
verify(mStatsLog).write(eq(UI_INTERACTION_FRAME_INFO_REPORTED),
+ eq(42), /* displayId */
eq(CUJ_TO_STATSD_INTERACTION_TYPE[CUJ_NOTIFICATION_SHADE_EXPAND_COLLAPSE]),
eq(2L) /* totalFrames */,
eq(0L) /* missedFrames */,
@@ -204,6 +206,7 @@
verify(tracker).triggerPerfetto();
verify(mStatsLog).write(eq(UI_INTERACTION_FRAME_INFO_REPORTED),
+ eq(42), /* displayId */
eq(CUJ_TO_STATSD_INTERACTION_TYPE[CUJ_NOTIFICATION_SHADE_EXPAND_COLLAPSE]),
eq(2L) /* totalFrames */,
eq(1L) /* missedFrames */,
@@ -240,6 +243,7 @@
verify(tracker, never()).triggerPerfetto();
verify(mStatsLog).write(eq(UI_INTERACTION_FRAME_INFO_REPORTED),
+ eq(42), /* displayId */
eq(CUJ_TO_STATSD_INTERACTION_TYPE[CUJ_NOTIFICATION_SHADE_EXPAND_COLLAPSE]),
eq(2L) /* totalFrames */,
eq(0L) /* missedFrames */,
@@ -276,6 +280,7 @@
verify(tracker).triggerPerfetto();
verify(mStatsLog).write(eq(UI_INTERACTION_FRAME_INFO_REPORTED),
+ eq(42), /* displayId */
eq(CUJ_TO_STATSD_INTERACTION_TYPE[CUJ_NOTIFICATION_SHADE_EXPAND_COLLAPSE]),
eq(2L) /* totalFrames */,
eq(1L) /* missedFrames */,
@@ -315,6 +320,7 @@
verify(tracker).triggerPerfetto();
verify(mStatsLog).write(eq(UI_INTERACTION_FRAME_INFO_REPORTED),
+ eq(42), /* displayId */
eq(CUJ_TO_STATSD_INTERACTION_TYPE[CUJ_NOTIFICATION_SHADE_EXPAND_COLLAPSE]),
eq(2L) /* totalFrames */,
eq(1L) /* missedFrames */,
@@ -356,6 +362,7 @@
verify(tracker).removeObservers();
verify(tracker, never()).triggerPerfetto();
verify(mStatsLog).write(eq(UI_INTERACTION_FRAME_INFO_REPORTED),
+ eq(42), /* displayId */
eq(CUJ_TO_STATSD_INTERACTION_TYPE[CUJ_NOTIFICATION_SHADE_EXPAND_COLLAPSE]),
eq(2L) /* totalFrames */,
eq(0L) /* missedFrames */,
@@ -483,6 +490,7 @@
verify(tracker).triggerPerfetto();
verify(mStatsLog).write(eq(UI_INTERACTION_FRAME_INFO_REPORTED),
+ eq(42), /* displayId */
eq(CUJ_TO_STATSD_INTERACTION_TYPE[CUJ_WALLPAPER_TRANSITION]),
eq(2L) /* totalFrames */,
eq(1L) /* missedFrames */,
@@ -519,6 +527,7 @@
verify(tracker, never()).triggerPerfetto();
verify(mStatsLog).write(eq(UI_INTERACTION_FRAME_INFO_REPORTED),
+ eq(42), /* displayId */
eq(CUJ_TO_STATSD_INTERACTION_TYPE[CUJ_WALLPAPER_TRANSITION]),
eq(2L) /* totalFrames */,
eq(0L) /* missedFrames */,
@@ -555,6 +564,7 @@
verify(tracker, never()).triggerPerfetto();
verify(mStatsLog).write(eq(UI_INTERACTION_FRAME_INFO_REPORTED),
+ eq(42), /* displayId */
eq(CUJ_TO_STATSD_INTERACTION_TYPE[CUJ_WALLPAPER_TRANSITION]),
eq(2L) /* totalFrames */,
eq(0L) /* missedFrames */,
@@ -585,6 +595,7 @@
verify(mSurfaceControlWrapper).removeJankStatsListener(any());
verify(tracker).triggerPerfetto();
verify(mStatsLog).write(eq(UI_INTERACTION_FRAME_INFO_REPORTED),
+ eq(42), /* displayId */
eq(CUJ_TO_STATSD_INTERACTION_TYPE[CUJ_WALLPAPER_TRANSITION]),
eq(6L) /* totalFrames */,
eq(5L) /* missedFrames */,
diff --git a/core/tests/coretests/src/com/android/internal/jank/InteractionJankMonitorTest.java b/core/tests/coretests/src/com/android/internal/jank/InteractionJankMonitorTest.java
index 1519e48..4770fa6 100644
--- a/core/tests/coretests/src/com/android/internal/jank/InteractionJankMonitorTest.java
+++ b/core/tests/coretests/src/com/android/internal/jank/InteractionJankMonitorTest.java
@@ -354,10 +354,11 @@
when(configuration.isSurfaceOnly()).thenReturn(false);
when(configuration.getView()).thenReturn(mView);
when(configuration.getHandler()).thenReturn(mView.getHandler());
+ when(configuration.getDisplayId()).thenReturn(42);
FrameTracker tracker = spy(new FrameTracker(monitor, session, mWorker.getThreadHandler(),
threadedRenderer, viewRoot, surfaceControl, choreographer,
- new FrameMetricsWrapper(), new StatsLogWrapper(),
+ new FrameMetricsWrapper(), new StatsLogWrapper(null),
/* traceThresholdMissedFrames= */ 1,
/* traceThresholdFrameTimeMillis= */ -1, listener, configuration));
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/pip/phone/PipController.java b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/phone/PipController.java
index 61fafb5..3d879b6 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/pip/phone/PipController.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/phone/PipController.java
@@ -114,6 +114,9 @@
UserChangeListener {
private static final String TAG = "PipController";
+ private static final long PIP_KEEP_CLEAR_AREAS_DELAY =
+ SystemProperties.getLong("persist.wm.debug.pip_keep_clear_areas_delay", 200);
+
private boolean mEnablePipKeepClearAlgorithm =
SystemProperties.getBoolean("persist.wm.debug.enable_pip_keep_clear_algorithm", false);
@@ -146,6 +149,8 @@
private final Rect mTmpInsetBounds = new Rect();
private final int mEnterAnimationDuration;
+ private final Runnable mMovePipInResponseToKeepClearAreasChangeCallback;
+
private boolean mIsInFixedRotation;
private PipAnimationListener mPinnedStackAnimationRecentsCallback;
@@ -277,14 +282,12 @@
if (mPipBoundsState.getDisplayId() == displayId) {
if (mEnablePipKeepClearAlgorithm) {
mPipBoundsState.setKeepClearAreas(restricted, unrestricted);
- // only move if already in pip, other transitions account for keep clear
- // areas
- if (mPipTransitionState.hasEnteredPip()) {
- Rect destBounds = mPipKeepClearAlgorithm.adjust(mPipBoundsState,
- mPipBoundsAlgorithm);
- mPipTaskOrganizer.scheduleAnimateResizePip(destBounds,
- mEnterAnimationDuration, null);
- }
+
+ mMainExecutor.removeCallbacks(
+ mMovePipInResponseToKeepClearAreasChangeCallback);
+ mMainExecutor.executeDelayed(
+ mMovePipInResponseToKeepClearAreasChangeCallback,
+ PIP_KEEP_CLEAR_AREAS_DELAY);
}
}
}
@@ -411,6 +414,15 @@
mEnterAnimationDuration = mContext.getResources()
.getInteger(R.integer.config_pipEnterAnimationDuration);
+ mMovePipInResponseToKeepClearAreasChangeCallback = () -> {
+ // only move if already in pip, other transitions account for keep clear areas
+ if (mPipTransitionState.hasEnteredPip()) {
+ Rect destBounds = mPipKeepClearAlgorithm.adjust(mPipBoundsState,
+ mPipBoundsAlgorithm);
+ mPipTaskOrganizer.scheduleAnimateResizePip(destBounds,
+ mEnterAnimationDuration, null);
+ }
+ };
mPipParamsChangedForwarder = pipParamsChangedForwarder;
mDisplayInsetsController = displayInsetsController;
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 9c9841f..8ed16ce 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
@@ -1887,7 +1887,6 @@
// properly for the animation itself.
mSplitLayout.release();
mSplitLayout.resetDividerPosition();
- mSideStagePosition = SPLIT_POSITION_BOTTOM_OR_RIGHT;
mTopStageAfterFoldDismiss = STAGE_TYPE_UNDEFINED;
}
}
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 2dccda6f..fac0f73 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,6 @@
package com.android.wm.shell.flicker.bubble
import android.os.SystemClock
-import android.platform.test.annotations.Postsubmit
import android.platform.test.annotations.Presubmit
import androidx.test.filters.RequiresDevice
import androidx.test.uiautomator.By
@@ -90,70 +89,4 @@
this.isVisible(testApp)
}
}
-
- /** {@inheritDoc} */
- @Postsubmit
- @Test
- override fun entireScreenCovered() =
- super.entireScreenCovered()
-
- /** {@inheritDoc} */
- @Postsubmit
- @Test
- override fun navBarLayerIsVisibleAtStartAndEnd() =
- super.navBarLayerIsVisibleAtStartAndEnd()
-
- /** {@inheritDoc} */
- @Postsubmit
- @Test
- override fun navBarLayerPositionAtStartAndEnd() =
- super.navBarLayerPositionAtStartAndEnd()
-
- /** {@inheritDoc} */
- @Postsubmit
- @Test
- override fun navBarWindowIsAlwaysVisible() =
- super.navBarWindowIsAlwaysVisible()
-
- /** {@inheritDoc} */
- @Postsubmit
- @Test
- override fun statusBarLayerIsVisibleAtStartAndEnd() =
- super.statusBarLayerIsVisibleAtStartAndEnd()
-
- /** {@inheritDoc} */
- @Postsubmit
- @Test
- override fun statusBarLayerPositionAtStartAndEnd() =
- super.statusBarLayerPositionAtStartAndEnd()
-
- /** {@inheritDoc} */
- @Postsubmit
- @Test
- override fun statusBarWindowIsAlwaysVisible() =
- super.statusBarWindowIsAlwaysVisible()
-
- /** {@inheritDoc} */
- @Postsubmit
- @Test
- override fun taskBarLayerIsVisibleAtStartAndEnd() =
- super.taskBarLayerIsVisibleAtStartAndEnd()
-
- /** {@inheritDoc} */
- @Postsubmit
- @Test
- override fun taskBarWindowIsAlwaysVisible() =
- super.taskBarWindowIsAlwaysVisible()
-
- /** {@inheritDoc} */
- @Postsubmit
- @Test
- override fun visibleLayersShownMoreThanOneConsecutiveEntry() =
- super.visibleLayersShownMoreThanOneConsecutiveEntry()
-
- /** {@inheritDoc} */
- @Postsubmit
- @Test
- override fun visibleWindowsShownMoreThanOneConsecutiveEntry() =
- super.visibleWindowsShownMoreThanOneConsecutiveEntry()
}
diff --git a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/AutoEnterPipOnGoToHomeTest.kt b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/AutoEnterPipOnGoToHomeTest.kt
index eebc97b..9684bb3 100644
--- a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/AutoEnterPipOnGoToHomeTest.kt
+++ b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/AutoEnterPipOnGoToHomeTest.kt
@@ -17,7 +17,7 @@
package com.android.wm.shell.flicker.pip
import android.platform.test.annotations.FlakyTest
-import android.platform.test.annotations.Postsubmit
+import android.platform.test.annotations.Presubmit
import android.view.Surface
import androidx.test.filters.RequiresDevice
import com.android.server.wm.flicker.FlickerParametersRunnerFactory
@@ -83,6 +83,7 @@
}
}
+ @FlakyTest
@Test
override fun pipLayerReduces() {
testSpec.assertLayers {
@@ -96,6 +97,7 @@
/**
* Checks that [pipApp] window is animated towards default position in right bottom corner
*/
+ @Presubmit
@Test
fun pipLayerMovesTowardsRightBottomCorner() {
// in gestural nav the swipe makes PiP first go upwards
@@ -111,66 +113,11 @@
}
}
+ @Presubmit
@Test
override fun focusChanges() {
// in gestural nav the focus goes to different activity on swipe up
Assume.assumeFalse(testSpec.isGesturalNavigation)
super.focusChanges()
}
-
- @Postsubmit
- @Test
- override fun entireScreenCovered() = super.entireScreenCovered()
-
- @Postsubmit
- @Test
- override fun navBarLayerIsVisibleAtStartAndEnd() = super.navBarLayerIsVisibleAtStartAndEnd()
-
- @Postsubmit
- @Test
- override fun navBarLayerPositionAtStartAndEnd() = super.navBarLayerPositionAtStartAndEnd()
-
- @Postsubmit
- @Test
- override fun navBarWindowIsAlwaysVisible() = super.navBarWindowIsAlwaysVisible()
-
- @Postsubmit
- @Test
- override fun pipAppLayerAlwaysVisible() = super.pipAppLayerAlwaysVisible()
-
- @Postsubmit
- @Test
- override fun pipLayerRemainInsideVisibleBounds() = super.pipLayerRemainInsideVisibleBounds()
-
- @Postsubmit
- @Test
- override fun statusBarLayerIsVisibleAtStartAndEnd() =
- super.statusBarLayerIsVisibleAtStartAndEnd()
-
- @Postsubmit
- @Test
- override fun statusBarLayerPositionAtStartAndEnd() =
- super.statusBarLayerPositionAtStartAndEnd()
-
- @Postsubmit
- @Test
- override fun statusBarWindowIsAlwaysVisible() = super.statusBarWindowIsAlwaysVisible()
-
- @Postsubmit
- @Test
- override fun taskBarLayerIsVisibleAtStartAndEnd() = super.taskBarLayerIsVisibleAtStartAndEnd()
-
- @Postsubmit
- @Test
- override fun taskBarWindowIsAlwaysVisible() = super.taskBarWindowIsAlwaysVisible()
-
- @Postsubmit
- @Test
- override fun visibleLayersShownMoreThanOneConsecutiveEntry() =
- super.visibleLayersShownMoreThanOneConsecutiveEntry()
-
- @Postsubmit
- @Test
- override fun visibleWindowsShownMoreThanOneConsecutiveEntry() =
- super.visibleWindowsShownMoreThanOneConsecutiveEntry()
}
diff --git a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/EnterPipOnUserLeaveHintTest.kt b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/EnterPipOnUserLeaveHintTest.kt
index bac6a0c..59f7ecf 100644
--- a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/EnterPipOnUserLeaveHintTest.kt
+++ b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/EnterPipOnUserLeaveHintTest.kt
@@ -17,7 +17,6 @@
package com.android.wm.shell.flicker.pip
import android.platform.test.annotations.FlakyTest
-import android.platform.test.annotations.Postsubmit
import android.platform.test.annotations.Presubmit
import android.view.Surface
import androidx.test.filters.RequiresDevice
@@ -81,7 +80,7 @@
}
}
- @Postsubmit
+ @Presubmit
@Test
override fun pipAppLayerAlwaysVisible() {
if (!testSpec.isGesturalNavigation) super.pipAppLayerAlwaysVisible() else {
@@ -94,7 +93,7 @@
}
}
- @Postsubmit
+ @Presubmit
@Test
override fun pipLayerReduces() {
// in gestural nav the pip enters through alpha animation
@@ -102,7 +101,7 @@
super.pipLayerReduces()
}
- @Postsubmit
+ @Presubmit
@Test
override fun focusChanges() {
// in gestural nav the focus goes to different activity on swipe up
@@ -110,11 +109,6 @@
super.focusChanges()
}
- /** {@inheritDoc} */
- @Postsubmit
- @Test
- override fun pipAppWindowAlwaysVisible() = super.pipAppWindowAlwaysVisible()
-
@Presubmit
@Test
override fun entireScreenCovered() {
@@ -129,7 +123,7 @@
super.entireScreenCovered()
}
- @Postsubmit
+ @Presubmit
@Test
override fun pipLayerRemainInsideVisibleBounds() {
if (!testSpec.isGesturalNavigation) super.pipLayerRemainInsideVisibleBounds() else {
diff --git a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/EnterPipToOtherOrientationTest.kt b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/EnterPipToOtherOrientationTest.kt
index f6bb534..87d800c 100644
--- a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/EnterPipToOtherOrientationTest.kt
+++ b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/EnterPipToOtherOrientationTest.kt
@@ -231,11 +231,6 @@
override fun visibleLayersShownMoreThanOneConsecutiveEntry() =
super.visibleLayersShownMoreThanOneConsecutiveEntry()
- /** {@inheritDoc} */
- @FlakyTest(bugId = 227313015)
- @Test
- override fun entireScreenCovered() = super.entireScreenCovered()
-
companion object {
/**
* Creates the test configurations.
diff --git a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/ExitPipTransition.kt b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/ExitPipTransition.kt
index 183c06f..0f7d8a9 100644
--- a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/ExitPipTransition.kt
+++ b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/ExitPipTransition.kt
@@ -16,7 +16,6 @@
package com.android.wm.shell.flicker.pip
-import android.platform.test.annotations.Postsubmit
import android.platform.test.annotations.Presubmit
import android.view.Surface
import com.android.server.wm.flicker.FlickerTestParameter
@@ -90,63 +89,4 @@
.isVisible(LAUNCHER)
}
}
-
- /** {@inheritDoc} */
- @Postsubmit
- @Test
- override fun visibleWindowsShownMoreThanOneConsecutiveEntry() =
- super.visibleWindowsShownMoreThanOneConsecutiveEntry()
-
- /** {@inheritDoc} */
- @Postsubmit
- @Test
- override fun visibleLayersShownMoreThanOneConsecutiveEntry() =
- super.visibleLayersShownMoreThanOneConsecutiveEntry()
-
- /** {@inheritDoc} */
- @Postsubmit
- @Test
- override fun taskBarLayerIsVisibleAtStartAndEnd() = super.taskBarLayerIsVisibleAtStartAndEnd()
-
- /** {@inheritDoc} */
- @Postsubmit
- @Test
- override fun taskBarWindowIsAlwaysVisible() = super.taskBarWindowIsAlwaysVisible()
-
- /** {@inheritDoc} */
- @Postsubmit
- @Test
- override fun entireScreenCovered() = super.entireScreenCovered()
-
- /** {@inheritDoc} */
- @Postsubmit
- @Test
- override fun navBarWindowIsAlwaysVisible() = super.navBarWindowIsAlwaysVisible()
-
- /** {@inheritDoc} */
- @Postsubmit
- @Test
- override fun statusBarWindowIsAlwaysVisible() = super.statusBarWindowIsAlwaysVisible()
-
- /** {@inheritDoc} */
- @Postsubmit
- @Test
- override fun statusBarLayerIsVisibleAtStartAndEnd() =
- super.statusBarLayerIsVisibleAtStartAndEnd()
-
- /** {@inheritDoc} */
- @Postsubmit
- @Test
- override fun navBarLayerPositionAtStartAndEnd() = super.navBarLayerPositionAtStartAndEnd()
-
- /** {@inheritDoc} */
- @Postsubmit
- @Test
- override fun navBarLayerIsVisibleAtStartAndEnd() = super.navBarLayerIsVisibleAtStartAndEnd()
-
- /** {@inheritDoc} */
- @Postsubmit
- @Test
- override fun statusBarLayerPositionAtStartAndEnd() =
- super.statusBarLayerPositionAtStartAndEnd()
}
diff --git a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/ExitPipViaIntentTest.kt b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/ExitPipViaIntentTest.kt
index 034f623..75018d1 100644
--- a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/ExitPipViaIntentTest.kt
+++ b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/ExitPipViaIntentTest.kt
@@ -78,7 +78,12 @@
}
/** {@inheritDoc} */
- @FlakyTest(bugId = 206753786)
+ @FlakyTest
+ @Test
+ override fun entireScreenCovered() = super.entireScreenCovered()
+
+ /** {@inheritDoc} */
+ @Presubmit
@Test
override fun statusBarLayerPositionAtStartAndEnd() {
Assume.assumeFalse(isShellTransitionsEnabled)
@@ -107,11 +112,6 @@
super.pipLayerExpands()
}
- /** {@inheritDoc} */
- @FlakyTest(bugId = 227313015)
- @Test
- override fun entireScreenCovered() = super.entireScreenCovered()
-
companion object {
/**
* Creates the test configurations.
diff --git a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/ExpandPipOnDoubleClickTest.kt b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/ExpandPipOnDoubleClickTest.kt
index 825aca3..4d39ec5 100644
--- a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/ExpandPipOnDoubleClickTest.kt
+++ b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/ExpandPipOnDoubleClickTest.kt
@@ -111,7 +111,7 @@
/**
* Checks that the visible region of [pipApp] always expands during the animation
*/
- @FlakyTest(bugId = 228012337)
+ @Presubmit
@Test
fun pipLayerExpands() {
testSpec.assertLayers {
diff --git a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/MovePipUpShelfHeightChangeTest.kt b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/MovePipUpShelfHeightChangeTest.kt
index 0b6e7ee..3e08bfb 100644
--- a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/MovePipUpShelfHeightChangeTest.kt
+++ b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/MovePipUpShelfHeightChangeTest.kt
@@ -16,7 +16,6 @@
package com.android.wm.shell.flicker.pip
-import android.platform.test.annotations.FlakyTest
import android.platform.test.annotations.RequiresDevice
import android.view.Surface
import com.android.server.wm.flicker.FlickerParametersRunnerFactory
@@ -29,7 +28,6 @@
import org.junit.Assume
import org.junit.Before
import org.junit.FixMethodOrder
-import org.junit.Test
import org.junit.runner.RunWith
import org.junit.runners.MethodSorters
import org.junit.runners.Parameterized
@@ -84,12 +82,6 @@
current.isLowerOrEqual(previous.region)
}
- /** {@inheritDoc} */
- @FlakyTest(bugId = 206753786)
- @Test
- override fun statusBarLayerPositionAtStartAndEnd() =
- super.statusBarLayerPositionAtStartAndEnd()
-
companion object {
/**
* Creates the test configurations.
diff --git a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/PipKeyboardTest.kt b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/PipKeyboardTest.kt
index df6ba98..27fc2ed 100644
--- a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/PipKeyboardTest.kt
+++ b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/PipKeyboardTest.kt
@@ -16,7 +16,6 @@
package com.android.wm.shell.flicker.pip
-import android.platform.test.annotations.FlakyTest
import android.platform.test.annotations.Presubmit
import android.view.Surface
import androidx.test.filters.RequiresDevice
@@ -76,12 +75,6 @@
}
}
- /** {@inheritDoc} */
- @FlakyTest(bugId = 206753786)
- @Test
- override fun statusBarLayerPositionAtStartAndEnd() =
- super.statusBarLayerPositionAtStartAndEnd()
-
/**
* Ensure the pip window remains visible throughout any keyboard interactions
*/
diff --git a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/PipRotationTest.kt b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/PipRotationTest.kt
index fc0f0ee..fd5ff29 100644
--- a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/PipRotationTest.kt
+++ b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/PipRotationTest.kt
@@ -17,6 +17,7 @@
package com.android.wm.shell.flicker.pip
import android.platform.test.annotations.FlakyTest
+import android.platform.test.annotations.Presubmit
import android.view.Surface
import androidx.test.filters.RequiresDevice
import com.android.server.wm.flicker.FlickerParametersRunnerFactory
@@ -24,7 +25,6 @@
import com.android.server.wm.flicker.FlickerTestParameterFactory
import com.android.server.wm.flicker.annotation.Group4
import com.android.server.wm.flicker.dsl.FlickerBuilder
-import com.android.server.wm.flicker.entireScreenCovered
import com.android.server.wm.flicker.helpers.WindowUtils
import com.android.server.wm.flicker.helpers.isShellTransitionsEnabled
import com.android.server.wm.flicker.helpers.setRotation
@@ -83,13 +83,6 @@
}
/**
- * Checks that all parts of the screen are covered at the start and end of the transition
- */
- @FlakyTest(bugId = 240499181)
- @Test
- override fun entireScreenCovered() = testSpec.entireScreenCovered()
-
- /**
* Checks the position of the navigation bar at the start and end of the transition
*/
@FlakyTest(bugId = 240499181)
@@ -99,7 +92,7 @@
/**
* Checks that [fixedApp] layer is within [screenBoundsStart] at the start of the transition
*/
- @FlakyTest(bugId = 240499181)
+ @Presubmit
@Test
fun fixedAppLayer_StartingBounds() {
testSpec.assertLayersStart {
@@ -110,7 +103,7 @@
/**
* Checks that [fixedApp] layer is within [screenBoundsEnd] at the end of the transition
*/
- @FlakyTest(bugId = 240499181)
+ @Presubmit
@Test
fun fixedAppLayer_EndingBounds() {
testSpec.assertLayersEnd {
@@ -122,7 +115,7 @@
* Checks that [fixedApp] plus [pipApp] layers are within [screenBoundsEnd] at the start
* of the transition
*/
- @FlakyTest(bugId = 240499181)
+ @Presubmit
@Test
fun appLayers_StartingBounds() {
testSpec.assertLayersStart {
@@ -134,7 +127,7 @@
* Checks that [fixedApp] plus [pipApp] layers are within [screenBoundsEnd] at the end
* of the transition
*/
- @FlakyTest(bugId = 240499181)
+ @Presubmit
@Test
fun appLayers_EndingBounds() {
testSpec.assertLayersEnd {
@@ -154,7 +147,7 @@
/**
* Checks that [pipApp] layer is within [screenBoundsStart] at the start of the transition
*/
- @FlakyTest(bugId = 240499181)
+ @Presubmit
@Test
fun pipLayerRotates_StartingBounds() {
pipLayerRotates_StartingBounds_internal()
@@ -163,7 +156,7 @@
/**
* Checks that [pipApp] layer is within [screenBoundsEnd] at the end of the transition
*/
- @FlakyTest(bugId = 240499181)
+ @Presubmit
@Test
fun pipLayerRotates_EndingBounds() {
testSpec.assertLayersEnd {
@@ -175,7 +168,7 @@
* Ensure that the [pipApp] window does not obscure the [fixedApp] at the start of the
* transition
*/
- @FlakyTest(bugId = 240499181)
+ @Presubmit
@Test
fun pipIsAboveFixedAppWindow_Start() {
testSpec.assertWmStart {
@@ -187,7 +180,7 @@
* Ensure that the [pipApp] window does not obscure the [fixedApp] at the end of the
* transition
*/
- @FlakyTest(bugId = 240499181)
+ @Presubmit
@Test
fun pipIsAboveFixedAppWindow_End() {
testSpec.assertWmEnd {
@@ -201,54 +194,6 @@
super.navBarLayerIsVisibleAtStartAndEnd()
}
- @FlakyTest(bugId = 240499181)
- @Test
- override fun navBarWindowIsAlwaysVisible() {
- super.navBarWindowIsAlwaysVisible()
- }
-
- @FlakyTest(bugId = 240499181)
- @Test
- override fun statusBarLayerIsVisibleAtStartAndEnd() {
- super.statusBarLayerIsVisibleAtStartAndEnd()
- }
-
- @FlakyTest(bugId = 240499181)
- @Test
- override fun statusBarLayerPositionAtStartAndEnd() {
- super.statusBarLayerPositionAtStartAndEnd()
- }
-
- @FlakyTest(bugId = 240499181)
- @Test
- override fun statusBarWindowIsAlwaysVisible() {
- super.statusBarWindowIsAlwaysVisible()
- }
-
- @FlakyTest(bugId = 240499181)
- @Test
- override fun taskBarLayerIsVisibleAtStartAndEnd() {
- super.taskBarLayerIsVisibleAtStartAndEnd()
- }
-
- @FlakyTest(bugId = 240499181)
- @Test
- override fun taskBarWindowIsAlwaysVisible() {
- super.taskBarWindowIsAlwaysVisible()
- }
-
- @FlakyTest(bugId = 240499181)
- @Test
- override fun visibleLayersShownMoreThanOneConsecutiveEntry() {
- super.visibleLayersShownMoreThanOneConsecutiveEntry()
- }
-
- @FlakyTest(bugId = 240499181)
- @Test
- override fun visibleWindowsShownMoreThanOneConsecutiveEntry() {
- super.visibleWindowsShownMoreThanOneConsecutiveEntry()
- }
-
companion object {
/**
* Creates the test configurations.
diff --git a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/PipRotationTest_ShellTransit.kt b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/PipRotationTest_ShellTransit.kt
index 0dd38cd..737f16a 100644
--- a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/PipRotationTest_ShellTransit.kt
+++ b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/PipRotationTest_ShellTransit.kt
@@ -25,6 +25,7 @@
import org.junit.Assume
import org.junit.Before
import org.junit.FixMethodOrder
+import org.junit.Test
import org.junit.runner.RunWith
import org.junit.runners.MethodSorters
import org.junit.runners.Parameterized
@@ -59,4 +60,10 @@
override fun before() {
Assume.assumeTrue(isShellTransitionsEnabled)
}
+
+ /** {@inheritDoc} */
+ @FlakyTest
+ @Test
+ override fun navBarLayerPositionAtStartAndEnd() =
+ super.navBarLayerPositionAtStartAndEnd()
}
diff --git a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/SetRequestedOrientationWhilePinnedTest.kt b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/SetRequestedOrientationWhilePinnedTest.kt
index acada4c..866e4e8 100644
--- a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/SetRequestedOrientationWhilePinnedTest.kt
+++ b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/SetRequestedOrientationWhilePinnedTest.kt
@@ -171,18 +171,6 @@
/** {@inheritDoc} */
@Postsubmit
@Test
- override fun visibleWindowsShownMoreThanOneConsecutiveEntry() =
- super.visibleWindowsShownMoreThanOneConsecutiveEntry()
-
- /** {@inheritDoc} */
- @Postsubmit
- @Test
- override fun visibleLayersShownMoreThanOneConsecutiveEntry() =
- super.visibleLayersShownMoreThanOneConsecutiveEntry()
-
- /** {@inheritDoc} */
- @Postsubmit
- @Test
override fun taskBarLayerIsVisibleAtStartAndEnd() = super.taskBarLayerIsVisibleAtStartAndEnd()
/** {@inheritDoc} */
@@ -193,25 +181,8 @@
/** {@inheritDoc} */
@Postsubmit
@Test
- override fun statusBarLayerPositionAtStartAndEnd() =
- super.statusBarLayerPositionAtStartAndEnd()
-
- /** {@inheritDoc} */
- @Postsubmit
- @Test
override fun entireScreenCovered() = super.entireScreenCovered()
- /** {@inheritDoc} */
- @Postsubmit
- @Test
- override fun navBarWindowIsAlwaysVisible() =
- super.navBarWindowIsAlwaysVisible()
-
- /** {@inheritDoc} */
- @Postsubmit
- @Test
- override fun statusBarWindowIsAlwaysVisible() = super.statusBarWindowIsAlwaysVisible()
-
companion object {
@Parameterized.Parameters(name = "{0}")
@JvmStatic
diff --git a/media/java/android/media/ImageReader.java b/media/java/android/media/ImageReader.java
index fde7afd..ca906d2 100644
--- a/media/java/android/media/ImageReader.java
+++ b/media/java/android/media/ImageReader.java
@@ -342,9 +342,14 @@
// Only include memory for 1 buffer, since actually accounting for the memory used is
// complex, and 1 buffer is enough for the VM to treat the ImageReader as being of some
// size.
- mEstimatedNativeAllocBytes = ImageUtils.getEstimatedNativeAllocBytes(
- width, height, useLegacyImageFormat ? imageFormat : hardwareBufferFormat,
- /*buffer count*/ 1);
+ if (hardwareBufferFormat == HardwareBuffer.BLOB) {
+ mEstimatedNativeAllocBytes = ImageUtils.getEstimatedNativeAllocBytes(
+ width, height, imageFormat, /*buffer count*/ 1);
+ } else {
+ mEstimatedNativeAllocBytes = ImageUtils.getEstimatedNativeAllocBytes(
+ width, height, useLegacyImageFormat ? imageFormat : hardwareBufferFormat,
+ /*buffer count*/ 1);
+ }
VMRuntime.getRuntime().registerNativeAllocation(mEstimatedNativeAllocBytes);
}
@@ -370,7 +375,6 @@
MultiResolutionImageReader parent, int hardwareBufferFormat, int dataSpace) {
mWidth = width;
mHeight = height;
- mFormat = ImageFormat.UNKNOWN; // set default image format value as UNKNOWN
mUsage = usage;
mMaxImages = maxImages;
mParent = parent;
@@ -378,6 +382,7 @@
mDataSpace = dataSpace;
mUseLegacyImageFormat = false;
mNumPlanes = ImageUtils.getNumPlanesForHardwareBufferFormat(mHardwareBufferFormat);
+ mFormat = PublicFormatUtils.getPublicFormat(hardwareBufferFormat, dataSpace);
initializeImageReader(width, height, mFormat, maxImages, usage, hardwareBufferFormat,
dataSpace, mUseLegacyImageFormat);
diff --git a/media/java/android/media/ImageWriter.java b/media/java/android/media/ImageWriter.java
index 9f52bf1..259c138 100644
--- a/media/java/android/media/ImageWriter.java
+++ b/media/java/android/media/ImageWriter.java
@@ -29,7 +29,6 @@
import android.hardware.HardwareBuffer;
import android.hardware.HardwareBuffer.Usage;
import android.hardware.SyncFence;
-import android.hardware.camera2.params.StreamConfigurationMap;
import android.hardware.camera2.utils.SurfaceUtils;
import android.os.Handler;
import android.os.Looper;
@@ -266,31 +265,11 @@
// nativeInit internally overrides UNKNOWN format. So does surface format query after
// nativeInit and before getEstimatedNativeAllocBytes().
imageFormat = SurfaceUtils.getSurfaceFormat(surface);
- mHardwareBufferFormat = PublicFormatUtils.getHalFormat(imageFormat);
- mDataSpace = PublicFormatUtils.getHalDataspace(imageFormat);
+ mDataSpace = dataSpace = PublicFormatUtils.getHalDataspace(dataSpace);
+ mHardwareBufferFormat =
+ hardwareBufferFormat = PublicFormatUtils.getHalFormat(imageFormat);
}
- // Several public formats use the same native HAL_PIXEL_FORMAT_BLOB. The native
- // allocation estimation sequence depends on the public formats values. To avoid
- // possible errors, convert where necessary.
- if (imageFormat == StreamConfigurationMap.HAL_PIXEL_FORMAT_BLOB) {
- int surfaceDataspace = SurfaceUtils.getSurfaceDataspace(surface);
- switch (surfaceDataspace) {
- case StreamConfigurationMap.HAL_DATASPACE_DEPTH:
- imageFormat = ImageFormat.DEPTH_POINT_CLOUD;
- break;
- case StreamConfigurationMap.HAL_DATASPACE_DYNAMIC_DEPTH:
- imageFormat = ImageFormat.DEPTH_JPEG;
- break;
- case StreamConfigurationMap.HAL_DATASPACE_HEIF:
- imageFormat = ImageFormat.HEIC;
- break;
- default:
- imageFormat = ImageFormat.JPEG;
- }
- mHardwareBufferFormat = PublicFormatUtils.getHalFormat(imageFormat);
- mDataSpace = PublicFormatUtils.getHalDataspace(imageFormat);
- }
// Estimate the native buffer allocation size and register it so it gets accounted for
// during GC. Note that this doesn't include the buffers required by the buffer queue
// itself and the buffers requested by the producer.
@@ -301,17 +280,44 @@
mWidth = width == -1 ? surfSize.getWidth() : width;
mHeight = height == -1 ? surfSize.getHeight() : height;
- mEstimatedNativeAllocBytes =
- ImageUtils.getEstimatedNativeAllocBytes(mWidth, mHeight,
- useLegacyImageFormat ? imageFormat : hardwareBufferFormat, /*buffer count*/ 1);
+ if (hardwareBufferFormat == HardwareBuffer.BLOB) {
+ // TODO(b/246344817): remove mWriterFormat and mDataSpace re-set here after fixing.
+ mWriterFormat = imageFormat = getImageFormatByBLOB(dataSpace);
+ mDataSpace = PublicFormatUtils.getHalDataspace(imageFormat);
+
+ mEstimatedNativeAllocBytes = ImageUtils.getEstimatedNativeAllocBytes(mWidth, mHeight,
+ imageFormat, /*buffer count*/ 1);
+ } else {
+ mEstimatedNativeAllocBytes =
+ ImageUtils.getEstimatedNativeAllocBytes(mWidth, mHeight,
+ useLegacyImageFormat ? imageFormat : hardwareBufferFormat, /*buffer count*/ 1);
+ }
VMRuntime.getRuntime().registerNativeAllocation(mEstimatedNativeAllocBytes);
}
+ // Several public formats use the same native HAL_PIXEL_FORMAT_BLOB. The native
+ // allocation estimation sequence depends on the public formats values. To avoid
+ // possible errors, convert where necessary.
+ private int getImageFormatByBLOB(int dataspace) {
+ switch (dataspace) {
+ case DataSpace.DATASPACE_DEPTH:
+ return ImageFormat.DEPTH_POINT_CLOUD;
+ case DataSpace.DATASPACE_DYNAMIC_DEPTH:
+ return ImageFormat.DEPTH_JPEG;
+ case DataSpace.DATASPACE_HEIF:
+ return ImageFormat.HEIC;
+ default:
+ return ImageFormat.JPEG;
+ }
+ }
+
private ImageWriter(Surface surface, int maxImages, boolean useSurfaceImageFormatInfo,
int imageFormat, int width, int height) {
mMaxImages = maxImages;
- mHardwareBufferFormat = PublicFormatUtils.getHalFormat(imageFormat);
- mDataSpace = PublicFormatUtils.getHalDataspace(imageFormat);
+ if (!useSurfaceImageFormatInfo) {
+ mHardwareBufferFormat = PublicFormatUtils.getHalFormat(imageFormat);
+ mDataSpace = PublicFormatUtils.getHalDataspace(imageFormat);
+ }
initializeImageWriter(surface, maxImages, useSurfaceImageFormatInfo, true,
imageFormat, mHardwareBufferFormat, mDataSpace, width, height, mUsage);
@@ -321,8 +327,10 @@
int imageFormat, int width, int height, long usage) {
mMaxImages = maxImages;
mUsage = usage;
- mHardwareBufferFormat = PublicFormatUtils.getHalFormat(imageFormat);
- mDataSpace = PublicFormatUtils.getHalDataspace(imageFormat);
+ if (!useSurfaceImageFormatInfo) {
+ mHardwareBufferFormat = PublicFormatUtils.getHalFormat(imageFormat);
+ mDataSpace = PublicFormatUtils.getHalDataspace(imageFormat);
+ }
initializeImageWriter(surface, maxImages, useSurfaceImageFormatInfo, true,
imageFormat, mHardwareBufferFormat, mDataSpace, width, height, usage);
@@ -337,8 +345,6 @@
// and retrieve corresponding hardwareBufferFormat and dataSpace here.
if (useSurfaceImageFormatInfo) {
imageFormat = ImageFormat.UNKNOWN;
- mHardwareBufferFormat = PublicFormatUtils.getHalFormat(imageFormat);
- mDataSpace = PublicFormatUtils.getHalDataspace(imageFormat);
} else {
imageFormat = PublicFormatUtils.getPublicFormat(hardwareBufferFormat, dataSpace);
mHardwareBufferFormat = hardwareBufferFormat;
diff --git a/media/java/android/media/MediaCodec.java b/media/java/android/media/MediaCodec.java
index 53d4efa..da2795f 100644
--- a/media/java/android/media/MediaCodec.java
+++ b/media/java/android/media/MediaCodec.java
@@ -3843,11 +3843,10 @@
private void invalidateByteBufferLocked(
@Nullable ByteBuffer[] buffers, int index, boolean input) {
if (buffers == null) {
- if (index < 0) {
- throw new IllegalStateException("index is negative (" + index + ")");
+ if (index >= 0) {
+ BitSet indices = input ? mValidInputIndices : mValidOutputIndices;
+ indices.clear(index);
}
- BitSet indices = input ? mValidInputIndices : mValidOutputIndices;
- indices.clear(index);
} else if (index >= 0 && index < buffers.length) {
ByteBuffer buffer = buffers[index];
if (buffer != null) {
@@ -3859,10 +3858,9 @@
private void validateInputByteBufferLocked(
@Nullable ByteBuffer[] buffers, int index) {
if (buffers == null) {
- if (index < 0) {
- throw new IllegalStateException("index is negative (" + index + ")");
+ if (index >= 0) {
+ mValidInputIndices.set(index);
}
- mValidInputIndices.set(index);
} else if (index >= 0 && index < buffers.length) {
ByteBuffer buffer = buffers[index];
if (buffer != null) {
@@ -3876,11 +3874,10 @@
@Nullable ByteBuffer[] buffers, int index, boolean input) {
synchronized(mBufferLock) {
if (buffers == null) {
- if (index < 0) {
- throw new IllegalStateException("index is negative (" + index + ")");
+ if (index >= 0) {
+ BitSet indices = input ? mValidInputIndices : mValidOutputIndices;
+ indices.set(index);
}
- BitSet indices = input ? mValidInputIndices : mValidOutputIndices;
- indices.set(index);
} else if (index >= 0 && index < buffers.length) {
ByteBuffer buffer = buffers[index];
if (buffer != null) {
@@ -3893,10 +3890,9 @@
private void validateOutputByteBufferLocked(
@Nullable ByteBuffer[] buffers, int index, @NonNull BufferInfo info) {
if (buffers == null) {
- if (index < 0) {
- throw new IllegalStateException("index is negative (" + index + ")");
+ if (index >= 0) {
+ mValidOutputIndices.set(index);
}
- mValidOutputIndices.set(index);
} else if (index >= 0 && index < buffers.length) {
ByteBuffer buffer = buffers[index];
if (buffer != null) {
diff --git a/media/java/android/media/MediaRouter.java b/media/java/android/media/MediaRouter.java
index d7fc205..2e7896e 100644
--- a/media/java/android/media/MediaRouter.java
+++ b/media/java/android/media/MediaRouter.java
@@ -221,7 +221,7 @@
} else if ((newRoutes.mainType & AudioRoutesInfo.MAIN_DOCK_SPEAKERS) != 0) {
name = R.string.default_audio_route_name_dock_speakers;
} else if ((newRoutes.mainType&AudioRoutesInfo.MAIN_HDMI) != 0) {
- name = R.string.default_audio_route_name_hdmi;
+ name = R.string.default_audio_route_name_external_device;
} else if ((newRoutes.mainType&AudioRoutesInfo.MAIN_USB) != 0) {
name = R.string.default_audio_route_name_usb;
} else {
diff --git a/packages/SettingsLib/Spa/gallery/src/com/android/settingslib/spa/gallery/SpaEnvironment.kt b/packages/SettingsLib/Spa/gallery/src/com/android/settingslib/spa/gallery/SpaEnvironment.kt
index 6f675a3..787d096 100644
--- a/packages/SettingsLib/Spa/gallery/src/com/android/settingslib/spa/gallery/SpaEnvironment.kt
+++ b/packages/SettingsLib/Spa/gallery/src/com/android/settingslib/spa/gallery/SpaEnvironment.kt
@@ -52,7 +52,7 @@
),
rootPages = listOf(
SettingsPage.create(HomePageProvider.name)
- ) + ArgumentPageProvider.buildRootPages()
+ )
)
}
diff --git a/packages/SettingsLib/Spa/gallery/src/com/android/settingslib/spa/gallery/home/HomePage.kt b/packages/SettingsLib/Spa/gallery/src/com/android/settingslib/spa/gallery/home/HomePage.kt
index 7c57e75..d8ef937 100644
--- a/packages/SettingsLib/Spa/gallery/src/com/android/settingslib/spa/gallery/home/HomePage.kt
+++ b/packages/SettingsLib/Spa/gallery/src/com/android/settingslib/spa/gallery/home/HomePage.kt
@@ -20,9 +20,12 @@
import androidx.compose.runtime.Composable
import androidx.compose.ui.res.stringResource
import androidx.compose.ui.tooling.preview.Preview
+import com.android.settingslib.spa.framework.common.SettingsEntry
+import com.android.settingslib.spa.framework.common.SettingsPage
import com.android.settingslib.spa.framework.common.SettingsPageProvider
import com.android.settingslib.spa.framework.theme.SettingsTheme
import com.android.settingslib.spa.gallery.R
+import com.android.settingslib.spa.gallery.page.ArgumentPageModel
import com.android.settingslib.spa.gallery.page.ArgumentPageProvider
import com.android.settingslib.spa.gallery.page.FooterPageProvider
import com.android.settingslib.spa.gallery.page.IllustrationPageProvider
@@ -35,23 +38,30 @@
object HomePageProvider : SettingsPageProvider {
override val name = "Home"
+ override fun buildEntry(arguments: Bundle?): List<SettingsEntry> {
+ val owner = SettingsPage.create(name)
+ return listOf(
+ PreferenceMainPageProvider.buildInjectEntry().setLink(fromPage = owner).build(),
+ ArgumentPageProvider.buildInjectEntry("foo")!!.setLink(fromPage = owner).build(),
+ SliderPageProvider.buildInjectEntry().setLink(fromPage = owner).build(),
+ SpinnerPageProvider.buildInjectEntry().setLink(fromPage = owner).build(),
+ SettingsPagerPageProvider.buildInjectEntry().setLink(fromPage = owner).build(),
+ FooterPageProvider.buildInjectEntry().setLink(fromPage = owner).build(),
+ IllustrationPageProvider.buildInjectEntry().setLink(fromPage = owner).build(),
+ )
+ }
+
@Composable
override fun Page(arguments: Bundle?) {
- HomePage()
- }
-}
-
-@Composable
-private fun HomePage() {
- HomeScaffold(title = stringResource(R.string.app_name)) {
- PreferenceMainPageProvider.EntryItem()
- ArgumentPageProvider.EntryItem(stringParam = "foo", intParam = 0)
-
- SliderPageProvider.EntryItem()
- SpinnerPageProvider.EntryItem()
- SettingsPagerPageProvider.EntryItem()
- FooterPageProvider.EntryItem()
- IllustrationPageProvider.EntryItem()
+ HomeScaffold(title = stringResource(R.string.app_name)) {
+ for (entry in buildEntry(arguments)) {
+ if (entry.name.startsWith(ArgumentPageModel.name)) {
+ entry.UiLayout(ArgumentPageModel.buildArgument(intParam = 0))
+ } else {
+ entry.UiLayout()
+ }
+ }
+ }
}
}
@@ -59,6 +69,6 @@
@Composable
private fun HomeScreenPreview() {
SettingsTheme {
- HomePage()
+ HomePageProvider.Page(null)
}
}
diff --git a/packages/SettingsLib/Spa/gallery/src/com/android/settingslib/spa/gallery/page/ArgumentPage.kt b/packages/SettingsLib/Spa/gallery/src/com/android/settingslib/spa/gallery/page/ArgumentPage.kt
index 5cce215..e32de7a 100644
--- a/packages/SettingsLib/Spa/gallery/src/com/android/settingslib/spa/gallery/page/ArgumentPage.kt
+++ b/packages/SettingsLib/Spa/gallery/src/com/android/settingslib/spa/gallery/page/ArgumentPage.kt
@@ -43,7 +43,7 @@
.setIsAllowSearch(true)
.setUiLayoutFn {
// Set ui rendering
- Preference(ArgumentPageModel.create(arguments).genStringParamPreferenceModel())
+ Preference(ArgumentPageModel.create(it).genStringParamPreferenceModel())
}.build()
)
@@ -53,54 +53,44 @@
.setIsAllowSearch(true)
.setUiLayoutFn {
// Set ui rendering
- Preference(ArgumentPageModel.create(arguments).genIntParamPreferenceModel())
+ Preference(ArgumentPageModel.create(it).genIntParamPreferenceModel())
}.build()
)
- val entryFoo = buildInjectEntry(ArgumentPageModel.buildNextArgument("foo", arguments))
- val entryBar = buildInjectEntry(ArgumentPageModel.buildNextArgument("bar", arguments))
- if (entryFoo != null) entryList.add(entryFoo.setLink(fromPage = owner).build())
- if (entryBar != null) entryList.add(entryBar.setLink(fromPage = owner).build())
+ entryList.add(buildInjectEntry("foo")!!.setLink(fromPage = owner).build())
+ entryList.add(buildInjectEntry("bar")!!.setLink(fromPage = owner).build())
return entryList
}
- private fun buildInjectEntry(arguments: Bundle?): SettingsEntryBuilder? {
+ fun buildInjectEntry(stringParam: String): SettingsEntryBuilder? {
+ val arguments = ArgumentPageModel.buildArgument(stringParam)
if (!ArgumentPageModel.isValidArgument(arguments)) return null
return SettingsEntryBuilder.createInject(
- entryName = ArgumentPageModel.getInjectEntryName(arguments),
+ entryName = "${name}_$stringParam",
owner = SettingsPage.create(name, parameter, arguments)
)
// Set attributes
.setIsAllowSearch(false)
.setUiLayoutFn {
// Set ui rendering
- Preference(ArgumentPageModel.create(arguments).genInjectPreferenceModel())
+ Preference(ArgumentPageModel.create(it).genInjectPreferenceModel())
}
}
- fun buildRootPages(): List<SettingsPage> {
- return listOf(
- SettingsPage.create(name, parameter, ArgumentPageModel.buildArgument("foo")),
- SettingsPage.create(name, parameter, ArgumentPageModel.buildArgument("bar")),
- )
- }
-
@Composable
override fun Page(arguments: Bundle?) {
RegularScaffold(title = ArgumentPageModel.create(arguments).genPageTitle()) {
for (entry in buildEntry(arguments)) {
- entry.uiLayout()
+ if (entry.name.startsWith(name)) {
+ entry.UiLayout(ArgumentPageModel.buildNextArgument(arguments))
+ } else {
+ entry.UiLayout()
+ }
}
}
}
-
- @Composable
- fun EntryItem(stringParam: String, intParam: Int) {
- buildInjectEntry(ArgumentPageModel.buildArgument(stringParam, intParam))
- ?.build()?.uiLayout?.let { it() }
- }
}
@Preview(showBackground = true)
diff --git a/packages/SettingsLib/Spa/gallery/src/com/android/settingslib/spa/gallery/page/ArgumentPageModel.kt b/packages/SettingsLib/Spa/gallery/src/com/android/settingslib/spa/gallery/page/ArgumentPageModel.kt
index e27bf6d..6e86fd7 100644
--- a/packages/SettingsLib/Spa/gallery/src/com/android/settingslib/spa/gallery/page/ArgumentPageModel.kt
+++ b/packages/SettingsLib/Spa/gallery/src/com/android/settingslib/spa/gallery/page/ArgumentPageModel.kt
@@ -44,19 +44,17 @@
navArgument(INT_PARAM_NAME) { type = NavType.IntType },
)
- fun buildArgument(stringParam: String, intParam: Int? = null): Bundle {
+ fun buildArgument(stringParam: String? = null, intParam: Int? = null): Bundle {
val args = Bundle()
- args.putString(STRING_PARAM_NAME, stringParam)
+ if (stringParam != null) args.putString(STRING_PARAM_NAME, stringParam)
if (intParam != null) args.putInt(INT_PARAM_NAME, intParam)
return args
}
- fun buildNextArgument(newStringParam: String, arguments: Bundle? = null): Bundle {
+ fun buildNextArgument(arguments: Bundle? = null): Bundle {
val intParam = parameter.getIntArg(INT_PARAM_NAME, arguments)
- return if (intParam == null)
- buildArgument(newStringParam)
- else
- buildArgument(newStringParam, intParam + 1)
+ val nextIntParam = if (intParam != null) intParam + 1 else null
+ return buildArgument(intParam = nextIntParam)
}
fun isValidArgument(arguments: Bundle?): Boolean {
@@ -64,10 +62,6 @@
return (stringParam != null && listOf("foo", "bar").contains(stringParam))
}
- fun getInjectEntryName(arguments: Bundle?): String {
- return "${name}_${parameter.getStringArg(STRING_PARAM_NAME, arguments)}"
- }
-
@Composable
fun create(arguments: Bundle?): ArgumentPageModel {
val pageModel: ArgumentPageModel = viewModel(key = arguments.toString())
diff --git a/packages/SettingsLib/Spa/gallery/src/com/android/settingslib/spa/gallery/page/FooterPage.kt b/packages/SettingsLib/Spa/gallery/src/com/android/settingslib/spa/gallery/page/FooterPage.kt
index 4a933ac..0fc2a5f 100644
--- a/packages/SettingsLib/Spa/gallery/src/com/android/settingslib/spa/gallery/page/FooterPage.kt
+++ b/packages/SettingsLib/Spa/gallery/src/com/android/settingslib/spa/gallery/page/FooterPage.kt
@@ -20,6 +20,9 @@
import androidx.compose.runtime.Composable
import androidx.compose.runtime.remember
import androidx.compose.ui.tooling.preview.Preview
+import com.android.settingslib.spa.framework.common.SettingsEntry
+import com.android.settingslib.spa.framework.common.SettingsEntryBuilder
+import com.android.settingslib.spa.framework.common.SettingsPage
import com.android.settingslib.spa.framework.common.SettingsPageProvider
import com.android.settingslib.spa.framework.compose.navigator
import com.android.settingslib.spa.framework.compose.stateOf
@@ -34,30 +37,44 @@
object FooterPageProvider : SettingsPageProvider {
override val name = "Footer"
+ override fun buildEntry(arguments: Bundle?): List<SettingsEntry> {
+ val owner = SettingsPage.create(name)
+ val entryList = mutableListOf<SettingsEntry>()
+ entryList.add(
+ SettingsEntryBuilder.create( "Some Preference", owner)
+ .setIsAllowSearch(true)
+ .setUiLayoutFn {
+ Preference(remember {
+ object : PreferenceModel {
+ override val title = "Some Preference"
+ override val summary = stateOf("Some summary")
+ }
+ })
+ }.build()
+ )
+
+ return entryList
+ }
+
+ fun buildInjectEntry(): SettingsEntryBuilder {
+ return SettingsEntryBuilder.createInject(owner = SettingsPage.create(name))
+ .setIsAllowSearch(true)
+ .setUiLayoutFn {
+ Preference(object : PreferenceModel {
+ override val title = TITLE
+ override val onClick = navigator(name)
+ })
+ }
+ }
+
@Composable
override fun Page(arguments: Bundle?) {
- FooterPage()
- }
-
- @Composable
- fun EntryItem() {
- Preference(object : PreferenceModel {
- override val title = TITLE
- override val onClick = navigator(name)
- })
- }
-}
-
-@Composable
-private fun FooterPage() {
- RegularScaffold(title = TITLE) {
- Preference(remember {
- object : PreferenceModel {
- override val title = "Some Preference"
- override val summary = stateOf("Some summary")
+ RegularScaffold(title = TITLE) {
+ for (entry in buildEntry(arguments)) {
+ entry.UiLayout()
}
- })
- Footer(footerText = "Footer text always at the end of page.")
+ Footer(footerText = "Footer text always at the end of page.")
+ }
}
}
@@ -65,6 +82,6 @@
@Composable
private fun FooterPagePreview() {
SettingsTheme {
- FooterPage()
+ FooterPageProvider.Page(null)
}
}
diff --git a/packages/SettingsLib/Spa/gallery/src/com/android/settingslib/spa/gallery/page/IllustrationPage.kt b/packages/SettingsLib/Spa/gallery/src/com/android/settingslib/spa/gallery/page/IllustrationPage.kt
index 4f8ea0b..a64d4a5 100644
--- a/packages/SettingsLib/Spa/gallery/src/com/android/settingslib/spa/gallery/page/IllustrationPage.kt
+++ b/packages/SettingsLib/Spa/gallery/src/com/android/settingslib/spa/gallery/page/IllustrationPage.kt
@@ -17,12 +17,11 @@
package com.android.settingslib.spa.gallery.page
import android.os.Bundle
-import androidx.compose.foundation.layout.Column
-import androidx.compose.foundation.rememberScrollState
-import androidx.compose.foundation.verticalScroll
import androidx.compose.runtime.Composable
-import androidx.compose.ui.Modifier
import androidx.compose.ui.tooling.preview.Preview
+import com.android.settingslib.spa.framework.common.SettingsEntry
+import com.android.settingslib.spa.framework.common.SettingsEntryBuilder
+import com.android.settingslib.spa.framework.common.SettingsPage
import com.android.settingslib.spa.framework.common.SettingsPageProvider
import com.android.settingslib.spa.framework.compose.navigator
import com.android.settingslib.spa.framework.theme.SettingsTheme
@@ -32,44 +31,64 @@
import com.android.settingslib.spa.widget.ResourceType
import com.android.settingslib.spa.widget.preference.Preference
import com.android.settingslib.spa.widget.preference.PreferenceModel
+import com.android.settingslib.spa.widget.scaffold.RegularScaffold
+
+private const val TITLE = "Sample Illustration"
object IllustrationPageProvider : SettingsPageProvider {
override val name = "Illustration"
+ override fun buildEntry(arguments: Bundle?): List<SettingsEntry> {
+ val owner = SettingsPage.create(name)
+ val entryList = mutableListOf<SettingsEntry>()
+ entryList.add(
+ SettingsEntryBuilder.create( "Lottie Illustration", owner)
+ .setUiLayoutFn {
+ Preference(object : PreferenceModel {
+ override val title = "Lottie Illustration"
+ })
+
+ Illustration(object : IllustrationModel {
+ override val resId = R.raw.accessibility_shortcut_type_triple_tap
+ override val resourceType = ResourceType.LOTTIE
+ })
+ }.build()
+ )
+ entryList.add(
+ SettingsEntryBuilder.create( "Image Illustration", owner)
+ .setUiLayoutFn {
+ Preference(object : PreferenceModel {
+ override val title = "Image Illustration"
+ })
+
+ Illustration(object : IllustrationModel {
+ override val resId = R.drawable.accessibility_captioning_banner
+ override val resourceType = ResourceType.IMAGE
+ })
+ }.build()
+ )
+
+ return entryList
+ }
+
+ fun buildInjectEntry(): SettingsEntryBuilder {
+ return SettingsEntryBuilder.createInject(owner = SettingsPage.create(name))
+ .setIsAllowSearch(true)
+ .setUiLayoutFn {
+ Preference(object : PreferenceModel {
+ override val title = TITLE
+ override val onClick = navigator(name)
+ })
+ }
+ }
+
@Composable
override fun Page(arguments: Bundle?) {
- IllustrationPage()
- }
-
- @Composable
- fun EntryItem() {
- Preference(object : PreferenceModel {
- override val title = "Sample Illustration"
- override val onClick = navigator(name)
- })
- }
-}
-
-@Composable
-private fun IllustrationPage() {
- Column(Modifier.verticalScroll(rememberScrollState())) {
- Preference(object : PreferenceModel {
- override val title = "Lottie Illustration"
- })
-
- Illustration(object : IllustrationModel {
- override val resId = R.raw.accessibility_shortcut_type_triple_tap
- override val resourceType = ResourceType.LOTTIE
- })
-
- Preference(object : PreferenceModel {
- override val title = "Image Illustration"
- })
-
- Illustration(object : IllustrationModel {
- override val resId = R.drawable.accessibility_captioning_banner
- override val resourceType = ResourceType.IMAGE
- })
+ RegularScaffold(title = TITLE) {
+ for (entry in buildEntry(arguments)) {
+ entry.UiLayout()
+ }
+ }
}
}
@@ -77,6 +96,6 @@
@Composable
private fun IllustrationPagePreview() {
SettingsTheme {
- IllustrationPage()
+ IllustrationPageProvider.Page(null)
}
}
diff --git a/packages/SettingsLib/Spa/gallery/src/com/android/settingslib/spa/gallery/page/SettingsPagerPage.kt b/packages/SettingsLib/Spa/gallery/src/com/android/settingslib/spa/gallery/page/SettingsPagerPage.kt
index 9d80818..e09ebda 100644
--- a/packages/SettingsLib/Spa/gallery/src/com/android/settingslib/spa/gallery/page/SettingsPagerPage.kt
+++ b/packages/SettingsLib/Spa/gallery/src/com/android/settingslib/spa/gallery/page/SettingsPagerPage.kt
@@ -19,6 +19,8 @@
import android.os.Bundle
import androidx.compose.runtime.Composable
import androidx.compose.ui.tooling.preview.Preview
+import com.android.settingslib.spa.framework.common.SettingsEntryBuilder
+import com.android.settingslib.spa.framework.common.SettingsPage
import com.android.settingslib.spa.framework.common.SettingsPageProvider
import com.android.settingslib.spa.framework.compose.navigator
import com.android.settingslib.spa.framework.theme.SettingsTheme
@@ -33,25 +35,23 @@
object SettingsPagerPageProvider : SettingsPageProvider {
override val name = "SettingsPager"
+ fun buildInjectEntry(): SettingsEntryBuilder {
+ return SettingsEntryBuilder.createInject(owner = SettingsPage.create(name))
+ .setIsAllowSearch(true)
+ .setUiLayoutFn {
+ Preference(object : PreferenceModel {
+ override val title = TITLE
+ override val onClick = navigator(name)
+ })
+ }
+ }
+
@Composable
override fun Page(arguments: Bundle?) {
- SettingsPagerPage()
- }
-
- @Composable
- fun EntryItem() {
- Preference(object : PreferenceModel {
- override val title = TITLE
- override val onClick = navigator(name)
- })
- }
-}
-
-@Composable
-private fun SettingsPagerPage() {
- SettingsScaffold(title = TITLE) {
- SettingsPager(listOf("Personal", "Work")) {
- PlaceholderTitle("Page $it")
+ SettingsScaffold(title = TITLE) {
+ SettingsPager(listOf("Personal", "Work")) {
+ PlaceholderTitle("Page $it")
+ }
}
}
}
@@ -60,6 +60,6 @@
@Composable
private fun SettingsPagerPagePreview() {
SettingsTheme {
- SettingsPagerPage()
+ SettingsPagerPageProvider.Page(null)
}
}
diff --git a/packages/SettingsLib/Spa/gallery/src/com/android/settingslib/spa/gallery/page/SliderPage.kt b/packages/SettingsLib/Spa/gallery/src/com/android/settingslib/spa/gallery/page/SliderPage.kt
index 130cbd9..0f95bf6 100644
--- a/packages/SettingsLib/Spa/gallery/src/com/android/settingslib/spa/gallery/page/SliderPage.kt
+++ b/packages/SettingsLib/Spa/gallery/src/com/android/settingslib/spa/gallery/page/SliderPage.kt
@@ -27,6 +27,9 @@
import androidx.compose.runtime.remember
import androidx.compose.runtime.setValue
import androidx.compose.ui.tooling.preview.Preview
+import com.android.settingslib.spa.framework.common.SettingsEntry
+import com.android.settingslib.spa.framework.common.SettingsEntryBuilder
+import com.android.settingslib.spa.framework.common.SettingsPage
import com.android.settingslib.spa.framework.common.SettingsPageProvider
import com.android.settingslib.spa.framework.compose.navigator
import com.android.settingslib.spa.framework.theme.SettingsTheme
@@ -41,59 +44,88 @@
object SliderPageProvider : SettingsPageProvider {
override val name = "Slider"
+ override fun buildEntry(arguments: Bundle?): List<SettingsEntry> {
+ val owner = SettingsPage.create(name)
+ val entryList = mutableListOf<SettingsEntry>()
+ entryList.add(
+ SettingsEntryBuilder.create("Simple Slider", owner)
+ .setIsAllowSearch(true)
+ .setUiLayoutFn {
+ SettingsSlider(object : SettingsSliderModel {
+ override val title = "Simple Slider"
+ override val initValue = 40
+ })
+ }.build()
+ )
+ entryList.add(
+ SettingsEntryBuilder.create("Slider with icon", owner)
+ .setIsAllowSearch(true)
+ .setUiLayoutFn {
+ SettingsSlider(object : SettingsSliderModel {
+ override val title = "Slider with icon"
+ override val initValue = 30
+ override val onValueChangeFinished = {
+ println("onValueChangeFinished")
+ }
+ override val icon = Icons.Outlined.AccessAlarm
+ })
+ }.build()
+ )
+ entryList.add(
+ SettingsEntryBuilder.create("Slider with changeable icon", owner)
+ .setIsAllowSearch(true)
+ .setUiLayoutFn {
+ val initValue = 0
+ var icon by remember { mutableStateOf(Icons.Outlined.MusicOff) }
+ var sliderPosition by remember { mutableStateOf(initValue) }
+ SettingsSlider(object : SettingsSliderModel {
+ override val title = "Slider with changeable icon"
+ override val initValue = initValue
+ override val onValueChange = { it: Int ->
+ sliderPosition = it
+ icon = if (it > 0) Icons.Outlined.MusicNote else Icons.Outlined.MusicOff
+ }
+ override val onValueChangeFinished = {
+ println("onValueChangeFinished: the value is $sliderPosition")
+ }
+ override val icon = icon
+ })
+ }.build()
+ )
+ entryList.add(
+ SettingsEntryBuilder.create("Slider with steps", owner)
+ .setIsAllowSearch(true)
+ .setUiLayoutFn {
+ SettingsSlider(object : SettingsSliderModel {
+ override val title = "Slider with steps"
+ override val initValue = 2
+ override val valueRange = 1..5
+ override val showSteps = true
+ })
+ }.build()
+ )
+
+ return entryList
+ }
+
+ fun buildInjectEntry(): SettingsEntryBuilder {
+ return SettingsEntryBuilder.createInject(owner = SettingsPage.create(name))
+ .setIsAllowSearch(true)
+ .setUiLayoutFn {
+ Preference(object : PreferenceModel {
+ override val title = TITLE
+ override val onClick = navigator(name)
+ })
+ }
+ }
+
@Composable
override fun Page(arguments: Bundle?) {
- SliderPage()
- }
-
- @Composable
- fun EntryItem() {
- Preference(object : PreferenceModel {
- override val title = TITLE
- override val onClick = navigator(name)
- })
- }
-}
-
-@Composable
-private fun SliderPage() {
- RegularScaffold(title = TITLE) {
- SettingsSlider(object : SettingsSliderModel {
- override val title = "Slider"
- override val initValue = 40
- })
-
- SettingsSlider(object : SettingsSliderModel {
- override val title = "Slider with icon"
- override val initValue = 30
- override val onValueChangeFinished = {
- println("onValueChangeFinished")
+ RegularScaffold(title = TITLE) {
+ for (entry in buildEntry(arguments)) {
+ entry.UiLayout()
}
- override val icon = Icons.Outlined.AccessAlarm
- })
-
- val initValue = 0
- var icon by remember { mutableStateOf(Icons.Outlined.MusicOff) }
- var sliderPosition by remember { mutableStateOf(initValue) }
- SettingsSlider(object : SettingsSliderModel {
- override val title = "Slider with changeable icon"
- override val initValue = initValue
- override val onValueChange = { it: Int ->
- sliderPosition = it
- icon = if (it > 0) Icons.Outlined.MusicNote else Icons.Outlined.MusicOff
- }
- override val onValueChangeFinished = {
- println("onValueChangeFinished: the value is $sliderPosition")
- }
- override val icon = icon
- })
-
- SettingsSlider(object : SettingsSliderModel {
- override val title = "Slider with steps"
- override val initValue = 2
- override val valueRange = 1..5
- override val showSteps = true
- })
+ }
}
}
@@ -101,6 +133,6 @@
@Composable
private fun SliderPagePreview() {
SettingsTheme {
- SliderPage()
+ SliderPageProvider.Page(null)
}
}
diff --git a/packages/SettingsLib/Spa/gallery/src/com/android/settingslib/spa/gallery/preference/MainSwitchPreferencePage.kt b/packages/SettingsLib/Spa/gallery/src/com/android/settingslib/spa/gallery/preference/MainSwitchPreferencePage.kt
index 53d7648..a8e4938 100644
--- a/packages/SettingsLib/Spa/gallery/src/com/android/settingslib/spa/gallery/preference/MainSwitchPreferencePage.kt
+++ b/packages/SettingsLib/Spa/gallery/src/com/android/settingslib/spa/gallery/preference/MainSwitchPreferencePage.kt
@@ -22,6 +22,9 @@
import androidx.compose.runtime.remember
import androidx.compose.runtime.saveable.rememberSaveable
import androidx.compose.ui.tooling.preview.Preview
+import com.android.settingslib.spa.framework.common.SettingsEntry
+import com.android.settingslib.spa.framework.common.SettingsEntryBuilder
+import com.android.settingslib.spa.framework.common.SettingsPage
import com.android.settingslib.spa.framework.common.SettingsPageProvider
import com.android.settingslib.spa.framework.compose.navigator
import com.android.settingslib.spa.framework.compose.stateOf
@@ -37,25 +40,45 @@
object MainSwitchPreferencePageProvider : SettingsPageProvider {
override val name = "MainSwitchPreference"
+ override fun buildEntry(arguments: Bundle?): List<SettingsEntry> {
+ val owner = SettingsPage.create(name)
+ val entryList = mutableListOf<SettingsEntry>()
+ entryList.add(
+ SettingsEntryBuilder.create( "MainSwitchPreference", owner)
+ .setIsAllowSearch(true)
+ .setUiLayoutFn {
+ SampleMainSwitchPreference()
+ }.build()
+ )
+ entryList.add(
+ SettingsEntryBuilder.create( "MainSwitchPreference not changeable", owner)
+ .setIsAllowSearch(true)
+ .setUiLayoutFn {
+ SampleNotChangeableMainSwitchPreference()
+ }.build()
+ )
+
+ return entryList
+ }
+
+ fun buildInjectEntry(): SettingsEntryBuilder {
+ return SettingsEntryBuilder.createInject(owner = SettingsPage.create(name))
+ .setIsAllowSearch(true)
+ .setUiLayoutFn {
+ Preference(object : PreferenceModel {
+ override val title = TITLE
+ override val onClick = navigator(name)
+ })
+ }
+ }
+
@Composable
override fun Page(arguments: Bundle?) {
- MainSwitchPreferencePage()
- }
-
- @Composable
- fun EntryItem() {
- Preference(object : PreferenceModel {
- override val title = TITLE
- override val onClick = navigator(name)
- })
- }
-}
-
-@Composable
-private fun MainSwitchPreferencePage() {
- RegularScaffold(title = TITLE) {
- SampleMainSwitchPreference()
- SampleNotChangeableMainSwitchPreference()
+ RegularScaffold(title = TITLE) {
+ for (entry in buildEntry(arguments)) {
+ entry.UiLayout()
+ }
+ }
}
}
@@ -88,6 +111,6 @@
@Composable
private fun MainSwitchPreferencePagePreview() {
SettingsTheme {
- MainSwitchPreferencePage()
+ MainSwitchPreferencePageProvider.Page(null)
}
}
diff --git a/packages/SettingsLib/Spa/gallery/src/com/android/settingslib/spa/gallery/preference/PreferenceMain.kt b/packages/SettingsLib/Spa/gallery/src/com/android/settingslib/spa/gallery/preference/PreferenceMain.kt
index 0a8dae3..0f99c57 100644
--- a/packages/SettingsLib/Spa/gallery/src/com/android/settingslib/spa/gallery/preference/PreferenceMain.kt
+++ b/packages/SettingsLib/Spa/gallery/src/com/android/settingslib/spa/gallery/preference/PreferenceMain.kt
@@ -18,6 +18,9 @@
import android.os.Bundle
import androidx.compose.runtime.Composable
+import com.android.settingslib.spa.framework.common.SettingsEntry
+import com.android.settingslib.spa.framework.common.SettingsEntryBuilder
+import com.android.settingslib.spa.framework.common.SettingsPage
import com.android.settingslib.spa.framework.common.SettingsPageProvider
import com.android.settingslib.spa.framework.compose.navigator
import com.android.settingslib.spa.widget.preference.Preference
@@ -29,26 +32,36 @@
object PreferenceMainPageProvider : SettingsPageProvider {
override val name = "PreferenceMain"
+ override fun buildEntry(arguments: Bundle?): List<SettingsEntry> {
+ return listOf(
+ PreferencePageProvider.buildInjectEntry()
+ .setLink(fromPage = SettingsPage.create(name)).build(),
+ SwitchPreferencePageProvider.buildInjectEntry()
+ .setLink(fromPage = SettingsPage.create(name)).build(),
+ MainSwitchPreferencePageProvider.buildInjectEntry()
+ .setLink(fromPage = SettingsPage.create(name)).build(),
+ TwoTargetSwitchPreferencePageProvider.buildInjectEntry()
+ .setLink(fromPage = SettingsPage.create(name)).build(),
+ )
+ }
+
+ fun buildInjectEntry(): SettingsEntryBuilder {
+ return SettingsEntryBuilder.createInject(owner = SettingsPage.create(name))
+ .setIsAllowSearch(true)
+ .setUiLayoutFn {
+ Preference(object : PreferenceModel {
+ override val title = TITLE
+ override val onClick = navigator(name)
+ })
+ }
+ }
+
@Composable
override fun Page(arguments: Bundle?) {
- PreferenceMain()
- }
-
- @Composable
- fun EntryItem() {
- Preference(object : PreferenceModel {
- override val title = TITLE
- override val onClick = navigator(name)
- })
- }
-}
-
-@Composable
-private fun PreferenceMain() {
- RegularScaffold(title = TITLE) {
- PreferencePageProvider.EntryItem()
- SwitchPreferencePageProvider.EntryItem()
- MainSwitchPreferencePageProvider.EntryItem()
- TwoTargetSwitchPreferencePageProvider.EntryItem()
+ RegularScaffold(title = TITLE) {
+ for (entry in buildEntry(arguments)) {
+ entry.UiLayout()
+ }
+ }
}
}
diff --git a/packages/SettingsLib/Spa/gallery/src/com/android/settingslib/spa/gallery/preference/PreferencePage.kt b/packages/SettingsLib/Spa/gallery/src/com/android/settingslib/spa/gallery/preference/PreferencePage.kt
index 36c619f..cbd028d 100644
--- a/packages/SettingsLib/Spa/gallery/src/com/android/settingslib/spa/gallery/preference/PreferencePage.kt
+++ b/packages/SettingsLib/Spa/gallery/src/com/android/settingslib/spa/gallery/preference/PreferencePage.kt
@@ -29,6 +29,9 @@
import androidx.compose.runtime.saveable.rememberSaveable
import androidx.compose.runtime.setValue
import androidx.compose.ui.tooling.preview.Preview
+import com.android.settingslib.spa.framework.common.SettingsEntry
+import com.android.settingslib.spa.framework.common.SettingsEntryBuilder
+import com.android.settingslib.spa.framework.common.SettingsPage
import com.android.settingslib.spa.framework.common.SettingsPageProvider
import com.android.settingslib.spa.framework.compose.navigator
import com.android.settingslib.spa.framework.compose.toState
@@ -44,68 +47,107 @@
object PreferencePageProvider : SettingsPageProvider {
override val name = "Preference"
+ override fun buildEntry(arguments: Bundle?): List<SettingsEntry> {
+ val owner = SettingsPage.create(name)
+ val entryList = mutableListOf<SettingsEntry>()
+ entryList.add(
+ SettingsEntryBuilder.create("Preference", owner)
+ .setIsAllowSearch(true)
+ .setUiLayoutFn {
+ Preference(object : PreferenceModel {
+ override val title = "Preference"
+ })
+ }.build()
+ )
+ entryList.add(
+ SettingsEntryBuilder.create("Preference with summary", owner)
+ .setIsAllowSearch(true)
+ .setUiLayoutFn {
+ Preference(object : PreferenceModel {
+ override val title = "Preference"
+ override val summary = "With summary".toState()
+ })
+ }.build()
+ )
+ entryList.add(
+ SettingsEntryBuilder.create("Preference with async summary", owner)
+ .setIsAllowSearch(true)
+ .setUiLayoutFn {
+ Preference(object : PreferenceModel {
+ override val title = "Preference"
+ override val summary = produceState(initialValue = " ") {
+ delay(1000L)
+ value = "Async summary"
+ }
+ })
+ }.build()
+ )
+ entryList.add(
+ SettingsEntryBuilder.create("Click me", owner)
+ .setIsAllowSearch(true)
+ .setUiLayoutFn {
+ var count by rememberSaveable { mutableStateOf(0) }
+ Preference(object : PreferenceModel {
+ override val title = "Click me"
+ override val summary = derivedStateOf { count.toString() }
+ override val onClick: (() -> Unit) = { count++ }
+ override val icon = @Composable {
+ SettingsIcon(imageVector = Icons.Outlined.TouchApp)
+ }
+ })
+ }.build()
+ )
+ entryList.add(
+ SettingsEntryBuilder.create("Ticker", owner)
+ .setIsAllowSearch(true)
+ .setUiLayoutFn {
+ var ticks by rememberSaveable { mutableStateOf(0) }
+ LaunchedEffect(ticks) {
+ delay(1000L)
+ ticks++
+ }
+ Preference(object : PreferenceModel {
+ override val title = "Ticker"
+ override val summary = derivedStateOf { ticks.toString() }
+ })
+ }.build()
+ )
+ entryList.add(
+ SettingsEntryBuilder.create("Disabled", owner)
+ .setIsAllowSearch(true)
+ .setUiLayoutFn {
+ Preference(object : PreferenceModel {
+ override val title = "Disabled"
+ override val summary = "Disabled".toState()
+ override val enabled = false.toState()
+ override val icon = @Composable {
+ SettingsIcon(imageVector = Icons.Outlined.DisabledByDefault)
+ }
+ })
+ }.build()
+ )
+
+ return entryList
+ }
+
+ fun buildInjectEntry(): SettingsEntryBuilder {
+ return SettingsEntryBuilder.createInject(owner = SettingsPage.create(name))
+ .setIsAllowSearch(true)
+ .setUiLayoutFn {
+ Preference(object : PreferenceModel {
+ override val title = TITLE
+ override val onClick = navigator(name)
+ })
+ }
+ }
+
@Composable
override fun Page(arguments: Bundle?) {
- PreferencePage()
- }
-
- @Composable
- fun EntryItem() {
- Preference(object : PreferenceModel {
- override val title = TITLE
- override val onClick = navigator(name)
- })
- }
-}
-
-@Composable
-private fun PreferencePage() {
- RegularScaffold(title = TITLE) {
- Preference(object : PreferenceModel {
- override val title = "Preference"
- })
-
- Preference(object : PreferenceModel {
- override val title = "Preference"
- override val summary = "With summary".toState()
- })
-
- Preference(object : PreferenceModel {
- override val title = "Preference"
- override val summary = produceState(initialValue = " ") {
- delay(1000L)
- value = "Async summary"
+ RegularScaffold(title = TITLE) {
+ for (entry in buildEntry(arguments)) {
+ entry.UiLayout()
}
- })
-
- var count by rememberSaveable { mutableStateOf(0) }
- Preference(object : PreferenceModel {
- override val title = "Click me"
- override val summary = derivedStateOf { count.toString() }
- override val onClick: (() -> Unit) = { count++ }
- override val icon = @Composable {
- SettingsIcon(imageVector = Icons.Outlined.TouchApp)
- }
- })
-
- var ticks by rememberSaveable { mutableStateOf(0) }
- LaunchedEffect(ticks) {
- delay(1000L)
- ticks++
}
- Preference(object : PreferenceModel {
- override val title = "Ticker"
- override val summary = derivedStateOf { ticks.toString() }
- })
-
- Preference(object : PreferenceModel {
- override val title = "Disabled"
- override val summary = "Disabled".toState()
- override val enabled = false.toState()
- override val icon = @Composable {
- SettingsIcon(imageVector = Icons.Outlined.DisabledByDefault)
- }
- })
}
}
@@ -113,6 +155,6 @@
@Composable
private fun PreferencePagePreview() {
SettingsTheme {
- PreferencePage()
+ PreferencePageProvider.Page(null)
}
}
diff --git a/packages/SettingsLib/Spa/gallery/src/com/android/settingslib/spa/gallery/preference/SwitchPreferencePage.kt b/packages/SettingsLib/Spa/gallery/src/com/android/settingslib/spa/gallery/preference/SwitchPreferencePage.kt
index 8be6a89..46b44ca 100644
--- a/packages/SettingsLib/Spa/gallery/src/com/android/settingslib/spa/gallery/preference/SwitchPreferencePage.kt
+++ b/packages/SettingsLib/Spa/gallery/src/com/android/settingslib/spa/gallery/preference/SwitchPreferencePage.kt
@@ -23,6 +23,9 @@
import androidx.compose.runtime.remember
import androidx.compose.runtime.saveable.rememberSaveable
import androidx.compose.ui.tooling.preview.Preview
+import com.android.settingslib.spa.framework.common.SettingsEntry
+import com.android.settingslib.spa.framework.common.SettingsEntryBuilder
+import com.android.settingslib.spa.framework.common.SettingsPage
import com.android.settingslib.spa.framework.common.SettingsPageProvider
import com.android.settingslib.spa.framework.compose.navigator
import com.android.settingslib.spa.framework.compose.stateOf
@@ -39,27 +42,59 @@
object SwitchPreferencePageProvider : SettingsPageProvider {
override val name = "SwitchPreference"
+ override fun buildEntry(arguments: Bundle?): List<SettingsEntry> {
+ val owner = SettingsPage.create(name)
+ val entryList = mutableListOf<SettingsEntry>()
+ entryList.add(
+ SettingsEntryBuilder.create( "SwitchPreference", owner)
+ .setIsAllowSearch(true)
+ .setUiLayoutFn {
+ SampleSwitchPreference()
+ }.build()
+ )
+ entryList.add(
+ SettingsEntryBuilder.create( "SwitchPreference with summary", owner)
+ .setIsAllowSearch(true)
+ .setUiLayoutFn {
+ SampleSwitchPreferenceWithSummary()
+ }.build()
+ )
+ entryList.add(
+ SettingsEntryBuilder.create( "SwitchPreference with async summary", owner)
+ .setIsAllowSearch(true)
+ .setUiLayoutFn {
+ SampleSwitchPreferenceWithAsyncSummary()
+ }.build()
+ )
+ entryList.add(
+ SettingsEntryBuilder.create( "SwitchPreference not changeable", owner)
+ .setIsAllowSearch(true)
+ .setUiLayoutFn {
+ SampleNotChangeableSwitchPreference()
+ }.build()
+ )
+
+ return entryList
+ }
+
+ fun buildInjectEntry(): SettingsEntryBuilder {
+ return SettingsEntryBuilder.createInject(owner = SettingsPage.create(name))
+ .setIsAllowSearch(true)
+ .setUiLayoutFn {
+ Preference(object : PreferenceModel {
+ override val title = TITLE
+ override val onClick = navigator(name)
+ })
+ }
+ }
+
@Composable
override fun Page(arguments: Bundle?) {
- SwitchPreferencePage()
- }
-
- @Composable
- fun EntryItem() {
- Preference(object : PreferenceModel {
- override val title = TITLE
- override val onClick = navigator(name)
- })
- }
-}
-
-@Composable
-private fun SwitchPreferencePage() {
- RegularScaffold(title = TITLE) {
- SampleSwitchPreference()
- SampleSwitchPreferenceWithSummary()
- SampleSwitchPreferenceWithAsyncSummary()
- SampleNotChangeableSwitchPreference()
+ RegularScaffold(title = TITLE) {
+ for (entry in buildEntry(arguments)) {
+ entry.UiLayout()
+ }
+ }
}
}
@@ -123,6 +158,6 @@
@Composable
private fun SwitchPreferencePagePreview() {
SettingsTheme {
- SwitchPreferencePage()
+ SwitchPreferencePageProvider.Page(null)
}
}
diff --git a/packages/SettingsLib/Spa/gallery/src/com/android/settingslib/spa/gallery/preference/TwoTargetSwitchPreferencePage.kt b/packages/SettingsLib/Spa/gallery/src/com/android/settingslib/spa/gallery/preference/TwoTargetSwitchPreferencePage.kt
index 894692b..b991f59 100644
--- a/packages/SettingsLib/Spa/gallery/src/com/android/settingslib/spa/gallery/preference/TwoTargetSwitchPreferencePage.kt
+++ b/packages/SettingsLib/Spa/gallery/src/com/android/settingslib/spa/gallery/preference/TwoTargetSwitchPreferencePage.kt
@@ -23,6 +23,9 @@
import androidx.compose.runtime.remember
import androidx.compose.runtime.saveable.rememberSaveable
import androidx.compose.ui.tooling.preview.Preview
+import com.android.settingslib.spa.framework.common.SettingsEntry
+import com.android.settingslib.spa.framework.common.SettingsEntryBuilder
+import com.android.settingslib.spa.framework.common.SettingsPage
import com.android.settingslib.spa.framework.common.SettingsPageProvider
import com.android.settingslib.spa.framework.compose.navigator
import com.android.settingslib.spa.framework.compose.stateOf
@@ -39,27 +42,59 @@
object TwoTargetSwitchPreferencePageProvider : SettingsPageProvider {
override val name = "TwoTargetSwitchPreference"
+ override fun buildEntry(arguments: Bundle?): List<SettingsEntry> {
+ val owner = SettingsPage.create(name)
+ val entryList = mutableListOf<SettingsEntry>()
+ entryList.add(
+ SettingsEntryBuilder.create( "TwoTargetSwitchPreference", owner)
+ .setIsAllowSearch(true)
+ .setUiLayoutFn {
+ SampleTwoTargetSwitchPreference()
+ }.build()
+ )
+ entryList.add(
+ SettingsEntryBuilder.create( "TwoTargetSwitchPreference with summary", owner)
+ .setIsAllowSearch(true)
+ .setUiLayoutFn {
+ SampleTwoTargetSwitchPreferenceWithSummary()
+ }.build()
+ )
+ entryList.add(
+ SettingsEntryBuilder.create( "TwoTargetSwitchPreference with async summary", owner)
+ .setIsAllowSearch(true)
+ .setUiLayoutFn {
+ SampleTwoTargetSwitchPreferenceWithAsyncSummary()
+ }.build()
+ )
+ entryList.add(
+ SettingsEntryBuilder.create( "TwoTargetSwitchPreference not changeable", owner)
+ .setIsAllowSearch(true)
+ .setUiLayoutFn {
+ SampleNotChangeableTwoTargetSwitchPreference()
+ }.build()
+ )
+
+ return entryList
+ }
+
+ fun buildInjectEntry(): SettingsEntryBuilder {
+ return SettingsEntryBuilder.createInject(owner = SettingsPage.create(name))
+ .setIsAllowSearch(true)
+ .setUiLayoutFn {
+ Preference(object : PreferenceModel {
+ override val title = TITLE
+ override val onClick = navigator(name)
+ })
+ }
+ }
+
@Composable
override fun Page(arguments: Bundle?) {
- TwoTargetSwitchPreferencePage()
- }
-
- @Composable
- fun EntryItem() {
- Preference(object : PreferenceModel {
- override val title = TITLE
- override val onClick = navigator(name)
- })
- }
-}
-
-@Composable
-private fun TwoTargetSwitchPreferencePage() {
- RegularScaffold(title = TITLE) {
- SampleTwoTargetSwitchPreference()
- SampleTwoTargetSwitchPreferenceWithSummary()
- SampleTwoTargetSwitchPreferenceWithAsyncSummary()
- SampleNotChangeableTwoTargetSwitchPreference()
+ RegularScaffold(title = TITLE) {
+ for (entry in buildEntry(arguments)) {
+ entry.UiLayout()
+ }
+ }
}
}
@@ -123,6 +158,6 @@
@Composable
private fun TwoTargetSwitchPreferencePagePreview() {
SettingsTheme {
- TwoTargetSwitchPreferencePage()
+ TwoTargetSwitchPreferencePageProvider.Page(null)
}
}
diff --git a/packages/SettingsLib/Spa/gallery/src/com/android/settingslib/spa/gallery/ui/SpinnerPage.kt b/packages/SettingsLib/Spa/gallery/src/com/android/settingslib/spa/gallery/ui/SpinnerPage.kt
index 7efa85b..03b72d3 100644
--- a/packages/SettingsLib/Spa/gallery/src/com/android/settingslib/spa/gallery/ui/SpinnerPage.kt
+++ b/packages/SettingsLib/Spa/gallery/src/com/android/settingslib/spa/gallery/ui/SpinnerPage.kt
@@ -23,6 +23,8 @@
import androidx.compose.runtime.remember
import androidx.compose.runtime.saveable.rememberSaveable
import androidx.compose.ui.tooling.preview.Preview
+import com.android.settingslib.spa.framework.common.SettingsEntryBuilder
+import com.android.settingslib.spa.framework.common.SettingsPage
import com.android.settingslib.spa.framework.common.SettingsPageProvider
import com.android.settingslib.spa.framework.compose.navigator
import com.android.settingslib.spa.framework.theme.SettingsTheme
@@ -36,33 +38,33 @@
object SpinnerPageProvider : SettingsPageProvider {
override val name = "Spinner"
+ fun buildInjectEntry(): SettingsEntryBuilder {
+ return SettingsEntryBuilder.createInject(owner = SettingsPage.create(name))
+ .setIsAllowSearch(true)
+ .setUiLayoutFn {
+ Preference(object : PreferenceModel {
+ override val title = TITLE
+ override val onClick = navigator(name)
+ })
+ }
+ }
+
@Composable
override fun Page(arguments: Bundle?) {
- SpinnerPage()
- }
-
- @Composable
- fun EntryItem() {
- Preference(object : PreferenceModel {
- override val title = TITLE
- override val onClick = navigator(name)
- })
- }
-}
-
-@Composable
-private fun SpinnerPage() {
- RegularScaffold(title = TITLE) {
- val selectedIndex = rememberSaveable { mutableStateOf(0) }
- Spinner(
- options = (1..3).map { "Option $it" },
- selectedIndex = selectedIndex.value,
- setIndex = { selectedIndex.value = it },
- )
- Preference(object : PreferenceModel {
- override val title = "Selected index"
- override val summary = remember { derivedStateOf { selectedIndex.value.toString() } }
- })
+ RegularScaffold(title = TITLE) {
+ val selectedIndex = rememberSaveable { mutableStateOf(0) }
+ Spinner(
+ options = (1..3).map { "Option $it" },
+ selectedIndex = selectedIndex.value,
+ setIndex = { selectedIndex.value = it },
+ )
+ Preference(object : PreferenceModel {
+ override val title = "Selected index"
+ override val summary = remember {
+ derivedStateOf { selectedIndex.value.toString() }
+ }
+ })
+ }
}
}
@@ -70,6 +72,6 @@
@Composable
private fun SpinnerPagePreview() {
SettingsTheme {
- SpinnerPage()
+ SpinnerPageProvider.Page(null)
}
}
diff --git a/packages/SettingsLib/Spa/spa/Android.bp b/packages/SettingsLib/Spa/spa/Android.bp
index a4928e6..6871f21 100644
--- a/packages/SettingsLib/Spa/spa/Android.bp
+++ b/packages/SettingsLib/Spa/spa/Android.bp
@@ -27,6 +27,7 @@
"androidx.compose.material3_material3",
"androidx.compose.material_material-icons-extended",
"androidx.compose.runtime_runtime",
+ "androidx.compose.runtime_runtime-livedata",
"androidx.compose.ui_ui-tooling-preview",
"androidx.navigation_navigation-compose",
"com.google.android.material_material",
diff --git a/packages/SettingsLib/Spa/spa/src/com/android/settingslib/spa/framework/DebugActivity.kt b/packages/SettingsLib/Spa/spa/src/com/android/settingslib/spa/framework/DebugActivity.kt
index 095e683..bd5aaa7 100644
--- a/packages/SettingsLib/Spa/spa/src/com/android/settingslib/spa/framework/DebugActivity.kt
+++ b/packages/SettingsLib/Spa/spa/src/com/android/settingslib/spa/framework/DebugActivity.kt
@@ -60,6 +60,17 @@
setTheme(R.style.Theme_SpaLib_DayNight)
super.onCreate(savedInstanceState)
+ val packageName = browseActivityClass.packageName
+ val className = browseActivityClass.toString().removePrefix("class $packageName")
+ for (pageWithEntry in entryRepository.getAllPageWithEntry()) {
+ if (pageWithEntry.page.hasRuntimeParam()) continue
+ val route = pageWithEntry.page.buildRoute()
+ Log.d(
+ "DEBUG ACTIVITY",
+ "adb shell am start -n $packageName/$className -e $KEY_DESTINATION $route"
+ )
+ }
+
setContent {
SettingsTheme {
MainContent()
@@ -136,6 +147,7 @@
Text(text = "Entry size: ${pageWithEntry.entries.size}")
Preference(model = object : PreferenceModel {
override val title = "open page"
+ override val enabled = (!pageWithEntry.page.hasRuntimeParam()).toState()
override val onClick = openPage(pageWithEntry.page)
})
EntryList(pageWithEntry.entries)
@@ -149,6 +161,7 @@
RegularScaffold(title = "Entry ${entry.displayName}") {
Preference(model = object : PreferenceModel {
override val title = "open entry"
+ override val enabled = (!entry.hasRuntimeParam()).toState()
override val onClick = openEntry(entry)
})
Text(text = entry.formatAll())
@@ -168,7 +181,8 @@
}
@Composable
- private fun openPage(page: SettingsPage): () -> Unit {
+ private fun openPage(page: SettingsPage): (() -> Unit)? {
+ if (page.hasRuntimeParam()) return null
val route = page.buildRoute()
val context = LocalContext.current
val intent = Intent(context, browseActivityClass).apply {
@@ -181,7 +195,8 @@
}
@Composable
- private fun openEntry(entry: SettingsEntry): () -> Unit {
+ private fun openEntry(entry: SettingsEntry): (() -> Unit)? {
+ if (entry.hasRuntimeParam()) return null
val route = entry.buildRoute()
val context = LocalContext.current
val intent = Intent(context, browseActivityClass).apply {
diff --git a/packages/SettingsLib/Spa/spa/src/com/android/settingslib/spa/framework/common/SettingsEntry.kt b/packages/SettingsLib/Spa/spa/src/com/android/settingslib/spa/framework/common/SettingsEntry.kt
index 86e75f3d..b0a1cbe 100644
--- a/packages/SettingsLib/Spa/spa/src/com/android/settingslib/spa/framework/common/SettingsEntry.kt
+++ b/packages/SettingsLib/Spa/spa/src/com/android/settingslib/spa/framework/common/SettingsEntry.kt
@@ -19,9 +19,9 @@
import android.os.Bundle
import androidx.compose.runtime.Composable
import androidx.navigation.NamedNavArgument
+import androidx.navigation.NavType
import com.android.settingslib.spa.framework.BrowseActivity
import com.android.settingslib.spa.framework.util.navLink
-import com.android.settingslib.spa.framework.util.normalize
const val INJECT_ENTRY_NAME = "INJECT"
const val ROOT_ENTRY_NAME = "ROOT"
@@ -85,6 +85,10 @@
"?${BrowseActivity.HIGHLIGHT_ENTRY_PARAM_NAME}=$highlightEntryName"
return name + parameter.navLink(arguments) + highlightParam
}
+
+ fun hasRuntimeParam(): Boolean {
+ return parameter.hasRuntimeParam(arguments)
+ }
}
/**
@@ -139,7 +143,7 @@
* injected entry. In the long term, we may deprecate the @Composable Page() API in SPP, and
* use each entries' UI rendering function in the page instead.
*/
- val uiLayout: (@Composable () -> Unit) = {},
+ val uiLayoutImpl: (@Composable (arguments: Bundle?) -> Unit) = {},
) {
fun formatAll(): String {
val content = listOf<String>(
@@ -150,10 +154,25 @@
return content.joinToString("\n")
}
+ private fun getDisplayPage(): SettingsPage {
+ // Display the entry on its from-page, or on its owner page if the from-page is unset.
+ return fromPage ?: owner
+ }
+
fun buildRoute(): String {
- // Open entry in its fromPage.
- val page = fromPage ?: owner
- return page.buildRoute(name)
+ return getDisplayPage().buildRoute(name)
+ }
+
+ fun hasRuntimeParam(): Boolean {
+ return getDisplayPage().hasRuntimeParam()
+ }
+
+ @Composable
+ fun UiLayout(runtimeArguments: Bundle? = null) {
+ val arguments = Bundle()
+ if (owner.arguments != null) arguments.putAll(owner.arguments)
+ if (runtimeArguments != null) arguments.putAll(runtimeArguments)
+ uiLayoutImpl(arguments)
}
}
@@ -196,7 +215,7 @@
private var isAllowSearch: Boolean? = null
private var searchDataFn: () -> SearchData? = { null }
- private var uiLayoutFn: (@Composable () -> Unit) = {}
+ private var uiLayoutFn: (@Composable (arguments: Bundle?) -> Unit) = {}
fun build(): SettingsEntry {
return SettingsEntry(
@@ -214,7 +233,7 @@
// functions
searchData = searchDataFn,
- uiLayout = uiLayoutFn,
+ uiLayoutImpl = uiLayoutFn,
)
}
@@ -237,7 +256,7 @@
return this
}
- fun setUiLayoutFn(fn: @Composable () -> Unit): SettingsEntryBuilder {
+ fun setUiLayoutFn(fn: @Composable (arguments: Bundle?) -> Unit): SettingsEntryBuilder {
this.uiLayoutFn = fn
return this
}
@@ -272,3 +291,33 @@
private fun String.toUniqueId(): Int {
return this.hashCode()
}
+
+private fun List<NamedNavArgument>.normalize(arguments: Bundle? = null): Bundle? {
+ if (this.isEmpty()) return null
+ val normArgs = Bundle()
+ for (navArg in this) {
+ when (navArg.argument.type) {
+ NavType.StringType -> {
+ val value = arguments?.getString(navArg.name)
+ if (value != null)
+ normArgs.putString(navArg.name, value)
+ else
+ normArgs.putString("unset_" + navArg.name, null)
+ }
+ NavType.IntType -> {
+ if (arguments != null && arguments.containsKey(navArg.name))
+ normArgs.putInt(navArg.name, arguments.getInt(navArg.name))
+ else
+ normArgs.putString("unset_" + navArg.name, null)
+ }
+ }
+ }
+ return normArgs
+}
+
+private fun List<NamedNavArgument>.hasRuntimeParam(arguments: Bundle? = null): Boolean {
+ for (navArg in this) {
+ if (arguments == null || !arguments.containsKey(navArg.name)) return true
+ }
+ return false
+}
diff --git a/packages/SettingsLib/Spa/spa/src/com/android/settingslib/spa/framework/util/Parameter.kt b/packages/SettingsLib/Spa/spa/src/com/android/settingslib/spa/framework/util/Parameter.kt
index 4e768eb..aaf8107 100644
--- a/packages/SettingsLib/Spa/spa/src/com/android/settingslib/spa/framework/util/Parameter.kt
+++ b/packages/SettingsLib/Spa/spa/src/com/android/settingslib/spa/framework/util/Parameter.kt
@@ -40,29 +40,6 @@
return argsArray.joinToString("") { arg -> "/$arg" }
}
-fun List<NamedNavArgument>.normalize(arguments: Bundle? = null): Bundle? {
- if (this.isEmpty()) return null
- val normArgs = Bundle()
- for (navArg in this) {
- when (navArg.argument.type) {
- NavType.StringType -> {
- val value = arguments?.getString(navArg.name)
- if (value != null)
- normArgs.putString(navArg.name, value)
- else
- normArgs.putString("unset_" + navArg.name, null)
- }
- NavType.IntType -> {
- if (arguments != null && arguments.containsKey(navArg.name))
- normArgs.putInt(navArg.name, arguments.getInt(navArg.name))
- else
- normArgs.putString("unset_" + navArg.name, null)
- }
- }
- }
- return normArgs
-}
-
fun List<NamedNavArgument>.getStringArg(name: String, arguments: Bundle? = null): String? {
if (this.containsStringArg(name) && arguments != null) {
return arguments.getString(name)
diff --git a/packages/SettingsLib/SpaPrivileged/src/com/android/settingslib/spaprivileged/model/app/AppOpsController.kt b/packages/SettingsLib/SpaPrivileged/src/com/android/settingslib/spaprivileged/model/app/AppOpsController.kt
index 8876f66..93ba4f7 100644
--- a/packages/SettingsLib/SpaPrivileged/src/com/android/settingslib/spaprivileged/model/app/AppOpsController.kt
+++ b/packages/SettingsLib/SpaPrivileged/src/com/android/settingslib/spaprivileged/model/app/AppOpsController.kt
@@ -24,6 +24,7 @@
import android.content.pm.ApplicationInfo
import androidx.lifecycle.LiveData
import androidx.lifecycle.MutableLiveData
+import androidx.lifecycle.Transformations
class AppOpsController(
context: Context,
@@ -32,21 +33,23 @@
) {
private val appOpsManager = checkNotNull(context.getSystemService(AppOpsManager::class.java))
+ val mode: LiveData<Int>
+ get() = _mode
val isAllowed: LiveData<Boolean>
- get() = _isAllowed
+ get() = Transformations.map(_mode) { it == MODE_ALLOWED }
fun setAllowed(allowed: Boolean) {
val mode = if (allowed) MODE_ALLOWED else MODE_ERRORED
appOpsManager.setMode(op, app.uid, app.packageName, mode)
- _isAllowed.postValue(allowed)
+ _mode.postValue(mode)
}
@Mode
fun getMode(): Int = appOpsManager.checkOpNoThrow(op, app.uid, app.packageName)
- private val _isAllowed = object : MutableLiveData<Boolean>() {
+ private val _mode = object : MutableLiveData<Int>() {
override fun onActive() {
- postValue(getMode() == MODE_ALLOWED)
+ postValue(getMode())
}
override fun onInactive() {
diff --git a/packages/SettingsLib/SpaPrivileged/src/com/android/settingslib/spaprivileged/model/app/PackageManagers.kt b/packages/SettingsLib/SpaPrivileged/src/com/android/settingslib/spaprivileged/model/app/PackageManagers.kt
index e521edd..ba8af54 100644
--- a/packages/SettingsLib/SpaPrivileged/src/com/android/settingslib/spaprivileged/model/app/PackageManagers.kt
+++ b/packages/SettingsLib/SpaPrivileged/src/com/android/settingslib/spaprivileged/model/app/PackageManagers.kt
@@ -16,31 +16,52 @@
package com.android.settingslib.spaprivileged.model.app
+import android.app.AppGlobals
import android.content.pm.ApplicationInfo
import android.content.pm.PackageInfo
+import android.content.pm.PackageInfo.REQUESTED_PERMISSION_GRANTED
import android.content.pm.PackageManager
import android.util.Log
+import com.android.settingslib.spa.framework.util.asyncFilter
private const val TAG = "PackageManagers"
object PackageManagers {
- fun getPackageInfoAsUser(packageName: String, userId: Int): PackageInfo =
- PackageManager.getPackageInfoAsUserCached(packageName, 0, userId)
+ private val iPackageManager by lazy { AppGlobals.getPackageManager() }
+
+ fun getPackageInfoAsUser(packageName: String, userId: Int): PackageInfo? =
+ getPackageInfoAsUser(packageName, 0, userId)
fun getApplicationInfoAsUser(packageName: String, userId: Int): ApplicationInfo =
PackageManager.getApplicationInfoAsUserCached(packageName, 0, userId)
- fun hasRequestPermission(app: ApplicationInfo, permission: String): Boolean {
- val packageInfo = try {
- PackageManager.getPackageInfoAsUserCached(
- app.packageName, PackageManager.GET_PERMISSIONS.toLong(), app.userId
- )
- } catch (e: PackageManager.NameNotFoundException) {
- Log.w(TAG, "getPackageInfoAsUserCached() failed", e)
- return false
- }
+ fun ApplicationInfo.hasRequestPermission(permission: String): Boolean {
+ val packageInfo = getPackageInfoAsUser(packageName, PackageManager.GET_PERMISSIONS, userId)
return packageInfo?.requestedPermissions?.let {
permission in it
} ?: false
}
+
+ fun ApplicationInfo.hasGrantPermission(permission: String): Boolean {
+ val packageInfo = getPackageInfoAsUser(packageName, PackageManager.GET_PERMISSIONS, userId)
+ ?: return false
+ val index = packageInfo.requestedPermissions.indexOf(permission)
+ return index >= 0 &&
+ packageInfo.requestedPermissionsFlags[index].hasFlag(REQUESTED_PERMISSION_GRANTED)
+ }
+
+ suspend fun getAppOpPermissionPackages(userId: Int, permission: String): Set<String> =
+ iPackageManager.getAppOpPermissionPackages(permission, userId).asIterable().asyncFilter {
+ iPackageManager.isPackageAvailable(it, userId)
+ }.toSet()
+
+ private fun getPackageInfoAsUser(packageName: String, flags: Int, userId: Int): PackageInfo? =
+ try {
+ PackageManager.getPackageInfoAsUserCached(packageName, flags.toLong(), userId)
+ } catch (e: PackageManager.NameNotFoundException) {
+ Log.w(TAG, "getPackageInfoAsUserCached() failed", e)
+ null
+ }
+
+ private fun Int.hasFlag(flag: Int) = (this and flag) > 0
}
diff --git a/packages/SettingsLib/SpaPrivileged/src/com/android/settingslib/spaprivileged/template/app/AppInfo.kt b/packages/SettingsLib/SpaPrivileged/src/com/android/settingslib/spaprivileged/template/app/AppInfo.kt
index 99deb70..f51d2db 100644
--- a/packages/SettingsLib/SpaPrivileged/src/com/android/settingslib/spaprivileged/template/app/AppInfo.kt
+++ b/packages/SettingsLib/SpaPrivileged/src/com/android/settingslib/spaprivileged/template/app/AppInfo.kt
@@ -49,7 +49,8 @@
),
horizontalAlignment = Alignment.CenterHorizontally,
) {
- val packageInfo = remember { PackageManagers.getPackageInfoAsUser(packageName, userId) }
+ val packageInfo =
+ remember { PackageManagers.getPackageInfoAsUser(packageName, userId) } ?: return
Box(modifier = Modifier.padding(SettingsDimension.itemPaddingAround)) {
AppIcon(app = packageInfo.applicationInfo, size = SettingsDimension.appIconInfoSize)
}
diff --git a/packages/SettingsLib/SpaPrivileged/src/com/android/settingslib/spaprivileged/template/app/AppOpPermissionAppList.kt b/packages/SettingsLib/SpaPrivileged/src/com/android/settingslib/spaprivileged/template/app/AppOpPermissionAppList.kt
new file mode 100644
index 0000000..c6f41d3
--- /dev/null
+++ b/packages/SettingsLib/SpaPrivileged/src/com/android/settingslib/spaprivileged/template/app/AppOpPermissionAppList.kt
@@ -0,0 +1,101 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.settingslib.spaprivileged.template.app
+
+import android.app.AppOpsManager.MODE_ALLOWED
+import android.app.AppOpsManager.MODE_DEFAULT
+import android.content.Context
+import android.content.pm.ApplicationInfo
+import androidx.compose.runtime.Composable
+import androidx.compose.runtime.State
+import androidx.compose.runtime.derivedStateOf
+import androidx.compose.runtime.livedata.observeAsState
+import androidx.compose.runtime.remember
+import com.android.settingslib.spaprivileged.model.app.AppOpsController
+import com.android.settingslib.spaprivileged.model.app.AppRecord
+import com.android.settingslib.spaprivileged.model.app.PackageManagers
+import com.android.settingslib.spaprivileged.model.app.PackageManagers.hasGrantPermission
+import com.android.settingslib.spaprivileged.model.app.PackageManagers.hasRequestPermission
+import kotlinx.coroutines.flow.Flow
+import kotlinx.coroutines.flow.combine
+import kotlinx.coroutines.flow.map
+
+data class AppOpPermissionRecord(
+ override val app: ApplicationInfo,
+ val hasRequestPermission: Boolean,
+ var appOpsController: AppOpsController,
+) : AppRecord
+
+abstract class AppOpPermissionListModel(private val context: Context) :
+ TogglePermissionAppListModel<AppOpPermissionRecord> {
+
+ abstract val appOp: Int
+ abstract val permission: String
+
+ private val notChangeablePackages =
+ setOf("android", "com.android.systemui", context.packageName)
+
+ override fun transform(userIdFlow: Flow<Int>, appListFlow: Flow<List<ApplicationInfo>>) =
+ userIdFlow.map { userId ->
+ PackageManagers.getAppOpPermissionPackages(userId, permission)
+ }.combine(appListFlow) { packageNames, appList ->
+ appList.map { app ->
+ AppOpPermissionRecord(
+ app = app,
+ hasRequestPermission = app.packageName in packageNames,
+ appOpsController = AppOpsController(context = context, app = app, op = appOp),
+ )
+ }
+ }
+
+ override fun transformItem(app: ApplicationInfo) = AppOpPermissionRecord(
+ app = app,
+ hasRequestPermission = app.hasRequestPermission(permission),
+ appOpsController = AppOpsController(context = context, app = app, op = appOp),
+ )
+
+ override fun filter(userIdFlow: Flow<Int>, recordListFlow: Flow<List<AppOpPermissionRecord>>) =
+ recordListFlow.map { recordList ->
+ recordList.filter { it.hasRequestPermission }
+ }
+
+ /**
+ * Defining the default behavior as permissible as long as the package requested this permission
+ * (This means pre-M gets approval during install time; M apps gets approval during runtime).
+ */
+ @Composable
+ override fun isAllowed(record: AppOpPermissionRecord): State<Boolean?> {
+ val mode = record.appOpsController.mode.observeAsState()
+ return remember {
+ derivedStateOf {
+ when (mode.value) {
+ null -> null
+ MODE_ALLOWED -> true
+ MODE_DEFAULT -> record.app.hasGrantPermission(permission)
+ else -> false
+ }
+ }
+ }
+ }
+
+ override fun isChangeable(record: AppOpPermissionRecord) =
+ record.hasRequestPermission && record.app.packageName !in notChangeablePackages
+
+ override fun setAllowed(record: AppOpPermissionRecord, newAllowed: Boolean) {
+ record.appOpsController.setAllowed(newAllowed)
+ }
+}
diff --git a/packages/SettingsLib/src/com/android/settingslib/bluetooth/CachedBluetoothDevice.java b/packages/SettingsLib/src/com/android/settingslib/bluetooth/CachedBluetoothDevice.java
index a5f3df9..7927c5d 100644
--- a/packages/SettingsLib/src/com/android/settingslib/bluetooth/CachedBluetoothDevice.java
+++ b/packages/SettingsLib/src/com/android/settingslib/bluetooth/CachedBluetoothDevice.java
@@ -81,8 +81,10 @@
private int mDeviceMode;
private long mHiSyncId;
private int mGroupId;
+
// Need this since there is no method for getting RSSI
short mRssi;
+
// mProfiles and mRemovedProfiles does not do swap() between main and sub device. It is
// because current sub device is only for HearingAid and its profile is the same.
private final Collection<LocalBluetoothProfile> mProfiles = new CopyOnWriteArrayList<>();
diff --git a/packages/SettingsLib/src/com/android/settingslib/bluetooth/HearingAidDeviceManager.java b/packages/SettingsLib/src/com/android/settingslib/bluetooth/HearingAidDeviceManager.java
index 818f5ca..cf4e1ee 100644
--- a/packages/SettingsLib/src/com/android/settingslib/bluetooth/HearingAidDeviceManager.java
+++ b/packages/SettingsLib/src/com/android/settingslib/bluetooth/HearingAidDeviceManager.java
@@ -46,16 +46,43 @@
if (isValidHiSyncId(hiSyncId)) {
// Once hiSyncId is valid, assign hiSyncId
newDevice.setHiSyncId(hiSyncId);
+ final int side = getDeviceSide(newDevice.getDevice());
+ final int mode = getDeviceMode(newDevice.getDevice());
+ newDevice.setDeviceSide(side);
+ newDevice.setDeviceMode(mode);
}
}
private long getHiSyncId(BluetoothDevice device) {
- LocalBluetoothProfileManager profileManager = mBtManager.getProfileManager();
- HearingAidProfile profileProxy = profileManager.getHearingAidProfile();
- if (profileProxy != null) {
- return profileProxy.getHiSyncId(device);
+ final LocalBluetoothProfileManager profileManager = mBtManager.getProfileManager();
+ final HearingAidProfile profileProxy = profileManager.getHearingAidProfile();
+ if (profileProxy == null) {
+ return BluetoothHearingAid.HI_SYNC_ID_INVALID;
}
- return BluetoothHearingAid.HI_SYNC_ID_INVALID;
+
+ return profileProxy.getHiSyncId(device);
+ }
+
+ private int getDeviceSide(BluetoothDevice device) {
+ final LocalBluetoothProfileManager profileManager = mBtManager.getProfileManager();
+ final HearingAidProfile profileProxy = profileManager.getHearingAidProfile();
+ if (profileProxy == null) {
+ Log.w(TAG, "HearingAidProfile is not supported and not ready to fetch device side");
+ return HearingAidProfile.DeviceSide.SIDE_INVALID;
+ }
+
+ return profileProxy.getDeviceSide(device);
+ }
+
+ private int getDeviceMode(BluetoothDevice device) {
+ final LocalBluetoothProfileManager profileManager = mBtManager.getProfileManager();
+ final HearingAidProfile profileProxy = profileManager.getHearingAidProfile();
+ if (profileProxy == null) {
+ Log.w(TAG, "HearingAidProfile is not supported and not ready to fetch device mode");
+ return HearingAidProfile.DeviceMode.MODE_INVALID;
+ }
+
+ return profileProxy.getDeviceMode(device);
}
boolean setSubDeviceIfNeeded(CachedBluetoothDevice newDevice) {
@@ -98,6 +125,10 @@
if (isValidHiSyncId(newHiSyncId)) {
cachedDevice.setHiSyncId(newHiSyncId);
newSyncIdSet.add(newHiSyncId);
+ final int side = getDeviceSide(cachedDevice.getDevice());
+ final int mode = getDeviceMode(cachedDevice.getDevice());
+ cachedDevice.setDeviceSide(side);
+ cachedDevice.setDeviceMode(mode);
}
}
}
diff --git a/packages/SettingsLib/src/com/android/settingslib/bluetooth/HearingAidStatsLogUtils.java b/packages/SettingsLib/src/com/android/settingslib/bluetooth/HearingAidStatsLogUtils.java
new file mode 100644
index 0000000..feb5e0b
--- /dev/null
+++ b/packages/SettingsLib/src/com/android/settingslib/bluetooth/HearingAidStatsLogUtils.java
@@ -0,0 +1,73 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.settingslib.bluetooth;
+
+import android.util.Log;
+
+import com.android.internal.annotations.VisibleForTesting;
+import com.android.internal.util.FrameworkStatsLog;
+
+import java.util.HashMap;
+
+/** Utils class to report hearing aid metrics to statsd */
+public final class HearingAidStatsLogUtils {
+
+ private static final String TAG = "HearingAidStatsLogUtils";
+ private static final HashMap<String, Integer> sDeviceAddressToBondEntryMap = new HashMap<>();
+
+ /**
+ * Sets the mapping from hearing aid device to the bond entry where this device starts it's
+ * bonding(connecting) process.
+ *
+ * @param bondEntry The entry page id where the bonding process starts
+ * @param device The bonding(connecting) hearing aid device
+ */
+ public static void setBondEntryForDevice(int bondEntry, CachedBluetoothDevice device) {
+ sDeviceAddressToBondEntryMap.put(device.getAddress(), bondEntry);
+ }
+
+ /**
+ * Logs hearing aid device information to westworld, including device mode, device side, and
+ * entry page id where the binding(connecting) process starts.
+ *
+ * Only logs the info once after hearing aid is bonded(connected). Clears the map entry of this
+ * device when logging is completed.
+ *
+ * @param device The bonded(connected) hearing aid device
+ */
+ public static void logHearingAidInfo(CachedBluetoothDevice device) {
+ final String deviceAddress = device.getAddress();
+ if (sDeviceAddressToBondEntryMap.containsKey(deviceAddress)) {
+ final int bondEntry = sDeviceAddressToBondEntryMap.getOrDefault(deviceAddress, -1);
+ final int deviceMode = device.getDeviceMode();
+ final int deviceSide = device.getDeviceSide();
+ FrameworkStatsLog.write(FrameworkStatsLog.HEARING_AID_INFO_REPORTED, deviceMode,
+ deviceSide, bondEntry);
+
+ sDeviceAddressToBondEntryMap.remove(deviceAddress);
+ } else {
+ Log.w(TAG, "The device address was not found. Hearing aid device info is not logged.");
+ }
+ }
+
+ @VisibleForTesting
+ static HashMap<String, Integer> getDeviceAddressToBondEntryMap() {
+ return sDeviceAddressToBondEntryMap;
+ }
+
+ private HearingAidStatsLogUtils() {}
+}
diff --git a/packages/SettingsLib/src/com/android/settingslib/bluetooth/LocalBluetoothProfileManager.java b/packages/SettingsLib/src/com/android/settingslib/bluetooth/LocalBluetoothProfileManager.java
index 4714ff9..8a9f9dd 100644
--- a/packages/SettingsLib/src/com/android/settingslib/bluetooth/LocalBluetoothProfileManager.java
+++ b/packages/SettingsLib/src/com/android/settingslib/bluetooth/LocalBluetoothProfileManager.java
@@ -352,6 +352,8 @@
cachedDevice.setHiSyncId(newHiSyncId);
}
}
+
+ HearingAidStatsLogUtils.logHearingAidInfo(cachedDevice);
}
if (getCsipSetCoordinatorProfile() != null
diff --git a/packages/SettingsLib/src/com/android/settingslib/users/AvatarPhotoController.java b/packages/SettingsLib/src/com/android/settingslib/users/AvatarPhotoController.java
index adfa39e..4ce88ee 100644
--- a/packages/SettingsLib/src/com/android/settingslib/users/AvatarPhotoController.java
+++ b/packages/SettingsLib/src/com/android/settingslib/users/AvatarPhotoController.java
@@ -21,6 +21,8 @@
import android.content.ContentResolver;
import android.content.Context;
import android.content.Intent;
+import android.content.pm.PackageManager;
+import android.content.pm.ResolveInfo;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
@@ -46,6 +48,7 @@
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
+import java.util.List;
import java.util.concurrent.ExecutionException;
class AvatarPhotoController {
@@ -57,9 +60,9 @@
void startActivityForResult(Intent intent, int resultCode);
- int getPhotoSize();
+ boolean startSystemActivityForResult(Intent intent, int resultCode);
- boolean canCropPhoto();
+ int getPhotoSize();
}
interface ContextInjector {
@@ -82,6 +85,7 @@
private static final long DELAY_BEFORE_CROP_MILLIS = 150;
private static final String IMAGES_DIR = "multi_user";
+ private static final String PRE_CROP_PICTURE_FILE_NAME = "PreCropEditUserPhoto.jpg";
private static final String CROP_PICTURE_FILE_NAME = "CropEditUserPhoto.jpg";
private static final String TAKE_PICTURE_FILE_NAME = "TakeEditUserPhoto.jpg";
@@ -91,6 +95,7 @@
private final ContextInjector mContextInjector;
private final File mImagesDir;
+ private final Uri mPreCropPictureUri;
private final Uri mCropPictureUri;
private final Uri mTakePictureUri;
@@ -100,6 +105,8 @@
mImagesDir = new File(mContextInjector.getCacheDir(), IMAGES_DIR);
mImagesDir.mkdir();
+ mPreCropPictureUri = mContextInjector
+ .createTempImageUri(mImagesDir, PRE_CROP_PICTURE_FILE_NAME, !waiting);
mCropPictureUri =
mContextInjector.createTempImageUri(mImagesDir, CROP_PICTURE_FILE_NAME, !waiting);
mTakePictureUri =
@@ -131,7 +138,7 @@
return true;
case REQUEST_CODE_TAKE_PHOTO:
if (mTakePictureUri.equals(pictureUri)) {
- cropPhoto();
+ cropPhoto(pictureUri);
} else {
copyAndCropPhoto(pictureUri, false);
}
@@ -160,7 +167,7 @@
ThreadUtils.postOnBackgroundThread(() -> {
final ContentResolver cr = mContextInjector.getContentResolver();
try (InputStream in = cr.openInputStream(pictureUri);
- OutputStream out = cr.openOutputStream(mTakePictureUri)) {
+ OutputStream out = cr.openOutputStream(mPreCropPictureUri)) {
Streams.copy(in, out);
} catch (IOException e) {
Log.w(TAG, "Failed to copy photo", e);
@@ -168,7 +175,7 @@
}
Runnable cropRunnable = () -> {
if (!mAvatarUi.isFinishing()) {
- cropPhoto();
+ cropPhoto(mPreCropPictureUri);
}
};
if (delayBeforeCrop) {
@@ -183,22 +190,21 @@
}
}
- private void cropPhoto() {
- if (mAvatarUi.canCropPhoto()) {
- // TODO: Use a public intent, when there is one.
- Intent intent = new Intent("com.android.camera.action.CROP");
- intent.setDataAndType(mTakePictureUri, "image/*");
- appendOutputExtra(intent, mCropPictureUri);
- appendCropExtras(intent);
- try {
- StrictMode.disableDeathOnFileUriExposure();
- mAvatarUi.startActivityForResult(intent, REQUEST_CODE_CROP_PHOTO);
- } finally {
- StrictMode.enableDeathOnFileUriExposure();
+ private void cropPhoto(final Uri pictureUri) {
+ // TODO: Use a public intent, when there is one.
+ Intent intent = new Intent("com.android.camera.action.CROP");
+ intent.setDataAndType(pictureUri, "image/*");
+ appendOutputExtra(intent, mCropPictureUri);
+ appendCropExtras(intent);
+ try {
+ StrictMode.disableDeathOnFileUriExposure();
+ if (mAvatarUi.startSystemActivityForResult(intent, REQUEST_CODE_CROP_PHOTO)) {
+ return;
}
- } else {
- onPhotoNotCropped(mTakePictureUri);
+ } finally {
+ StrictMode.enableDeathOnFileUriExposure();
}
+ onPhotoNotCropped(pictureUri);
}
private void appendOutputExtra(Intent intent, Uri pictureUri) {
@@ -320,14 +326,22 @@
}
@Override
- public int getPhotoSize() {
- return mActivity.getResources()
- .getDimensionPixelSize(com.android.internal.R.dimen.user_icon_size);
+ public boolean startSystemActivityForResult(Intent intent, int code) {
+ List<ResolveInfo> resolveInfos = mActivity.getPackageManager()
+ .queryIntentActivities(intent, PackageManager.MATCH_SYSTEM_ONLY);
+ if (resolveInfos.isEmpty()) {
+ Log.w(TAG, "No system package activity could be found for code " + code);
+ return false;
+ }
+ intent.setPackage(resolveInfos.get(0).activityInfo.packageName);
+ mActivity.startActivityForResult(intent, code);
+ return true;
}
@Override
- public boolean canCropPhoto() {
- return PhotoCapabilityUtils.canCropPhoto(mActivity);
+ public int getPhotoSize() {
+ return mActivity.getResources()
+ .getDimensionPixelSize(com.android.internal.R.dimen.user_icon_size);
}
}
diff --git a/packages/SettingsLib/tests/integ/src/com/android/settingslib/users/AvatarPhotoControllerTest.java b/packages/SettingsLib/tests/integ/src/com/android/settingslib/users/AvatarPhotoControllerTest.java
index 3dc2fab..d988111 100644
--- a/packages/SettingsLib/tests/integ/src/com/android/settingslib/users/AvatarPhotoControllerTest.java
+++ b/packages/SettingsLib/tests/integ/src/com/android/settingslib/users/AvatarPhotoControllerTest.java
@@ -34,6 +34,7 @@
import android.content.Context;
import android.content.Intent;
import android.graphics.Bitmap;
+import android.graphics.BitmapFactory;
import android.net.Uri;
import android.provider.MediaStore;
@@ -51,6 +52,7 @@
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
+import java.io.InputStream;
import java.io.OutputStream;
@RunWith(AndroidJUnit4.class)
@@ -73,6 +75,7 @@
public void setUp() {
MockitoAnnotations.initMocks(this);
when(mMockAvatarUi.getPhotoSize()).thenReturn(PHOTO_SIZE);
+ when(mMockAvatarUi.startSystemActivityForResult(any(), anyInt())).thenReturn(true);
mImagesDir = new File(
InstrumentationRegistry.getTargetContext().getCacheDir(), "multi_user");
@@ -110,9 +113,7 @@
}
@Test
- public void takePhotoIsFollowedByCropWhenSupported() throws IOException {
- when(mMockAvatarUi.canCropPhoto()).thenReturn(true);
-
+ public void takePhotoIsFollowedByCrop() throws IOException {
new File(mImagesDir, "file.txt").createNewFile();
Intent intent = new Intent();
@@ -121,14 +122,12 @@
mController.onActivityResult(
REQUEST_CODE_TAKE_PHOTO, Activity.RESULT_OK, intent);
- verifyStartActivityForResult(
+ verifyStartSystemActivityForResult(
"com.android.camera.action.CROP", REQUEST_CODE_CROP_PHOTO);
}
@Test
public void takePhotoIsNotFollowedByCropWhenResultCodeNotOk() throws IOException {
- when(mMockAvatarUi.canCropPhoto()).thenReturn(true);
-
new File(mImagesDir, "file.txt").createNewFile();
Intent intent = new Intent();
@@ -138,12 +137,11 @@
REQUEST_CODE_TAKE_PHOTO, Activity.RESULT_CANCELED, intent);
verify(mMockAvatarUi, never()).startActivityForResult(any(), anyInt());
+ verify(mMockAvatarUi, never()).startSystemActivityForResult(any(), anyInt());
}
@Test
public void takePhotoIsFollowedByCropWhenTakePhotoUriReturned() throws IOException {
- when(mMockAvatarUi.canCropPhoto()).thenReturn(true);
-
new File(mImagesDir, "TakeEditUserPhoto.jpg").createNewFile();
Intent intent = new Intent();
@@ -151,14 +149,12 @@
mController.onActivityResult(
REQUEST_CODE_TAKE_PHOTO, Activity.RESULT_OK, intent);
- verifyStartActivityForResult(
+ verifyStartSystemActivityForResult(
"com.android.camera.action.CROP", REQUEST_CODE_CROP_PHOTO);
}
@Test
public void choosePhotoIsFollowedByCrop() throws IOException {
- when(mMockAvatarUi.canCropPhoto()).thenReturn(true);
-
new File(mImagesDir, "file.txt").createNewFile();
Intent intent = new Intent();
@@ -167,14 +163,12 @@
mController.onActivityResult(
REQUEST_CODE_CHOOSE_PHOTO, Activity.RESULT_OK, intent);
- verifyStartActivityForResult(
+ verifyStartSystemActivityForResult(
"com.android.camera.action.CROP", REQUEST_CODE_CROP_PHOTO);
}
@Test
public void choosePhotoIsNotFollowedByCropWhenResultCodeNotOk() throws IOException {
- when(mMockAvatarUi.canCropPhoto()).thenReturn(true);
-
new File(mImagesDir, "file.txt").createNewFile();
Intent intent = new Intent();
@@ -184,12 +178,11 @@
REQUEST_CODE_CHOOSE_PHOTO, Activity.RESULT_CANCELED, intent);
verify(mMockAvatarUi, never()).startActivityForResult(any(), anyInt());
+ verify(mMockAvatarUi, never()).startSystemActivityForResult(any(), anyInt());
}
@Test
public void choosePhotoIsFollowedByCropWhenTakePhotoUriReturned() throws IOException {
- when(mMockAvatarUi.canCropPhoto()).thenReturn(true);
-
new File(mImagesDir, "TakeEditUserPhoto.jpg").createNewFile();
Intent intent = new Intent();
@@ -197,28 +190,11 @@
mController.onActivityResult(
REQUEST_CODE_CHOOSE_PHOTO, Activity.RESULT_OK, intent);
- verifyStartActivityForResult(
+ verifyStartSystemActivityForResult(
"com.android.camera.action.CROP", REQUEST_CODE_CROP_PHOTO);
}
@Test
- public void choosePhotoIsNotFollowedByCropIntentWhenCropNotSupported() throws IOException {
- when(mMockAvatarUi.canCropPhoto()).thenReturn(false);
-
- File file = new File(mImagesDir, "file.txt");
- saveBitmapToFile(file);
-
- Intent intent = new Intent();
- intent.setData(Uri.parse(
- "content://com.android.settingslib.test/my_cache/multi_user/file.txt"));
- mController.onActivityResult(
- REQUEST_CODE_CHOOSE_PHOTO, Activity.RESULT_OK, intent);
-
- verify(mMockAvatarUi, never()).startActivityForResult(any(), anyInt());
- verify(mMockAvatarUi, timeout(TIMEOUT_MILLIS)).returnUriResult(mCropPhotoUri);
- }
-
- @Test
public void cropPhotoResultIsReturnedIfResultOkAndContent() {
Intent intent = new Intent();
intent.setData(mCropPhotoUri);
@@ -242,11 +218,58 @@
verify(mMockAvatarUi, timeout(TIMEOUT_MILLIS).times(0)).returnUriResult(mCropPhotoUri);
}
- private void verifyStartActivityForResult(String action, int resultCode) {
+ @Test
+ public void cropDoesNotUseTakePhotoUri() throws IOException {
+ new File(mImagesDir, "file.txt").createNewFile();
+
+ Intent intent = new Intent();
+ intent.setData(Uri.parse(
+ "content://com.android.settingslib.test/my_cache/multi_user/file.txt"));
+ mController.onActivityResult(
+ REQUEST_CODE_TAKE_PHOTO, Activity.RESULT_OK, intent);
+
+ Intent startIntent = verifyStartSystemActivityForResult(
+ "com.android.camera.action.CROP", REQUEST_CODE_CROP_PHOTO);
+ assertThat(startIntent.getData()).isNotEqualTo(mTakePhotoUri);
+ }
+
+ @Test
+ public void internalCropUsedIfNoSystemCropperFound() throws IOException {
+ when(mMockAvatarUi.startSystemActivityForResult(any(), anyInt())).thenReturn(false);
+
+ File file = new File(mImagesDir, "file.txt");
+ saveBitmapToFile(file);
+
+ Intent intent = new Intent();
+ intent.setData(Uri.parse(
+ "content://com.android.settingslib.test/my_cache/multi_user/file.txt"));
+ mController.onActivityResult(
+ REQUEST_CODE_TAKE_PHOTO, Activity.RESULT_OK, intent);
+
+ verify(mMockAvatarUi, timeout(TIMEOUT_MILLIS)).returnUriResult(mCropPhotoUri);
+
+ InputStream imageStream = mContext.getContentResolver().openInputStream(mCropPhotoUri);
+ Bitmap bitmap = BitmapFactory.decodeStream(imageStream);
+ assertThat(bitmap.getWidth()).isEqualTo(PHOTO_SIZE);
+ assertThat(bitmap.getHeight()).isEqualTo(PHOTO_SIZE);
+ }
+
+ private Intent verifyStartActivityForResult(String action, int resultCode) {
ArgumentCaptor<Intent> captor = ArgumentCaptor.forClass(Intent.class);
verify(mMockAvatarUi, timeout(TIMEOUT_MILLIS))
.startActivityForResult(captor.capture(), eq(resultCode));
- assertThat(captor.getValue().getAction()).isEqualTo(action);
+ Intent intent = captor.getValue();
+ assertThat(intent.getAction()).isEqualTo(action);
+ return intent;
+ }
+
+ private Intent verifyStartSystemActivityForResult(String action, int resultCode) {
+ ArgumentCaptor<Intent> captor = ArgumentCaptor.forClass(Intent.class);
+ verify(mMockAvatarUi, timeout(TIMEOUT_MILLIS))
+ .startSystemActivityForResult(captor.capture(), eq(resultCode));
+ Intent intent = captor.getValue();
+ assertThat(intent.getAction()).isEqualTo(action);
+ return intent;
}
private void saveBitmapToFile(File file) throws IOException {
diff --git a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/bluetooth/HearingAidDeviceManagerTest.java b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/bluetooth/HearingAidDeviceManagerTest.java
index d80a591..611b0a4 100644
--- a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/bluetooth/HearingAidDeviceManagerTest.java
+++ b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/bluetooth/HearingAidDeviceManagerTest.java
@@ -102,16 +102,25 @@
}
/**
- * Test initHearingAidDeviceIfNeeded, a valid HiSyncId will be assigned
+ * Test initHearingAidDeviceIfNeeded, set HearingAid's information, including HiSyncId,
+ * deviceSide, deviceMode.
*/
@Test
- public void initHearingAidDeviceIfNeeded_validHiSyncId_verifyHiSyncId() {
+ public void initHearingAidDeviceIfNeeded_validHiSyncId_setHearingAidInfos() {
when(mHearingAidProfile.getHiSyncId(mDevice1)).thenReturn(HISYNCID1);
+ when(mHearingAidProfile.getDeviceMode(mDevice1)).thenReturn(
+ HearingAidProfile.DeviceMode.MODE_BINAURAL);
+ when(mHearingAidProfile.getDeviceSide(mDevice1)).thenReturn(
+ HearingAidProfile.DeviceSide.SIDE_RIGHT);
assertThat(mCachedDevice1.getHiSyncId()).isNotEqualTo(HISYNCID1);
mHearingAidDeviceManager.initHearingAidDeviceIfNeeded(mCachedDevice1);
assertThat(mCachedDevice1.getHiSyncId()).isEqualTo(HISYNCID1);
+ assertThat(mCachedDevice1.getDeviceMode()).isEqualTo(
+ HearingAidProfile.DeviceMode.MODE_BINAURAL);
+ assertThat(mCachedDevice1.getDeviceSide()).isEqualTo(
+ HearingAidProfile.DeviceSide.SIDE_RIGHT);
}
/**
@@ -251,6 +260,29 @@
}
/**
+ * Test updateHearingAidsDevices, set HearingAid's information, including HiSyncId, deviceSide,
+ * deviceMode.
+ */
+ @Test
+ public void updateHearingAidsDevices_validHiSyncId_setHearingAidInfos() {
+ when(mHearingAidProfile.getHiSyncId(mDevice1)).thenReturn(HISYNCID1);
+ when(mHearingAidProfile.getDeviceMode(mDevice1)).thenReturn(
+ HearingAidProfile.DeviceMode.MODE_BINAURAL);
+ when(mHearingAidProfile.getDeviceSide(mDevice1)).thenReturn(
+ HearingAidProfile.DeviceSide.SIDE_RIGHT);
+ mCachedDeviceManager.mCachedDevices.add(mCachedDevice1);
+
+ mHearingAidDeviceManager.updateHearingAidsDevices();
+
+ assertThat(mCachedDevice1.getHiSyncId()).isEqualTo(HISYNCID1);
+ assertThat(mCachedDevice1.getDeviceMode()).isEqualTo(
+ HearingAidProfile.DeviceMode.MODE_BINAURAL);
+ assertThat(mCachedDevice1.getDeviceSide()).isEqualTo(
+ HearingAidProfile.DeviceSide.SIDE_RIGHT);
+ verify(mHearingAidDeviceManager).onHiSyncIdChanged(HISYNCID1);
+ }
+
+ /**
* Test onProfileConnectionStateChangedIfProcessed.
* When first hearing aid device is connected, to process it same as other generic devices.
* No need to process it.
diff --git a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/bluetooth/HearingAidStatsLogUtilsTest.java b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/bluetooth/HearingAidStatsLogUtilsTest.java
new file mode 100644
index 0000000..0cf5b89
--- /dev/null
+++ b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/bluetooth/HearingAidStatsLogUtilsTest.java
@@ -0,0 +1,74 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.settingslib.bluetooth;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import static org.mockito.Mockito.when;
+
+import com.android.internal.util.FrameworkStatsLog;
+
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.Mock;
+import org.mockito.junit.MockitoJUnit;
+import org.mockito.junit.MockitoRule;
+import org.robolectric.RobolectricTestRunner;
+
+import java.util.HashMap;
+
+@RunWith(RobolectricTestRunner.class)
+public class HearingAidStatsLogUtilsTest {
+
+ private static final String TEST_DEVICE_ADDRESS = "00:A1:A1:A1:A1:A1";
+
+ @Rule
+ public final MockitoRule mockito = MockitoJUnit.rule();
+
+ @Mock
+ private CachedBluetoothDevice mCachedBluetoothDevice;
+
+ @Test
+ public void setBondEntryForDevice_addsEntryToDeviceAddressToBondEntryMap() {
+ when(mCachedBluetoothDevice.getAddress()).thenReturn(TEST_DEVICE_ADDRESS);
+
+ HearingAidStatsLogUtils.setBondEntryForDevice(
+ FrameworkStatsLog.HEARING_AID_INFO_REPORTED__BOND_ENTRY__BLUETOOTH,
+ mCachedBluetoothDevice);
+
+ final HashMap<String, Integer> map =
+ HearingAidStatsLogUtils.getDeviceAddressToBondEntryMap();
+ assertThat(map.containsKey(TEST_DEVICE_ADDRESS)).isTrue();
+ assertThat(map.get(TEST_DEVICE_ADDRESS)).isEqualTo(
+ FrameworkStatsLog.HEARING_AID_INFO_REPORTED__BOND_ENTRY__BLUETOOTH);
+ }
+
+ @Test
+ public void logHearingAidInfo_removesEntryFromDeviceAddressToBondEntryMap() {
+ when(mCachedBluetoothDevice.getAddress()).thenReturn(TEST_DEVICE_ADDRESS);
+
+ HearingAidStatsLogUtils.setBondEntryForDevice(
+ FrameworkStatsLog.HEARING_AID_INFO_REPORTED__BOND_ENTRY__BLUETOOTH,
+ mCachedBluetoothDevice);
+ HearingAidStatsLogUtils.logHearingAidInfo(mCachedBluetoothDevice);
+
+ final HashMap<String, Integer> map =
+ HearingAidStatsLogUtils.getDeviceAddressToBondEntryMap();
+ assertThat(map.containsKey(TEST_DEVICE_ADDRESS)).isFalse();
+ }
+}
diff --git a/packages/SystemUI/AndroidManifest.xml b/packages/SystemUI/AndroidManifest.xml
index 7649de6..2737ecf 100644
--- a/packages/SystemUI/AndroidManifest.xml
+++ b/packages/SystemUI/AndroidManifest.xml
@@ -414,7 +414,7 @@
</intent-filter>
</receiver>
- <service android:name=".ImageWallpaper"
+ <service android:name=".wallpapers.ImageWallpaper"
android:singleUser="true"
android:permission="android.permission.BIND_WALLPAPER"
android:exported="true" />
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 57193e7..436145e 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
@@ -16,6 +16,8 @@
import android.view.View;
+import androidx.annotation.FloatRange;
+
import com.android.systemui.plugins.FragmentBase;
import com.android.systemui.plugins.annotations.DependsOn;
import com.android.systemui.plugins.annotations.ProvidesInterface;
@@ -107,10 +109,24 @@
void setInSplitShade(boolean shouldTranslate);
/**
- * Set the amount of pixels we have currently dragged down if we're transitioning to the full
- * shade. 0.0f means we're not transitioning yet.
+ * Sets the progress of the transition to full shade on the lockscreen.
+ *
+ * @param isTransitioningToFullShade
+ * whether the transition to full shade is in progress. This might be {@code true}, even
+ * though {@code qsTransitionFraction} is still 0.
+ * The reason for that is that on some device configurations, the QS transition has a
+ * start delay compared to the overall transition.
+ *
+ * @param qsTransitionFraction
+ * the fraction of the QS transition progress, from 0 to 1.
+ *
+ * @param qsSquishinessFraction
+ * the fraction of the QS "squish" transition progress, from 0 to 1.
*/
- default void setTransitionToFullShadeAmount(float pxAmount, float progress) {}
+ default void setTransitionToFullShadeProgress(
+ boolean isTransitioningToFullShade,
+ @FloatRange(from = 0.0, to = 1.0) float qsTransitionFraction,
+ @FloatRange(from = 0.0, to = 1.0) float qsSquishinessFraction) {}
/**
* A rounded corner clipping that makes QS feel as if it were behind everything.
@@ -140,6 +156,12 @@
default void setOverScrollAmount(int overScrollAmount) {}
/**
+ * Sets whether the notification panel is using the full width of the screen. Typically true on
+ * small screens and false on large screens.
+ */
+ void setIsNotificationPanelFullWidth(boolean isFullWidth);
+
+ /**
* Callback for when QSPanel container is scrolled
*/
@ProvidesInterface(version = ScrollListener.VERSION)
diff --git a/packages/SystemUI/res/values-sw600dp-land/dimens.xml b/packages/SystemUI/res/values-sw600dp-land/dimens.xml
index d638c9d..f4d4824 100644
--- a/packages/SystemUI/res/values-sw600dp-land/dimens.xml
+++ b/packages/SystemUI/res/values-sw600dp-land/dimens.xml
@@ -49,54 +49,29 @@
<dimen name="status_view_margin_horizontal">8dp</dimen>
- <!-- Distance that the full shade transition takes in order to complete by tapping on a button
- like "expand". -->
+ <!-- Lockscreen shade transition values -->
<dimen name="lockscreen_shade_transition_by_tap_distance">200dp</dimen>
-
- <!-- Distance that the full shade transition takes in order to complete. -->
<dimen name="lockscreen_shade_full_transition_distance">200dp</dimen>
-
- <!-- Distance that the full shade transition takes in order for media to fully transition to
- the shade -->
- <dimen name="lockscreen_shade_media_transition_distance">200dp</dimen>
-
- <!-- Distance that the full shade transition takes in order for scrim to fully transition to
- the shade (in alpha) -->
+ <!-- Media transition distance = qs delay + qs distance -->
+ <dimen name="lockscreen_shade_media_transition_distance">129.28dp</dimen>
<dimen name="lockscreen_shade_scrim_transition_distance">80dp</dimen>
-
<!-- The notifications scrim transition should start when the other scrims' transition is at
95%. -->
<dimen name="lockscreen_shade_notifications_scrim_transition_delay">76dp</dimen>
-
<!-- The notifications scrim transition duration is 66.6% of the duration of the other scrims'
- transition. -->
+ transition. -->
<dimen name="lockscreen_shade_notifications_scrim_transition_distance">53.28dp</dimen>
-
- <!-- Distance that the full shade transition takes in order for the keyguard content on
- NotificationPanelViewController to fully fade (e.g. Clock & Smartspace) -->
<dimen name="lockscreen_shade_npvc_keyguard_content_alpha_transition_distance">80dp</dimen>
-
- <!-- Distance that the full shade transition takes in order for the notification shell to fully
- expand. -->
<dimen name="lockscreen_shade_notif_shelf_transition_distance">@dimen/lockscreen_shade_full_transition_distance</dimen>
-
- <!-- Distance that the full shade transition takes in order for the Quick Settings to fully
- fade and expand. -->
- <dimen name="lockscreen_shade_qs_transition_distance">@dimen/lockscreen_shade_full_transition_distance</dimen>
-
- <!-- Distance that the full shade transition takes in order for depth of the wallpaper to fully
- change.
- On split-shade, there should be no depth effect, so setting the value to 0. -->
+ <dimen name="lockscreen_shade_qs_transition_distance">@dimen/lockscreen_shade_notifications_scrim_transition_distance</dimen>
+ <dimen name="lockscreen_shade_qs_transition_delay">@dimen/lockscreen_shade_notifications_scrim_transition_delay</dimen>
+ <dimen name="lockscreen_shade_qs_squish_transition_distance">@dimen/lockscreen_shade_qs_transition_distance</dimen>
+ <!-- On split-shade, the QS squish transition should start from half height. -->
+ <item name="lockscreen_shade_qs_squish_start_fraction" type="dimen" format="float" >0.5</item>
+ <!-- On split-shade, there should be no depth effect, so setting the value to 0. -->
<dimen name="lockscreen_shade_depth_controller_transition_distance">0dp</dimen>
-
- <!-- Distance that the full shade transition takes in order for the UDFPS Keyguard View to fully
- fade. -->
<dimen name="lockscreen_shade_udfps_keyguard_transition_distance">@dimen/lockscreen_shade_full_transition_distance</dimen>
-
- <!-- Used for StatusBar to know that a transition is in progress. At the moment it only checks
- whether the progress is > 0, therefore this value is not very important. -->
<dimen name="lockscreen_shade_status_bar_transition_distance">@dimen/lockscreen_shade_full_transition_distance</dimen>
-
<dimen name="lockscreen_shade_keyguard_transition_distance">@dimen/lockscreen_shade_media_transition_distance</dimen>
<!-- Roughly the same distance as media on LS to media on QS. We will translate by this value
diff --git a/packages/SystemUI/res/values-sw600dp/dimens.xml b/packages/SystemUI/res/values-sw600dp/dimens.xml
index 008299b..a587e5a 100644
--- a/packages/SystemUI/res/values-sw600dp/dimens.xml
+++ b/packages/SystemUI/res/values-sw600dp/dimens.xml
@@ -73,4 +73,24 @@
<dimen name="large_dialog_width">472dp</dimen>
<dimen name="large_screen_shade_header_height">42dp</dimen>
+
+ <!-- Lockscreen shade transition values -->
+ <dimen name="lockscreen_shade_transition_by_tap_distance">200dp</dimen>
+ <dimen name="lockscreen_shade_full_transition_distance">80dp</dimen>
+ <dimen name="lockscreen_shade_media_transition_distance">120dp</dimen>
+ <dimen name="lockscreen_shade_scrim_transition_distance">@dimen/lockscreen_shade_full_transition_distance</dimen>
+ <dimen name="lockscreen_shade_notifications_scrim_transition_delay">@dimen/lockscreen_shade_scrim_transition_distance</dimen>
+ <dimen name="lockscreen_shade_notifications_scrim_transition_distance">@dimen/lockscreen_shade_scrim_transition_distance</dimen>
+ <dimen name="lockscreen_shade_npvc_keyguard_content_alpha_transition_distance">@dimen/lockscreen_shade_full_transition_distance</dimen>
+ <dimen name="lockscreen_shade_notif_shelf_transition_distance">@dimen/lockscreen_shade_full_transition_distance</dimen>
+ <dimen name="lockscreen_shade_qs_transition_distance">@dimen/lockscreen_shade_full_transition_distance</dimen>
+ <dimen name="lockscreen_shade_qs_transition_delay">@dimen/lockscreen_shade_scrim_transition_distance</dimen>
+ <dimen name="lockscreen_shade_qs_squish_transition_distance">@dimen/lockscreen_shade_qs_transition_distance</dimen>
+ <!-- On large screen portrait, the QS squish transition should start from half height. -->
+ <item name="lockscreen_shade_qs_squish_start_fraction" type="dimen" format="float" >0.5</item>
+ <dimen name="lockscreen_shade_depth_controller_transition_distance">@dimen/lockscreen_shade_full_transition_distance</dimen>
+ <dimen name="lockscreen_shade_udfps_keyguard_transition_distance">@dimen/lockscreen_shade_full_transition_distance</dimen>
+ <dimen name="lockscreen_shade_status_bar_transition_distance">@dimen/lockscreen_shade_full_transition_distance</dimen>
+ <dimen name="lockscreen_shade_keyguard_transition_distance">@dimen/lockscreen_shade_media_transition_distance</dimen>
+
</resources>
diff --git a/packages/SystemUI/res/values/dimens.xml b/packages/SystemUI/res/values/dimens.xml
index 19a6aba..9cb4cc4 100644
--- a/packages/SystemUI/res/values/dimens.xml
+++ b/packages/SystemUI/res/values/dimens.xml
@@ -1223,6 +1223,17 @@
fade and expand. -->
<dimen name="lockscreen_shade_qs_transition_distance">@dimen/lockscreen_shade_full_transition_distance</dimen>
+ <!-- Distance delay for the QS transition to start during the lockscreen shade expansion. -->
+ <dimen name="lockscreen_shade_qs_transition_delay">0dp</dimen>
+
+ <!-- Distance that it takes to complete the QS "squish" transition during the lockscreen shade
+ expansion. -->
+ <dimen name="lockscreen_shade_qs_squish_transition_distance">@dimen/lockscreen_shade_qs_transition_distance</dimen>
+
+ <!-- The fraction at which the QS "squish" transition should start during the lockscreen shade
+ expansion. 0 is fully collapsed, 1 is fully expanded. -->
+ <item type="dimen" format="float" name="lockscreen_shade_qs_squish_start_fraction">0</item>
+
<!-- Distance that the full shade transition takes in order for depth of the wallpaper to fully
change. -->
<dimen name="lockscreen_shade_depth_controller_transition_distance">@dimen/lockscreen_shade_full_transition_distance</dimen>
diff --git a/packages/SystemUI/src/com/android/systemui/dagger/DefaultServiceBinder.java b/packages/SystemUI/src/com/android/systemui/dagger/DefaultServiceBinder.java
index e1cbdcd..92eeace 100644
--- a/packages/SystemUI/src/com/android/systemui/dagger/DefaultServiceBinder.java
+++ b/packages/SystemUI/src/com/android/systemui/dagger/DefaultServiceBinder.java
@@ -18,7 +18,6 @@
import android.app.Service;
-import com.android.systemui.ImageWallpaper;
import com.android.systemui.SystemUIService;
import com.android.systemui.doze.DozeService;
import com.android.systemui.dreams.DreamOverlayService;
@@ -26,6 +25,7 @@
import com.android.systemui.keyguard.KeyguardService;
import com.android.systemui.screenrecord.RecordingService;
import com.android.systemui.statusbar.phone.NotificationListenerWithPlugins;
+import com.android.systemui.wallpapers.ImageWallpaper;
import dagger.Binds;
import dagger.Module;
diff --git a/packages/SystemUI/src/com/android/systemui/media/MediaCarouselController.kt b/packages/SystemUI/src/com/android/systemui/media/MediaCarouselController.kt
index 4c6aa7b..cc77ed1 100644
--- a/packages/SystemUI/src/com/android/systemui/media/MediaCarouselController.kt
+++ b/packages/SystemUI/src/com/android/systemui/media/MediaCarouselController.kt
@@ -458,6 +458,7 @@
val existingPlayer = MediaPlayerData.getMediaPlayer(key)
val curVisibleMediaKey = MediaPlayerData.playerKeys()
.elementAtOrNull(mediaCarouselScrollHandler.visibleMediaIndex)
+ val isCurVisibleMediaPlaying = MediaPlayerData.getMediaData(curVisibleMediaKey)?.isPlaying
if (existingPlayer == null) {
val newPlayer = mediaControlPanelFactory.get()
newPlayer.attachPlayer(MediaViewHolder.create(
@@ -472,13 +473,23 @@
key, data, newPlayer, systemClock, isSsReactivated, debugLogger
)
updatePlayerToState(newPlayer, noAnimation = true)
- reorderAllPlayers(curVisibleMediaKey)
+ if (data.active) {
+ reorderAllPlayers(curVisibleMediaKey)
+ } else {
+ needsReordering = true
+ }
} else {
existingPlayer.bindPlayer(data, key)
MediaPlayerData.addMediaPlayer(
key, data, existingPlayer, systemClock, isSsReactivated, debugLogger
)
- if (isReorderingAllowed || shouldScrollToActivePlayer) {
+ // Check the playing status of both current visible and new media players
+ // To make sure we scroll to the active playing media card.
+ if (isReorderingAllowed ||
+ shouldScrollToActivePlayer &&
+ data.isPlaying == true &&
+ isCurVisibleMediaPlaying == false
+ ) {
reorderAllPlayers(curVisibleMediaKey)
} else {
needsReordering = true
@@ -1035,6 +1046,15 @@
}
}
+ fun getMediaData(mediaSortKey: MediaSortKey?): MediaData? {
+ mediaData.forEach { (key, value) ->
+ if (value == mediaSortKey) {
+ return mediaData[key]?.data
+ }
+ }
+ return null
+ }
+
fun getMediaPlayer(key: String): MediaControlPanel? {
return mediaData.get(key)?.let { mediaPlayers.get(it) }
}
diff --git a/packages/SystemUI/src/com/android/systemui/qs/QSFragment.java b/packages/SystemUI/src/com/android/systemui/qs/QSFragment.java
index b31e472..072c32f 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/QSFragment.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/QSFragment.java
@@ -34,6 +34,7 @@
import android.view.ViewGroup;
import android.view.ViewTreeObserver;
+import androidx.annotation.FloatRange;
import androidx.annotation.Nullable;
import androidx.annotation.VisibleForTesting;
import androidx.lifecycle.Lifecycle;
@@ -166,6 +167,13 @@
// visible;
private boolean mQsVisible;
+ /**
+ * Whether the notification panel uses the full width of the screen.
+ *
+ * Usually {@code true} on small screens, and {@code false} on large screens.
+ */
+ private boolean mIsNotificationPanelFullWidth;
+
@Inject
public QSFragment(RemoteInputQuickSettingsDisabler remoteInputQsDisabler,
QSTileHost qsTileHost,
@@ -571,15 +579,17 @@
}
@Override
- public void setTransitionToFullShadeAmount(float pxAmount, float progress) {
- boolean isTransitioningToFullShade = pxAmount > 0;
+ public void setTransitionToFullShadeProgress(
+ boolean isTransitioningToFullShade,
+ @FloatRange(from = 0.0, to = 1.0) float qsTransitionFraction,
+ @FloatRange(from = 0.0, to = 1.0) float qsSquishinessFraction) {
if (isTransitioningToFullShade != mTransitioningToFullShade) {
mTransitioningToFullShade = isTransitioningToFullShade;
updateShowCollapsedOnKeyguard();
}
- mFullShadeProgress = progress;
+ mFullShadeProgress = qsTransitionFraction;
setQsExpansion(mLastQSExpansion, mLastPanelFraction, mLastHeaderTranslation,
- isTransitioningToFullShade ? progress : mSquishinessFraction);
+ isTransitioningToFullShade ? qsSquishinessFraction : mSquishinessFraction);
}
@Override
@@ -598,12 +608,16 @@
}
@Override
+ public void setIsNotificationPanelFullWidth(boolean isFullWidth) {
+ mIsNotificationPanelFullWidth = isFullWidth;
+ }
+
+ @Override
public void setQsExpansion(float expansion, float panelExpansionFraction,
float proposedTranslation, float squishinessFraction) {
float headerTranslation = mTransitioningToFullShade ? 0 : proposedTranslation;
- float alphaProgress = mTransitioningToFullShade || mState == StatusBarState.KEYGUARD
- ? mFullShadeProgress : panelExpansionFraction;
- setAlphaAnimationProgress(mInSplitShade ? alphaProgress : 1);
+ float alphaProgress = calculateAlphaProgress(panelExpansionFraction);
+ setAlphaAnimationProgress(alphaProgress);
mContainer.setExpansion(expansion);
final float translationScaleY = (mInSplitShade
? 1 : QSAnimator.SHORT_PARALLAX_AMOUNT) * (expansion - 1);
@@ -684,10 +698,43 @@
} else if (progress > 0 && view.getVisibility() != View.VISIBLE) {
view.setVisibility((View.VISIBLE));
}
- float alpha = mQSPanelController.isBouncerInTransit()
- ? BouncerPanelExpansionCalculator.aboutToShowBouncerProgress(progress)
- : ShadeInterpolation.getContentAlpha(progress);
- view.setAlpha(alpha);
+ view.setAlpha(interpolateAlphaAnimationProgress(progress));
+ }
+
+ private float calculateAlphaProgress(float panelExpansionFraction) {
+ if (mIsNotificationPanelFullWidth) {
+ // Small screens. QS alpha is not animated.
+ return 1;
+ }
+ if (mInSplitShade) {
+ // Large screens in landscape.
+ if (mTransitioningToFullShade || isKeyguardState()) {
+ // Always use "mFullShadeProgress" on keyguard, because
+ // "panelExpansionFractions" is always 1 on keyguard split shade.
+ return mFullShadeProgress;
+ } else {
+ return panelExpansionFraction;
+ }
+ }
+ // Large screens in portrait.
+ if (mTransitioningToFullShade) {
+ // Only use this value during the standard lock screen shade expansion. During the
+ // "quick" expansion from top, this value is 0.
+ return mFullShadeProgress;
+ } else {
+ return panelExpansionFraction;
+ }
+ }
+
+ private float interpolateAlphaAnimationProgress(float progress) {
+ if (mQSPanelController.isBouncerInTransit()) {
+ return BouncerPanelExpansionCalculator.aboutToShowBouncerProgress(progress);
+ }
+ if (isKeyguardState()) {
+ // Alpha progress should be linear on lockscreen shade expansion.
+ return progress;
+ }
+ return ShadeInterpolation.getContentAlpha(progress);
}
private void updateQsBounds() {
diff --git a/packages/SystemUI/src/com/android/systemui/shade/NotificationPanelViewController.java b/packages/SystemUI/src/com/android/systemui/shade/NotificationPanelViewController.java
index c3b265f..156b123 100644
--- a/packages/SystemUI/src/com/android/systemui/shade/NotificationPanelViewController.java
+++ b/packages/SystemUI/src/com/android/systemui/shade/NotificationPanelViewController.java
@@ -1320,6 +1320,9 @@
mIsFullWidth = isFullWidth;
mScrimController.setClipsQsScrim(isFullWidth);
mNotificationStackScrollLayoutController.setIsFullWidth(isFullWidth);
+ if (mQs != null) {
+ mQs.setIsNotificationPanelFullWidth(isFullWidth);
+ }
}
private void startQsSizeChangeAnimation(int oldHeight, final int newHeight) {
@@ -2428,8 +2431,8 @@
final float squishiness;
if ((mQsExpandImmediate || mQsExpanded) && !mSplitShadeEnabled) {
squishiness = 1;
- } else if (mLockscreenShadeTransitionController.getQSDragProgress() > 0) {
- squishiness = mLockscreenShadeTransitionController.getQSDragProgress();
+ } else if (mTransitioningToFullShadeProgress > 0.0f) {
+ squishiness = mLockscreenShadeTransitionController.getQsSquishTransitionFraction();
} else {
squishiness = mNotificationStackScrollLayoutController
.getNotificationSquishinessFraction();
@@ -3716,6 +3719,7 @@
mQs.setHeaderClickable(isQsExpansionEnabled());
mQs.setOverscrolling(mStackScrollerOverscrolling);
mQs.setInSplitShade(mSplitShadeEnabled);
+ mQs.setIsNotificationPanelFullWidth(mIsFullWidth);
// recompute internal state when qspanel height changes
mQs.getView().addOnLayoutChangeListener(
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/LockscreenShadeQsTransitionController.kt b/packages/SystemUI/src/com/android/systemui/statusbar/LockscreenShadeQsTransitionController.kt
new file mode 100644
index 0000000..62c225b
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/LockscreenShadeQsTransitionController.kt
@@ -0,0 +1,159 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.statusbar
+
+import android.content.Context
+import android.util.IndentingPrintWriter
+import android.util.MathUtils
+import androidx.annotation.FloatRange
+import androidx.annotation.Px
+import com.android.systemui.R
+import com.android.systemui.dump.DumpManager
+import com.android.systemui.plugins.qs.QS
+import com.android.systemui.statusbar.policy.ConfigurationController
+import dagger.assisted.Assisted
+import dagger.assisted.AssistedFactory
+import dagger.assisted.AssistedInject
+import kotlin.math.max
+
+/** Responsible for the QS components during the lockscreen shade transition. */
+class LockscreenShadeQsTransitionController
+@AssistedInject
+constructor(
+ context: Context,
+ configurationController: ConfigurationController,
+ dumpManager: DumpManager,
+ @Assisted private val qsProvider: () -> QS,
+) : AbstractLockscreenShadeTransitionController(context, configurationController, dumpManager) {
+
+ private val qs: QS
+ get() = qsProvider()
+
+ /**
+ * The progress fraction of the QS transition during lockscreen shade expansion.
+ *
+ * Note that this value might be 0 for some time when the expansion is already in progress,
+ * since there is a transition start delay for QS on some device configurations. For this
+ * reason, don't use this value to check whether the shade expansion is in progress.
+ */
+ @FloatRange(from = 0.0, to = 1.0)
+ var qsTransitionFraction = 0f
+ private set
+
+ /**
+ * The fraction of the QS "squish" transition progress during lockscreen shade expansion.
+ *
+ * Note that in some device configurations (large screens) this value can start at a value
+ * greater than 0. For this reason don't use this value to check whether the QS transition has
+ * started or not.
+ */
+ @FloatRange(from = 0.0, to = 1.0)
+ var qsSquishTransitionFraction = 0f
+ private set
+
+ /**
+ * The drag down amount, in pixels __for the QS transition__, also taking into account the
+ * [qsTransitionStartDelay].
+ *
+ * Since it takes into account the start delay, it is __not__ the same as the raw drag down
+ * amount from the shade expansion.
+ */
+ @Px private var qsDragDownAmount = 0f
+
+ /**
+ * Distance it takes for the QS transition to complete during the lockscreen shade expansion.
+ */
+ @Px private var qsTransitionDistance = 0
+
+ /** Distance delay for the QS transition to start during the lockscreen shade expansion. */
+ @Px private var qsTransitionStartDelay = 0
+
+ /**
+ * Distance that it takes to complete the QS "squish" transition during the lockscreen shade
+ * expansion.
+ */
+ @Px private var qsSquishTransitionDistance = 0
+
+ /**
+ * Whether the transition to full shade is in progress. Might be `true` even though
+ * [qsTransitionFraction] is still 0, due to [qsTransitionStartDelay].
+ */
+ private var isTransitioningToFullShade = false
+
+ /**
+ * The fraction at which the QS "squish" transition should start during the lockscreen shade
+ * expansion.
+ *
+ * 0 is fully collapsed, 1 is fully expanded.
+ */
+ @FloatRange(from = 0.0, to = 1.0) private var qsSquishStartFraction = 0f
+
+ override fun updateResources() {
+ qsTransitionDistance =
+ context.resources.getDimensionPixelSize(R.dimen.lockscreen_shade_qs_transition_distance)
+ qsTransitionStartDelay =
+ context.resources.getDimensionPixelSize(R.dimen.lockscreen_shade_qs_transition_delay)
+ qsSquishTransitionDistance =
+ context.resources.getDimensionPixelSize(
+ R.dimen.lockscreen_shade_qs_squish_transition_distance
+ )
+ qsSquishStartFraction =
+ context.resources.getFloat(R.dimen.lockscreen_shade_qs_squish_start_fraction)
+
+ qsSquishTransitionFraction = max(qsSquishTransitionFraction, qsSquishStartFraction)
+ }
+
+ override fun onDragDownAmountChanged(dragDownAmount: Float) {
+ qsDragDownAmount = dragDownAmount - qsTransitionStartDelay
+ qsTransitionFraction = MathUtils.saturate(qsDragDownAmount / qsTransitionDistance)
+ qsSquishTransitionFraction =
+ MathUtils.lerp(
+ /* start= */ qsSquishStartFraction,
+ /* stop= */ 1f,
+ /* amount= */ MathUtils.saturate(qsDragDownAmount / qsSquishTransitionDistance)
+ )
+ isTransitioningToFullShade = dragDownAmount > 0.0f
+ qs.setTransitionToFullShadeProgress(
+ isTransitioningToFullShade,
+ qsTransitionFraction,
+ qsSquishTransitionFraction
+ )
+ }
+
+ override fun dump(pw: IndentingPrintWriter) {
+ pw.println(
+ """
+ Resources:
+ qsTransitionDistance: $qsTransitionDistance
+ qsTransitionStartDelay: $qsTransitionStartDelay
+ qsSquishTransitionDistance: $qsSquishTransitionDistance
+ qsSquishStartFraction: $qsSquishStartFraction
+ State:
+ dragDownAmount: $dragDownAmount
+ qsDragDownAmount: $qsDragDownAmount
+ qsDragFraction: $qsTransitionFraction
+ qsSquishFraction: $qsSquishTransitionFraction
+ isTransitioningToFullShade: $isTransitioningToFullShade
+ """.trimIndent()
+ )
+ }
+
+ @AssistedFactory
+ fun interface Factory {
+ fun create(qsProvider: () -> QS): LockscreenShadeQsTransitionController
+ }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/LockscreenShadeTransitionController.kt b/packages/SystemUI/src/com/android/systemui/statusbar/LockscreenShadeTransitionController.kt
index d3343df..8006931 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/LockscreenShadeTransitionController.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/LockscreenShadeTransitionController.kt
@@ -11,6 +11,7 @@
import android.view.MotionEvent
import android.view.View
import android.view.ViewConfiguration
+import androidx.annotation.FloatRange
import androidx.annotation.VisibleForTesting
import com.android.systemui.Dumpable
import com.android.systemui.ExpandHelper
@@ -68,7 +69,8 @@
wakefulnessLifecycle: WakefulnessLifecycle,
configurationController: ConfigurationController,
falsingManager: FalsingManager,
- dumpManager: DumpManager
+ dumpManager: DumpManager,
+ qsTransitionControllerFactory: LockscreenShadeQsTransitionController.Factory,
) : Dumpable {
private var pulseHeight: Float = 0f
@get:VisibleForTesting
@@ -120,12 +122,6 @@
private var notificationShelfTransitionDistance = 0
/**
- * Distance that the full shade transition takes in order for the Quick Settings to fully fade
- * and expand.
- */
- private var qsTransitionDistance = 0
-
- /**
* Distance that the full shade transition takes in order for depth of the wallpaper to fully
* change.
*/
@@ -188,6 +184,18 @@
keyguardTransitionControllerFactory.create(notificationPanelController)
}
+ private val qsTransitionController = qsTransitionControllerFactory.create { qS }
+
+ /** See [LockscreenShadeQsTransitionController.qsTransitionFraction].*/
+ @get:FloatRange(from = 0.0, to = 1.0)
+ val qSDragProgress: Float
+ get() = qsTransitionController.qsTransitionFraction
+
+ /** See [LockscreenShadeQsTransitionController.qsSquishTransitionFraction].*/
+ @get:FloatRange(from = 0.0, to = 1.0)
+ val qsSquishTransitionFraction: Float
+ get() = qsTransitionController.qsSquishTransitionFraction
+
/**
* [LockScreenShadeOverScroller] property that delegates to either
* [SingleShadeLockScreenOverScroller] or [SplitShadeLockScreenOverScroller].
@@ -242,8 +250,6 @@
R.dimen.lockscreen_shade_transition_by_tap_distance)
notificationShelfTransitionDistance = context.resources.getDimensionPixelSize(
R.dimen.lockscreen_shade_notif_shelf_transition_distance)
- qsTransitionDistance = context.resources.getDimensionPixelSize(
- R.dimen.lockscreen_shade_qs_transition_distance)
depthControllerTransitionDistance = context.resources.getDimensionPixelSize(
R.dimen.lockscreen_shade_depth_controller_transition_distance)
udfpsTransitionDistance = context.resources.getDimensionPixelSize(
@@ -411,8 +417,7 @@
MathUtils.saturate(dragDownAmount / notificationShelfTransitionDistance)
nsslController.setTransitionToFullShadeAmount(fractionToShade)
- qSDragProgress = MathUtils.saturate(dragDownAmount / qsTransitionDistance)
- qS.setTransitionToFullShadeAmount(field, qSDragProgress)
+ qsTransitionController.dragDownAmount = value
notificationPanelController.setTransitionToFullShadeAmount(field,
false /* animate */, 0 /* delay */)
@@ -426,12 +431,6 @@
}
}
- /**
- * The drag progress of the quick settings drag down amount
- */
- var qSDragProgress = 0f
- private set
-
private fun transitionToShadeAmountCommon(dragDownAmount: Float) {
if (depthControllerTransitionDistance == 0) { // split shade
depthController.transitionToFullShadeProgress = 0f
@@ -704,7 +703,6 @@
it.println("pulseHeight: $pulseHeight")
it.println("useSplitShade: $useSplitShade")
it.println("dragDownAmount: $dragDownAmount")
- it.println("qSDragProgress: $qSDragProgress")
it.println("isDragDownAnywhereEnabled: $isDragDownAnywhereEnabled")
it.println("isFalsingCheckNeeded: $isFalsingCheckNeeded")
it.println("isWakingToShadeLocked: $isWakingToShadeLocked")
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/ScrimController.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/ScrimController.java
index cb0a148..4d1c361 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/ScrimController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/ScrimController.java
@@ -259,11 +259,17 @@
private boolean mKeyguardOccluded;
@Inject
- public ScrimController(LightBarController lightBarController, DozeParameters dozeParameters,
- AlarmManager alarmManager, KeyguardStateController keyguardStateController,
- DelayedWakeLock.Builder delayedWakeLockBuilder, Handler handler,
- KeyguardUpdateMonitor keyguardUpdateMonitor, DockManager dockManager,
- ConfigurationController configurationController, @Main Executor mainExecutor,
+ public ScrimController(
+ LightBarController lightBarController,
+ DozeParameters dozeParameters,
+ AlarmManager alarmManager,
+ KeyguardStateController keyguardStateController,
+ DelayedWakeLock.Builder delayedWakeLockBuilder,
+ Handler handler,
+ KeyguardUpdateMonitor keyguardUpdateMonitor,
+ DockManager dockManager,
+ ConfigurationController configurationController,
+ @Main Executor mainExecutor,
ScreenOffAnimationController screenOffAnimationController,
KeyguardUnlockAnimationController keyguardUnlockAnimationController,
StatusBarKeyguardViewManager statusBarKeyguardViewManager) {
@@ -826,20 +832,15 @@
mBehindTint = Color.BLACK;
} else {
mBehindAlpha = behindAlpha;
- if (mState == ScrimState.SHADE_LOCKED) {
+ if (mState == ScrimState.KEYGUARD && mTransitionToFullShadeProgress > 0.0f) {
+ mNotificationsAlpha = MathUtils
+ .saturate(mTransitionToLockScreenFullShadeNotificationsProgress);
+ } else if (mState == ScrimState.SHADE_LOCKED) {
// going from KEYGUARD to SHADE_LOCKED state
mNotificationsAlpha = getInterpolatedFraction();
} else {
mNotificationsAlpha = Math.max(1.0f - getInterpolatedFraction(), mQsExpansion);
}
- if (mState == ScrimState.KEYGUARD
- && mTransitionToLockScreenFullShadeNotificationsProgress > 0.0f) {
- // Interpolate the notification alpha when transitioning!
- mNotificationsAlpha = MathUtils.lerp(
- mNotificationsAlpha,
- getInterpolatedFraction(),
- mTransitionToLockScreenFullShadeNotificationsProgress);
- }
mNotificationsTint = mState.getNotifTint();
mBehindTint = behindTint;
}
@@ -1430,6 +1431,8 @@
pw.print(mNotificationsAlpha);
pw.print(" tint=0x");
pw.println(Integer.toHexString(mNotificationsScrim.getTint()));
+ pw.print(" expansionProgress=");
+ pw.println(mTransitionToLockScreenFullShadeNotificationsProgress);
pw.print(" mTracking=");
pw.println(mTracking);
diff --git a/packages/SystemUI/src/com/android/systemui/ImageWallpaper.java b/packages/SystemUI/src/com/android/systemui/wallpapers/ImageWallpaper.java
similarity index 98%
rename from packages/SystemUI/src/com/android/systemui/ImageWallpaper.java
rename to packages/SystemUI/src/com/android/systemui/wallpapers/ImageWallpaper.java
index 8ff90f7..2878ad9 100644
--- a/packages/SystemUI/src/com/android/systemui/ImageWallpaper.java
+++ b/packages/SystemUI/src/com/android/systemui/wallpapers/ImageWallpaper.java
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-package com.android.systemui;
+package com.android.systemui.wallpapers;
import android.app.WallpaperColors;
import android.graphics.Bitmap;
@@ -37,8 +37,8 @@
import androidx.annotation.NonNull;
import com.android.internal.annotations.VisibleForTesting;
-import com.android.systemui.glwallpaper.EglHelper;
-import com.android.systemui.glwallpaper.ImageWallpaperRenderer;
+import com.android.systemui.wallpapers.gl.EglHelper;
+import com.android.systemui.wallpapers.gl.ImageWallpaperRenderer;
import java.io.FileDescriptor;
import java.io.PrintWriter;
diff --git a/packages/SystemUI/src/com/android/systemui/wallpapers/OWNERS b/packages/SystemUI/src/com/android/systemui/wallpapers/OWNERS
new file mode 100644
index 0000000..731c798
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/wallpapers/OWNERS
@@ -0,0 +1,6 @@
+set noparent
+
+cinek@google.com
+dupin@google.com
+pomini@google.com
+santie@google.com
diff --git a/packages/SystemUI/src/com/android/systemui/glwallpaper/EglHelper.java b/packages/SystemUI/src/com/android/systemui/wallpapers/gl/EglHelper.java
similarity index 99%
rename from packages/SystemUI/src/com/android/systemui/glwallpaper/EglHelper.java
rename to packages/SystemUI/src/com/android/systemui/wallpapers/gl/EglHelper.java
index 11e215d..f9ddce8 100644
--- a/packages/SystemUI/src/com/android/systemui/glwallpaper/EglHelper.java
+++ b/packages/SystemUI/src/com/android/systemui/wallpapers/gl/EglHelper.java
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-package com.android.systemui.glwallpaper;
+package com.android.systemui.wallpapers.gl;
import static android.opengl.EGL14.EGL_ALPHA_SIZE;
import static android.opengl.EGL14.EGL_BLUE_SIZE;
diff --git a/packages/SystemUI/src/com/android/systemui/glwallpaper/GLWallpaperRenderer.java b/packages/SystemUI/src/com/android/systemui/wallpapers/gl/GLWallpaperRenderer.java
similarity index 97%
rename from packages/SystemUI/src/com/android/systemui/glwallpaper/GLWallpaperRenderer.java
rename to packages/SystemUI/src/com/android/systemui/wallpapers/gl/GLWallpaperRenderer.java
index 6152490..692ced0 100644
--- a/packages/SystemUI/src/com/android/systemui/glwallpaper/GLWallpaperRenderer.java
+++ b/packages/SystemUI/src/com/android/systemui/wallpapers/gl/GLWallpaperRenderer.java
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-package com.android.systemui.glwallpaper;
+package com.android.systemui.wallpapers.gl;
import android.util.Size;
diff --git a/packages/SystemUI/src/com/android/systemui/glwallpaper/ImageGLProgram.java b/packages/SystemUI/src/com/android/systemui/wallpapers/gl/ImageGLProgram.java
similarity index 98%
rename from packages/SystemUI/src/com/android/systemui/glwallpaper/ImageGLProgram.java
rename to packages/SystemUI/src/com/android/systemui/wallpapers/gl/ImageGLProgram.java
index d03b00b..d34eca4 100644
--- a/packages/SystemUI/src/com/android/systemui/glwallpaper/ImageGLProgram.java
+++ b/packages/SystemUI/src/com/android/systemui/wallpapers/gl/ImageGLProgram.java
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-package com.android.systemui.glwallpaper;
+package com.android.systemui.wallpapers.gl;
import static android.opengl.GLES20.GL_FRAGMENT_SHADER;
import static android.opengl.GLES20.GL_VERTEX_SHADER;
diff --git a/packages/SystemUI/src/com/android/systemui/glwallpaper/ImageGLWallpaper.java b/packages/SystemUI/src/com/android/systemui/wallpapers/gl/ImageGLWallpaper.java
similarity index 99%
rename from packages/SystemUI/src/com/android/systemui/glwallpaper/ImageGLWallpaper.java
rename to packages/SystemUI/src/com/android/systemui/wallpapers/gl/ImageGLWallpaper.java
index 1a53c28..f1659b9 100644
--- a/packages/SystemUI/src/com/android/systemui/glwallpaper/ImageGLWallpaper.java
+++ b/packages/SystemUI/src/com/android/systemui/wallpapers/gl/ImageGLWallpaper.java
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-package com.android.systemui.glwallpaper;
+package com.android.systemui.wallpapers.gl;
import static android.opengl.GLES20.GL_FLOAT;
import static android.opengl.GLES20.GL_LINEAR;
diff --git a/packages/SystemUI/src/com/android/systemui/glwallpaper/ImageWallpaperRenderer.java b/packages/SystemUI/src/com/android/systemui/wallpapers/gl/ImageWallpaperRenderer.java
similarity index 98%
rename from packages/SystemUI/src/com/android/systemui/glwallpaper/ImageWallpaperRenderer.java
rename to packages/SystemUI/src/com/android/systemui/wallpapers/gl/ImageWallpaperRenderer.java
index 7c0b93b..e393786 100644
--- a/packages/SystemUI/src/com/android/systemui/glwallpaper/ImageWallpaperRenderer.java
+++ b/packages/SystemUI/src/com/android/systemui/wallpapers/gl/ImageWallpaperRenderer.java
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-package com.android.systemui.glwallpaper;
+package com.android.systemui.wallpapers.gl;
import static android.opengl.GLES20.GL_COLOR_BUFFER_BIT;
import static android.opengl.GLES20.glClear;
diff --git a/packages/SystemUI/tests/src/com/android/systemui/media/MediaCarouselControllerTest.kt b/packages/SystemUI/tests/src/com/android/systemui/media/MediaCarouselControllerTest.kt
index 1bc1972..5a50a9f 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/media/MediaCarouselControllerTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/media/MediaCarouselControllerTest.kt
@@ -30,6 +30,7 @@
import com.android.systemui.statusbar.policy.ConfigurationController
import com.android.systemui.util.animation.TransitionLayout
import com.android.systemui.util.concurrency.DelayableExecutor
+import com.android.systemui.util.mockito.capture
import com.android.systemui.util.mockito.eq
import com.android.systemui.util.time.FakeSystemClock
import javax.inject.Provider
@@ -38,6 +39,8 @@
import org.junit.Before
import org.junit.Test
import org.junit.runner.RunWith
+import org.mockito.ArgumentCaptor
+import org.mockito.Captor
import org.mockito.Mock
import org.mockito.Mockito.verify
import org.mockito.Mockito.verifyNoMoreInteractions
@@ -71,6 +74,10 @@
@Mock lateinit var player: TransitionLayout
@Mock lateinit var recommendationViewHolder: RecommendationViewHolder
@Mock lateinit var recommendations: TransitionLayout
+ @Mock lateinit var mediaPlayer: MediaControlPanel
+ @Mock lateinit var mediaViewController: MediaViewController
+ @Mock lateinit var smartspaceMediaData: SmartspaceMediaData
+ @Captor lateinit var listener: ArgumentCaptor<MediaDataManager.Listener>
private val clock = FakeSystemClock()
private lateinit var mediaCarouselController: MediaCarouselController
@@ -94,7 +101,10 @@
logger,
debugLogger
)
-
+ verify(mediaDataManager).addListener(capture(listener))
+ whenever(mediaControlPanelFactory.get()).thenReturn(mediaPlayer)
+ whenever(mediaPlayer.mediaViewController).thenReturn(mediaViewController)
+ whenever(mediaDataManager.smartspaceMediaData).thenReturn(smartspaceMediaData)
MediaPlayerData.clear()
}
@@ -305,4 +315,63 @@
verifyNoMoreInteractions(mediaViewHolder)
verify(recommendationViewHolder.recommendations).bottom = 75
}
+
+ fun testMediaLoaded_ScrollToActivePlayer() {
+ listener.value.onMediaDataLoaded("playing local",
+ null,
+ DATA.copy(active = true, isPlaying = true,
+ playbackLocation = MediaData.PLAYBACK_LOCAL, resumption = false)
+ )
+ listener.value.onMediaDataLoaded("paused local",
+ null,
+ DATA.copy(active = true, isPlaying = false,
+ playbackLocation = MediaData.PLAYBACK_LOCAL, resumption = false))
+ // adding a media recommendation card.
+ MediaPlayerData.addMediaRecommendation(SMARTSPACE_KEY, EMPTY_SMARTSPACE_MEDIA_DATA, panel,
+ false, clock)
+ mediaCarouselController.shouldScrollToActivePlayer = true
+ // switching between media players.
+ listener.value.onMediaDataLoaded("playing local",
+ "playing local",
+ DATA.copy(active = true, isPlaying = false,
+ playbackLocation = MediaData.PLAYBACK_LOCAL, resumption = true)
+ )
+ listener.value.onMediaDataLoaded("paused local",
+ "paused local",
+ DATA.copy(active = true, isPlaying = true,
+ playbackLocation = MediaData.PLAYBACK_LOCAL, resumption = false))
+
+ assertEquals(
+ MediaPlayerData.getMediaPlayerIndex("paused local"),
+ mediaCarouselController.mediaCarouselScrollHandler.visibleMediaIndex
+ )
+ }
+
+ @Test
+ fun testMediaLoadedFromRecommendationCard_ScrollToActivePlayer() {
+ MediaPlayerData.addMediaRecommendation(SMARTSPACE_KEY, EMPTY_SMARTSPACE_MEDIA_DATA, panel,
+ false, clock)
+ listener.value.onMediaDataLoaded("playing local",
+ null,
+ DATA.copy(active = true, isPlaying = true,
+ playbackLocation = MediaData.PLAYBACK_LOCAL, resumption = false)
+ )
+
+ var playerIndex = MediaPlayerData.getMediaPlayerIndex("playing local")
+ assertEquals(
+ playerIndex,
+ mediaCarouselController.mediaCarouselScrollHandler.visibleMediaIndex
+ )
+ assertEquals( playerIndex, 0)
+
+ // Replaying the same media player one more time.
+ // And check that the card stays in its position.
+ listener.value.onMediaDataLoaded("playing local",
+ null,
+ DATA.copy(active = true, isPlaying = true,
+ playbackLocation = MediaData.PLAYBACK_LOCAL, resumption = false)
+ )
+ playerIndex = MediaPlayerData.getMediaPlayerIndex("playing local")
+ assertEquals(playerIndex, 0)
+ }
}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/qs/QSFragmentTest.java b/packages/SystemUI/tests/src/com/android/systemui/qs/QSFragmentTest.java
index f08ad24..5d5918d 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/qs/QSFragmentTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/qs/QSFragmentTest.java
@@ -94,6 +94,7 @@
@Mock private QSPanel.QSTileLayout mQQsTileLayout;
@Mock private QSAnimator mQSAnimator;
@Mock private StatusBarStateController mStatusBarStateController;
+ @Mock private QSSquishinessController mSquishinessController;
private View mQsFragmentView;
public QSFragmentTest() {
@@ -139,13 +140,15 @@
}
@Test
- public void transitionToFullShade_inSplitShade_setsAlphaBasedOnProgress() {
+ public void transitionToFullShade_setsAlphaUsingShadeInterpolator() {
QSFragment fragment = resumeAndGetFragment();
- enableSplitShade();
- int transitionPxAmount = 123;
+ setStatusBarState(StatusBarState.SHADE);
+ boolean isTransitioningToFullShade = true;
float transitionProgress = 0.5f;
+ float squishinessFraction = 0.5f;
- fragment.setTransitionToFullShadeAmount(transitionPxAmount, transitionProgress);
+ fragment.setTransitionToFullShadeProgress(isTransitioningToFullShade, transitionProgress,
+ squishinessFraction);
assertThat(mQsFragmentView.getAlpha())
.isEqualTo(ShadeInterpolation.getContentAlpha(transitionProgress));
@@ -153,31 +156,32 @@
@Test
public void
- transitionToFullShade_inSplitShade_onKeyguard_bouncerNotActive_usesShadeInterpolator() {
+ transitionToFullShade_onKeyguard_noBouncer_setsAlphaUsingLinearInterpolator() {
QSFragment fragment = resumeAndGetFragment();
- enableSplitShade();
setStatusBarState(StatusBarState.KEYGUARD);
when(mQSPanelController.isBouncerInTransit()).thenReturn(false);
- int transitionPxAmount = 123;
+ boolean isTransitioningToFullShade = true;
float transitionProgress = 0.5f;
+ float squishinessFraction = 0.5f;
- fragment.setTransitionToFullShadeAmount(transitionPxAmount, transitionProgress);
+ fragment.setTransitionToFullShadeProgress(isTransitioningToFullShade, transitionProgress,
+ squishinessFraction);
- assertThat(mQsFragmentView.getAlpha())
- .isEqualTo(ShadeInterpolation.getContentAlpha(transitionProgress));
+ assertThat(mQsFragmentView.getAlpha()).isEqualTo(transitionProgress);
}
@Test
public void
- transitionToFullShade_inSplitShade_onKeyguard_bouncerActive_usesBouncerInterpolator() {
+ transitionToFullShade_onKeyguard_bouncerActive_setsAlphaUsingBouncerInterpolator() {
QSFragment fragment = resumeAndGetFragment();
- enableSplitShade();
setStatusBarState(StatusBarState.KEYGUARD);
when(mQSPanelController.isBouncerInTransit()).thenReturn(true);
- int transitionPxAmount = 123;
+ boolean isTransitioningToFullShade = true;
float transitionProgress = 0.5f;
+ float squishinessFraction = 0.5f;
- fragment.setTransitionToFullShadeAmount(transitionPxAmount, transitionProgress);
+ fragment.setTransitionToFullShadeProgress(isTransitioningToFullShade, transitionProgress,
+ squishinessFraction);
assertThat(mQsFragmentView.getAlpha())
.isEqualTo(
@@ -186,28 +190,44 @@
}
@Test
- public void transitionToFullShade_notInSplitShade_alwaysSetsAlphaTo1() {
+ public void transitionToFullShade_inFullWidth_alwaysSetsAlphaTo1() {
QSFragment fragment = resumeAndGetFragment();
- disableSplitShade();
+ fragment.setIsNotificationPanelFullWidth(true);
- int transitionPxAmount = 12;
+ boolean isTransitioningToFullShade = true;
float transitionProgress = 0.1f;
- fragment.setTransitionToFullShadeAmount(transitionPxAmount, transitionProgress);
+ float squishinessFraction = 0.5f;
+ fragment.setTransitionToFullShadeProgress(isTransitioningToFullShade, transitionProgress,
+ squishinessFraction);
assertThat(mQsFragmentView.getAlpha()).isEqualTo(1);
- transitionPxAmount = 123;
transitionProgress = 0.5f;
- fragment.setTransitionToFullShadeAmount(transitionPxAmount, transitionProgress);
+ fragment.setTransitionToFullShadeProgress(isTransitioningToFullShade, transitionProgress,
+ squishinessFraction);
assertThat(mQsFragmentView.getAlpha()).isEqualTo(1);
assertThat(mQsFragmentView.getAlpha()).isEqualTo(1);
- transitionPxAmount = 234;
transitionProgress = 0.7f;
- fragment.setTransitionToFullShadeAmount(transitionPxAmount, transitionProgress);
+ fragment.setTransitionToFullShadeProgress(isTransitioningToFullShade, transitionProgress,
+ squishinessFraction);
assertThat(mQsFragmentView.getAlpha()).isEqualTo(1);
}
@Test
+ public void transitionToFullShade_setsSquishinessOnController() {
+ QSFragment fragment = resumeAndGetFragment();
+ boolean isTransitioningToFullShade = true;
+ float transitionProgress = 0.123f;
+ float squishinessFraction = 0.456f;
+
+ fragment.setTransitionToFullShadeProgress(isTransitioningToFullShade, transitionProgress,
+ squishinessFraction);
+
+ verify(mQsFragmentComponent.getQSSquishinessController())
+ .setSquishiness(squishinessFraction);
+ }
+
+ @Test
public void setQsExpansion_inSplitShade_setsFooterActionsExpansion_basedOnPanelExpFraction() {
// Random test values without any meaning. They just have to be different from each other.
float expansion = 0.123f;
@@ -453,6 +473,7 @@
when(mQsFragmentComponent.getQSFooterActionController())
.thenReturn(mQSFooterActionController);
when(mQsFragmentComponent.getQSAnimator()).thenReturn(mQSAnimator);
+ when(mQsFragmentComponent.getQSSquishinessController()).thenReturn(mSquishinessController);
}
private QSFragment getFragment() {
diff --git a/packages/SystemUI/tests/src/com/android/systemui/shade/NotificationPanelViewControllerTest.java b/packages/SystemUI/tests/src/com/android/systemui/shade/NotificationPanelViewControllerTest.java
index 3224a6f..f1c54ef 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/shade/NotificationPanelViewControllerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/shade/NotificationPanelViewControllerTest.java
@@ -42,7 +42,6 @@
import static org.mockito.Mockito.when;
import android.annotation.IdRes;
-import android.app.ActivityManager;
import android.content.ContentResolver;
import android.content.res.Configuration;
import android.content.res.Resources;
@@ -57,6 +56,7 @@
import android.view.LayoutInflater;
import android.view.MotionEvent;
import android.view.View;
+import android.view.ViewGroup;
import android.view.ViewParent;
import android.view.ViewPropertyAnimator;
import android.view.ViewStub;
@@ -107,6 +107,7 @@
import com.android.systemui.plugins.FalsingManager;
import com.android.systemui.plugins.qs.QS;
import com.android.systemui.qrcodescanner.controller.QRCodeScannerController;
+import com.android.systemui.qs.QSFragment;
import com.android.systemui.screenrecord.RecordingController;
import com.android.systemui.shade.transition.ShadeTransitionController;
import com.android.systemui.statusbar.CommandQueue;
@@ -160,8 +161,6 @@
import com.android.systemui.statusbar.policy.KeyguardUserSwitcherView;
import com.android.systemui.statusbar.window.StatusBarWindowStateController;
import com.android.systemui.unfold.SysUIUnfoldComponent;
-import com.android.systemui.util.concurrency.FakeExecutor;
-import com.android.systemui.util.settings.SecureSettings;
import com.android.systemui.util.time.FakeSystemClock;
import com.android.systemui.util.time.SystemClock;
import com.android.systemui.wallet.controller.QuickAccessWalletController;
@@ -185,225 +184,134 @@
public class NotificationPanelViewControllerTest extends SysuiTestCase {
private static final int NOTIFICATION_SCRIM_TOP_PADDING_IN_SPLIT_SHADE = 50;
+ private static final int PANEL_WIDTH = 500; // Random value just for the test.
- @Mock
- private CentralSurfaces mCentralSurfaces;
- @Mock
- private NotificationStackScrollLayout mNotificationStackScrollLayout;
- @Mock
- private KeyguardBottomAreaView mKeyguardBottomArea;
- @Mock
- private KeyguardBottomAreaViewController mKeyguardBottomAreaViewController;
- @Mock
- private KeyguardBottomAreaView mQsFrame;
- private KeyguardStatusView mKeyguardStatusView;
- @Mock
- private NotificationIconAreaController mNotificationAreaController;
- @Mock
- private HeadsUpManagerPhone mHeadsUpManager;
- @Mock
- private NotificationShelfController mNotificationShelfController;
- @Mock
- private KeyguardStatusBarView mKeyguardStatusBar;
- @Mock
- private KeyguardUserSwitcherView mUserSwitcherView;
- @Mock
- private ViewStub mUserSwitcherStubView;
- @Mock
- private HeadsUpTouchHelper.Callback mHeadsUpCallback;
- @Mock
- private KeyguardUpdateMonitor mUpdateMonitor;
- @Mock
- private KeyguardBypassController mKeyguardBypassController;
- @Mock
- private DozeParameters mDozeParameters;
- @Mock
- private ScreenOffAnimationController mScreenOffAnimationController;
- @Mock
- private NotificationPanelView mView;
- @Mock
- private LayoutInflater mLayoutInflater;
- @Mock
- private FeatureFlags mFeatureFlags;
- @Mock
- private DynamicPrivacyController mDynamicPrivacyController;
- @Mock
- private StatusBarTouchableRegionManager mStatusBarTouchableRegionManager;
- @Mock
- private KeyguardStateController mKeyguardStateController;
- @Mock
- private DozeLog mDozeLog;
- @Mock
- private ShadeLogger mShadeLog;
- @Mock
- private CommandQueue mCommandQueue;
- @Mock
- private VibratorHelper mVibratorHelper;
- @Mock
- private LatencyTracker mLatencyTracker;
- @Mock
- private PowerManager mPowerManager;
- @Mock
- private AccessibilityManager mAccessibilityManager;
- @Mock
- private MetricsLogger mMetricsLogger;
- @Mock
- private ActivityManager mActivityManager;
- @Mock
- private Resources mResources;
- @Mock
- private Configuration mConfiguration;
- private DisplayMetrics mDisplayMetrics = new DisplayMetrics();
- @Mock
- private KeyguardClockSwitch mKeyguardClockSwitch;
- private NotificationPanelViewController.TouchHandler mTouchHandler;
- private ConfigurationController mConfigurationController;
- @Mock
- private MediaHierarchyManager mMediaHiearchyManager;
- @Mock
- private ConversationNotificationManager mConversationNotificationManager;
- @Mock
- private StatusBarKeyguardViewManager mStatusBarKeyguardViewManager;
- @Mock
- private KeyguardStatusViewComponent.Factory mKeyguardStatusViewComponentFactory;
- @Mock
- private KeyguardQsUserSwitchComponent.Factory mKeyguardQsUserSwitchComponentFactory;
- @Mock
- private KeyguardQsUserSwitchComponent mKeyguardQsUserSwitchComponent;
- @Mock
- private KeyguardQsUserSwitchController mKeyguardQsUserSwitchController;
- @Mock
- private KeyguardUserSwitcherComponent.Factory mKeyguardUserSwitcherComponentFactory;
- @Mock
- private KeyguardUserSwitcherComponent mKeyguardUserSwitcherComponent;
- @Mock
- private KeyguardUserSwitcherController mKeyguardUserSwitcherController;
- @Mock
- private KeyguardStatusViewComponent mKeyguardStatusViewComponent;
- @Mock
- private KeyguardStatusBarViewComponent.Factory mKeyguardStatusBarViewComponentFactory;
- @Mock
- private KeyguardStatusBarViewComponent mKeyguardStatusBarViewComponent;
- @Mock
- private KeyguardClockSwitchController mKeyguardClockSwitchController;
- @Mock
- private KeyguardStatusViewController mKeyguardStatusViewController;
- @Mock
- private KeyguardStatusBarViewController mKeyguardStatusBarViewController;
- @Mock
- private NotificationStackScrollLayoutController mNotificationStackScrollLayoutController;
- @Mock
- private NotificationShadeDepthController mNotificationShadeDepthController;
- @Mock
- private LockscreenShadeTransitionController mLockscreenShadeTransitionController;
- @Mock
- private AuthController mAuthController;
- @Mock
- private ScrimController mScrimController;
- @Mock
- private MediaDataManager mMediaDataManager;
- @Mock
- private AmbientState mAmbientState;
- @Mock
- private UserManager mUserManager;
- @Mock
- private UiEventLogger mUiEventLogger;
- @Mock
- private LockIconViewController mLockIconViewController;
- @Mock
- private KeyguardMediaController mKeyguardMediaController;
- @Mock
- private PrivacyDotViewController mPrivacyDotViewController;
- @Mock
- private NavigationModeController mNavigationModeController;
- @Mock
- private SecureSettings mSecureSettings;
- @Mock
- private LargeScreenShadeHeaderController mLargeScreenShadeHeaderController;
- @Mock
- private ContentResolver mContentResolver;
- @Mock
- private TapAgainViewController mTapAgainViewController;
- @Mock
- private KeyguardIndicationController mKeyguardIndicationController;
- @Mock
- private FragmentService mFragmentService;
- @Mock
- private FragmentHostManager mFragmentHostManager;
- @Mock
- private QuickAccessWalletController mQuickAccessWalletController;
- @Mock
- private QRCodeScannerController mQrCodeScannerController;
- @Mock
- private NotificationRemoteInputManager mNotificationRemoteInputManager;
- @Mock
- private RecordingController mRecordingController;
- @Mock
- private ControlsComponent mControlsComponent;
- @Mock
- private LockscreenGestureLogger mLockscreenGestureLogger;
- @Mock
- private DumpManager mDumpManager;
- @Mock
- private InteractionJankMonitor mInteractionJankMonitor;
- @Mock
- private NotificationsQSContainerController mNotificationsQSContainerController;
- @Mock
- private QsFrameTranslateController mQsFrameTranslateController;
- @Mock
- private StatusBarWindowStateController mStatusBarWindowStateController;
- @Mock
- private KeyguardUnlockAnimationController mKeyguardUnlockAnimationController;
- @Mock
- private NotificationShadeWindowController mNotificationShadeWindowController;
- @Mock
- private SysUiState mSysUiState;
- @Mock
- private NotificationListContainer mNotificationListContainer;
- @Mock
- private NotificationStackSizeCalculator mNotificationStackSizeCalculator;
- @Mock
- private UnlockedScreenOffAnimationController mUnlockedScreenOffAnimationController;
- @Mock
- private ShadeTransitionController mShadeTransitionController;
- @Mock
- private QS mQs;
- @Mock
- private View mQsHeader;
- @Mock
- private ViewParent mViewParent;
- @Mock
- private ViewTreeObserver mViewTreeObserver;
+ @Mock private CentralSurfaces mCentralSurfaces;
+ @Mock private NotificationStackScrollLayout mNotificationStackScrollLayout;
+ @Mock private KeyguardBottomAreaView mKeyguardBottomArea;
+ @Mock private KeyguardBottomAreaViewController mKeyguardBottomAreaViewController;
+ @Mock private KeyguardBottomAreaView mQsFrame;
+ @Mock private NotificationIconAreaController mNotificationAreaController;
+ @Mock private HeadsUpManagerPhone mHeadsUpManager;
+ @Mock private NotificationShelfController mNotificationShelfController;
+ @Mock private KeyguardStatusBarView mKeyguardStatusBar;
+ @Mock private KeyguardUserSwitcherView mUserSwitcherView;
+ @Mock private ViewStub mUserSwitcherStubView;
+ @Mock private HeadsUpTouchHelper.Callback mHeadsUpCallback;
+ @Mock private KeyguardUpdateMonitor mUpdateMonitor;
+ @Mock private KeyguardBypassController mKeyguardBypassController;
+ @Mock private DozeParameters mDozeParameters;
+ @Mock private ScreenOffAnimationController mScreenOffAnimationController;
+ @Mock private NotificationPanelView mView;
+ @Mock private LayoutInflater mLayoutInflater;
+ @Mock private FeatureFlags mFeatureFlags;
+ @Mock private DynamicPrivacyController mDynamicPrivacyController;
+ @Mock private StatusBarTouchableRegionManager mStatusBarTouchableRegionManager;
+ @Mock private KeyguardStateController mKeyguardStateController;
+ @Mock private DozeLog mDozeLog;
+ @Mock private ShadeLogger mShadeLog;
+ @Mock private CommandQueue mCommandQueue;
+ @Mock private VibratorHelper mVibratorHelper;
+ @Mock private LatencyTracker mLatencyTracker;
+ @Mock private PowerManager mPowerManager;
+ @Mock private AccessibilityManager mAccessibilityManager;
+ @Mock private MetricsLogger mMetricsLogger;
+ @Mock private Resources mResources;
+ @Mock private Configuration mConfiguration;
+ @Mock private KeyguardClockSwitch mKeyguardClockSwitch;
+ @Mock private MediaHierarchyManager mMediaHiearchyManager;
+ @Mock private ConversationNotificationManager mConversationNotificationManager;
+ @Mock private StatusBarKeyguardViewManager mStatusBarKeyguardViewManager;
+ @Mock private KeyguardStatusViewComponent.Factory mKeyguardStatusViewComponentFactory;
+ @Mock private KeyguardQsUserSwitchComponent.Factory mKeyguardQsUserSwitchComponentFactory;
+ @Mock private KeyguardQsUserSwitchComponent mKeyguardQsUserSwitchComponent;
+ @Mock private KeyguardQsUserSwitchController mKeyguardQsUserSwitchController;
+ @Mock private KeyguardUserSwitcherComponent.Factory mKeyguardUserSwitcherComponentFactory;
+ @Mock private KeyguardUserSwitcherComponent mKeyguardUserSwitcherComponent;
+ @Mock private KeyguardUserSwitcherController mKeyguardUserSwitcherController;
+ @Mock private KeyguardStatusViewComponent mKeyguardStatusViewComponent;
+ @Mock private KeyguardStatusBarViewComponent.Factory mKeyguardStatusBarViewComponentFactory;
+ @Mock private KeyguardStatusBarViewComponent mKeyguardStatusBarViewComponent;
+ @Mock private KeyguardClockSwitchController mKeyguardClockSwitchController;
+ @Mock private KeyguardStatusViewController mKeyguardStatusViewController;
+ @Mock private KeyguardStatusBarViewController mKeyguardStatusBarViewController;
+ @Mock private NotificationStackScrollLayoutController mNotificationStackScrollLayoutController;
+ @Mock private NotificationShadeDepthController mNotificationShadeDepthController;
+ @Mock private LockscreenShadeTransitionController mLockscreenShadeTransitionController;
+ @Mock private AuthController mAuthController;
+ @Mock private ScrimController mScrimController;
+ @Mock private MediaDataManager mMediaDataManager;
+ @Mock private AmbientState mAmbientState;
+ @Mock private UserManager mUserManager;
+ @Mock private UiEventLogger mUiEventLogger;
+ @Mock private LockIconViewController mLockIconViewController;
+ @Mock private KeyguardMediaController mKeyguardMediaController;
+ @Mock private PrivacyDotViewController mPrivacyDotViewController;
+ @Mock private NavigationModeController mNavigationModeController;
+ @Mock private LargeScreenShadeHeaderController mLargeScreenShadeHeaderController;
+ @Mock private ContentResolver mContentResolver;
+ @Mock private TapAgainViewController mTapAgainViewController;
+ @Mock private KeyguardIndicationController mKeyguardIndicationController;
+ @Mock private FragmentService mFragmentService;
+ @Mock private FragmentHostManager mFragmentHostManager;
+ @Mock private QuickAccessWalletController mQuickAccessWalletController;
+ @Mock private QRCodeScannerController mQrCodeScannerController;
+ @Mock private NotificationRemoteInputManager mNotificationRemoteInputManager;
+ @Mock private RecordingController mRecordingController;
+ @Mock private ControlsComponent mControlsComponent;
+ @Mock private LockscreenGestureLogger mLockscreenGestureLogger;
+ @Mock private DumpManager mDumpManager;
+ @Mock private InteractionJankMonitor mInteractionJankMonitor;
+ @Mock private NotificationsQSContainerController mNotificationsQSContainerController;
+ @Mock private QsFrameTranslateController mQsFrameTranslateController;
+ @Mock private StatusBarWindowStateController mStatusBarWindowStateController;
+ @Mock private KeyguardUnlockAnimationController mKeyguardUnlockAnimationController;
+ @Mock private NotificationShadeWindowController mNotificationShadeWindowController;
+ @Mock private SysUiState mSysUiState;
+ @Mock private NotificationListContainer mNotificationListContainer;
+ @Mock private NotificationStackSizeCalculator mNotificationStackSizeCalculator;
+ @Mock private UnlockedScreenOffAnimationController mUnlockedScreenOffAnimationController;
+ @Mock private ShadeTransitionController mShadeTransitionController;
+ @Mock private QS mQs;
+ @Mock private QSFragment mQSFragment;
+ @Mock private ViewGroup mQsHeader;
+ @Mock private ViewParent mViewParent;
+ @Mock private ViewTreeObserver mViewTreeObserver;
@Mock private KeyguardBottomAreaViewModel mKeyguardBottomAreaViewModel;
@Mock private KeyguardBottomAreaInteractor mKeyguardBottomAreaInteractor;
- private NotificationPanelViewController.PanelEventsEmitter mPanelEventsEmitter;
- private Optional<SysUIUnfoldComponent> mSysUIUnfoldComponent = Optional.empty();
+
+ private NotificationPanelViewController.TouchHandler mTouchHandler;
+ private ConfigurationController mConfigurationController;
private SysuiStatusBarStateController mStatusBarStateController;
private NotificationPanelViewController mNotificationPanelViewController;
private View.AccessibilityDelegate mAccessibiltyDelegate;
private NotificationsQuickSettingsContainer mNotificationContainerParent;
private List<View.OnAttachStateChangeListener> mOnAttachStateChangeListeners;
- private FalsingManagerFake mFalsingManager = new FalsingManagerFake();
- private FakeExecutor mExecutor = new FakeExecutor(new FakeSystemClock());
private Handler mMainHandler;
+ private View.OnLayoutChangeListener mLayoutChangeListener;
+
+ private final FalsingManagerFake mFalsingManager = new FalsingManagerFake();
+ private final Optional<SysUIUnfoldComponent> mSysUIUnfoldComponent = Optional.empty();
+ private final DisplayMetrics mDisplayMetrics = new DisplayMetrics();
private final PanelExpansionStateManager mPanelExpansionStateManager =
new PanelExpansionStateManager();
- private SystemClock mSystemClock;
+ private FragmentHostManager.FragmentListener mFragmentListener;
@Before
public void setup() {
MockitoAnnotations.initMocks(this);
- mSystemClock = new FakeSystemClock();
+ SystemClock systemClock = new FakeSystemClock();
mStatusBarStateController = new StatusBarStateControllerImpl(mUiEventLogger, mDumpManager,
mInteractionJankMonitor);
- mKeyguardStatusView = new KeyguardStatusView(mContext);
- mKeyguardStatusView.setId(R.id.keyguard_status_view);
+ KeyguardStatusView keyguardStatusView = new KeyguardStatusView(mContext);
+ keyguardStatusView.setId(R.id.keyguard_status_view);
DejankUtils.setImmediate(true);
when(mAuthController.isUdfpsEnrolled(anyInt())).thenReturn(false);
when(mHeadsUpCallback.getContext()).thenReturn(mContext);
when(mView.getResources()).thenReturn(mResources);
+ when(mView.getWidth()).thenReturn(PANEL_WIDTH);
when(mResources.getConfiguration()).thenReturn(mConfiguration);
mConfiguration.orientation = ORIENTATION_PORTRAIT;
when(mResources.getDisplayMetrics()).thenReturn(mDisplayMetrics);
@@ -431,7 +339,7 @@
when(mView.findViewById(R.id.keyguard_status_view))
.thenReturn(mock(KeyguardStatusView.class));
mNotificationContainerParent = new NotificationsQuickSettingsContainer(getContext(), null);
- mNotificationContainerParent.addView(mKeyguardStatusView);
+ mNotificationContainerParent.addView(keyguardStatusView);
mNotificationContainerParent.onFinishInflate();
when(mView.findViewById(R.id.notification_container_parent))
.thenReturn(mNotificationContainerParent);
@@ -447,7 +355,12 @@
when(mKeyguardUserSwitcherComponent.getKeyguardUserSwitcherController())
.thenReturn(mKeyguardUserSwitcherController);
when(mScreenOffAnimationController.shouldAnimateClockChange()).thenReturn(true);
-
+ when(mQs.getView()).thenReturn(mView);
+ when(mQSFragment.getView()).thenReturn(mView);
+ doAnswer(invocation -> {
+ mFragmentListener = invocation.getArgument(1);
+ return null;
+ }).when(mFragmentHostManager).addTagListener(eq(QS.TAG), any());
doAnswer((Answer<Void>) invocation -> {
mTouchHandler = invocation.getArgument(0);
return null;
@@ -484,7 +397,7 @@
when(mKeyguardStatusBarViewComponent.getKeyguardStatusBarViewController())
.thenReturn(mKeyguardStatusBarViewController);
when(mLayoutInflater.inflate(eq(R.layout.keyguard_status_view), any(), anyBoolean()))
- .thenReturn(mKeyguardStatusView);
+ .thenReturn(keyguardStatusView);
when(mLayoutInflater.inflate(eq(R.layout.keyguard_user_switcher), any(), anyBoolean()))
.thenReturn(mUserSwitcherView);
when(mLayoutInflater.inflate(eq(R.layout.keyguard_bottom_area), any(), anyBoolean()))
@@ -499,13 +412,18 @@
((Runnable) invocation.getArgument(0)).run();
return null;
}).when(mNotificationShadeWindowController).batchApplyWindowLayoutParams(any());
+ doAnswer(invocation -> {
+ mLayoutChangeListener = invocation.getArgument(0);
+ return null;
+ }).when(mView).addOnLayoutChangeListener(any());
when(mView.getViewTreeObserver()).thenReturn(mViewTreeObserver);
when(mView.getParent()).thenReturn(mViewParent);
when(mQs.getHeader()).thenReturn(mQsHeader);
mMainHandler = new Handler(Looper.getMainLooper());
- mPanelEventsEmitter = new NotificationPanelViewController.PanelEventsEmitter();
+ NotificationPanelViewController.PanelEventsEmitter panelEventsEmitter =
+ new NotificationPanelViewController.PanelEventsEmitter();
mNotificationPanelViewController = new NotificationPanelViewController(
mView,
@@ -560,11 +478,11 @@
() -> mKeyguardBottomAreaViewController,
mKeyguardUnlockAnimationController,
mNotificationListContainer,
- mPanelEventsEmitter,
+ panelEventsEmitter,
mNotificationStackSizeCalculator,
mUnlockedScreenOffAnimationController,
mShadeTransitionController,
- mSystemClock,
+ systemClock,
mock(CameraGestureHelper.class),
mKeyguardBottomAreaViewModel,
mKeyguardBottomAreaInteractor);
@@ -1481,6 +1399,96 @@
assertThat(maxPanelHeight).isNotEqualTo(splitShadeFullTransitionDistance);
}
+ @Test
+ public void onLayoutChange_fullWidth_updatesQSWithFullWithTrue() {
+ mNotificationPanelViewController.mQs = mQs;
+
+ setIsFullWidth(true);
+
+ verify(mQs).setIsNotificationPanelFullWidth(true);
+ }
+
+ @Test
+ public void onLayoutChange_notFullWidth_updatesQSWithFullWithFalse() {
+ mNotificationPanelViewController.mQs = mQs;
+
+ setIsFullWidth(false);
+
+ verify(mQs).setIsNotificationPanelFullWidth(false);
+ }
+
+ @Test
+ public void onLayoutChange_qsNotSet_doesNotCrash() {
+ mNotificationPanelViewController.mQs = null;
+
+ triggerLayoutChange();
+ }
+
+ @Test
+ public void onQsFragmentAttached_fullWidth_setsFullWidthTrueOnQS() {
+ setIsFullWidth(true);
+ givenViewAttached();
+ mFragmentListener.onFragmentViewCreated(QS.TAG, mQSFragment);
+
+ verify(mQSFragment).setIsNotificationPanelFullWidth(true);
+ }
+
+ @Test
+ public void onQsFragmentAttached_notFullWidth_setsFullWidthFalseOnQS() {
+ setIsFullWidth(false);
+ givenViewAttached();
+ mFragmentListener.onFragmentViewCreated(QS.TAG, mQSFragment);
+
+ verify(mQSFragment).setIsNotificationPanelFullWidth(false);
+ }
+
+ @Test
+ public void setQsExpansion_lockscreenShadeTransitionInProgress_usesLockscreenSquishiness() {
+ float squishinessFraction = 0.456f;
+ mNotificationPanelViewController.mQs = mQs;
+ when(mLockscreenShadeTransitionController.getQsSquishTransitionFraction())
+ .thenReturn(squishinessFraction);
+ when(mNotificationStackScrollLayoutController.getNotificationSquishinessFraction())
+ .thenReturn(0.987f);
+ // Call setTransitionToFullShadeAmount to get into the full shade transition in progress
+ // state.
+ mNotificationPanelViewController.setTransitionToFullShadeAmount(
+ /* pxAmount= */ 234,
+ /* animate= */ false,
+ /* delay= */ 0
+ );
+
+ mNotificationPanelViewController.setQsExpansion(/* height= */ 123);
+
+ // First for setTransitionToFullShadeAmount and then setQsExpansion
+ verify(mQs, times(2)).setQsExpansion(
+ /* expansion= */ anyFloat(),
+ /* panelExpansionFraction= */ anyFloat(),
+ /* proposedTranslation= */ anyFloat(),
+ eq(squishinessFraction)
+ );
+ }
+
+ @Test
+ public void setQsExpansion_lockscreenShadeTransitionNotInProgress_usesStandardSquishiness() {
+ float lsSquishinessFraction = 0.456f;
+ float nsslSquishinessFraction = 0.987f;
+ mNotificationPanelViewController.mQs = mQs;
+ when(mLockscreenShadeTransitionController.getQsSquishTransitionFraction())
+ .thenReturn(lsSquishinessFraction);
+ when(mNotificationStackScrollLayoutController.getNotificationSquishinessFraction())
+ .thenReturn(nsslSquishinessFraction);
+
+ mNotificationPanelViewController.setQsExpansion(/* height= */ 123);
+
+ verify(mQs).setQsExpansion(
+ /* expansion= */ anyFloat(),
+ /* panelExpansionFraction= */ anyFloat(),
+ /* proposedTranslation= */ anyFloat(),
+ eq(nsslSquishinessFraction)
+ );
+ }
+
private static MotionEvent createMotionEvent(int x, int y, int action) {
return MotionEvent.obtain(
/* downTime= */ 0, /* eventTime= */ 0, action, x, y, /* metaState= */ 0);
@@ -1504,12 +1512,6 @@
}
}
- private void givenViewDetached() {
- for (View.OnAttachStateChangeListener listener : mOnAttachStateChangeListeners) {
- listener.onViewDetachedFromWindow(mView);
- }
- }
-
private ConstraintSet.Layout getConstraintSetLayout(@IdRes int id) {
ConstraintSet constraintSet = new ConstraintSet();
constraintSet.clone(mNotificationContainerParent);
@@ -1566,4 +1568,24 @@
assertThat(getConstraintSetLayout(R.id.keyguard_status_view).endToEnd).isEqualTo(
R.id.qs_edge_guideline);
}
+
+ private void setIsFullWidth(boolean fullWidth) {
+ float nsslWidth = fullWidth ? PANEL_WIDTH : PANEL_WIDTH / 2f;
+ when(mNotificationStackScrollLayoutController.getWidth()).thenReturn(nsslWidth);
+ triggerLayoutChange();
+ }
+
+ private void triggerLayoutChange() {
+ mLayoutChangeListener.onLayoutChange(
+ mView,
+ /* left= */ 0,
+ /* top= */ 0,
+ /* right= */ 0,
+ /* bottom= */ 0,
+ /* oldLeft= */ 0,
+ /* oldTop= */ 0,
+ /* oldRight= */ 0,
+ /* oldBottom= */ 0
+ );
+ }
}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/LockscreenShadeQsTransitionControllerTest.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/LockscreenShadeQsTransitionControllerTest.kt
new file mode 100644
index 0000000..7041262
--- /dev/null
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/LockscreenShadeQsTransitionControllerTest.kt
@@ -0,0 +1,255 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.statusbar
+
+import android.testing.AndroidTestingRunner
+import androidx.test.filters.SmallTest
+import com.android.systemui.R
+import com.android.systemui.SysuiTestCase
+import com.android.systemui.dump.DumpManager
+import com.android.systemui.plugins.qs.QS
+import com.android.systemui.statusbar.policy.FakeConfigurationController
+import com.google.common.truth.Expect
+import com.google.common.truth.Truth.assertThat
+import org.junit.Before
+import org.junit.Rule
+import org.junit.Test
+import org.junit.runner.RunWith
+import org.mockito.Mock
+import org.mockito.Mockito.verify
+import org.mockito.MockitoAnnotations
+
+@SmallTest
+@RunWith(AndroidTestingRunner::class)
+class LockscreenShadeQsTransitionControllerTest : SysuiTestCase() {
+
+ private val configurationController = FakeConfigurationController()
+
+ @get:Rule val expect: Expect = Expect.create()
+
+ @Mock private lateinit var dumpManager: DumpManager
+ @Mock private lateinit var qS: QS
+
+ private lateinit var controller: LockscreenShadeQsTransitionController
+
+ @Before
+ fun setUp() {
+ MockitoAnnotations.initMocks(this)
+ setTransitionDistance(TRANSITION_DISTANCE)
+ setTransitionDelay(TRANSITION_DELAY)
+ setSquishTransitionDistance(SQUISH_TRANSITION_DISTANCE)
+ setSquishStartFraction(SQUISH_START_FRACTION)
+
+ controller =
+ LockscreenShadeQsTransitionController(
+ context,
+ configurationController,
+ dumpManager,
+ qsProvider = { qS }
+ )
+ }
+
+ @Test
+ fun qsTransitionFraction_byDefault_returns0() {
+ assertThat(controller.qsTransitionFraction).isZero()
+ }
+
+ @Test
+ fun qsTransitionFraction_noStartDelay_returnsBasedOnTransitionDistance() {
+ setTransitionDelay(0)
+ setTransitionDistance(100)
+
+ controller.dragDownAmount = 25f
+ expect.that(controller.qsTransitionFraction).isEqualTo(0.25f)
+
+ controller.dragDownAmount = 50f
+ expect.that(controller.qsTransitionFraction).isEqualTo(0.5f)
+
+ controller.dragDownAmount = 75f
+ expect.that(controller.qsTransitionFraction).isEqualTo(0.75f)
+
+ controller.dragDownAmount = 100f
+ expect.that(controller.qsTransitionFraction).isEqualTo(1f)
+ }
+
+ @Test
+ fun qsTransitionFraction_noStartDelay_returnsValuesBetween0and1() {
+ setTransitionDelay(0)
+ setTransitionDistance(100)
+
+ controller.dragDownAmount = -500f
+ expect.that(controller.qsTransitionFraction).isEqualTo(0f)
+
+ controller.dragDownAmount = 500f
+ expect.that(controller.qsTransitionFraction).isEqualTo(1f)
+ }
+
+ @Test
+ fun qsTransitionFraction_withStartDelay_returnsBasedOnTransitionDistanceAndDelay() {
+ setTransitionDelay(10)
+ setTransitionDistance(100)
+
+ controller.dragDownAmount = 0f
+ expect.that(controller.qsTransitionFraction).isEqualTo(0f)
+
+ controller.dragDownAmount = 10f
+ expect.that(controller.qsTransitionFraction).isEqualTo(0f)
+
+ controller.dragDownAmount = 25f
+ expect.that(controller.qsTransitionFraction).isEqualTo(0.15f)
+
+ controller.dragDownAmount = 100f
+ expect.that(controller.qsTransitionFraction).isEqualTo(0.9f)
+
+ controller.dragDownAmount = 110f
+ expect.that(controller.qsTransitionFraction).isEqualTo(1f)
+ }
+
+ @Test
+ fun qsTransitionFraction_withStartDelay_returnsValuesBetween0and1() {
+ setTransitionDelay(10)
+ setTransitionDistance(100)
+
+ controller.dragDownAmount = -500f
+ expect.that(controller.qsTransitionFraction).isEqualTo(0f)
+
+ controller.dragDownAmount = 500f
+ expect.that(controller.qsTransitionFraction).isEqualTo(1f)
+ }
+
+ @Test
+ fun qsSquishTransitionFraction_byDefault_returnsValueSetFromResource() {
+ assertThat(controller.qsSquishTransitionFraction).isEqualTo(SQUISH_START_FRACTION)
+ }
+
+ @Test
+ fun qsSquishTransitionFraction_noStartDelay_startFraction0_returnsBasedOnTransitionDistance() {
+ setTransitionDelay(0)
+ setSquishStartFraction(0f)
+ setSquishTransitionDistance(1000)
+
+ controller.dragDownAmount = 250f
+ expect.that(controller.qsSquishTransitionFraction).isEqualTo(0.25f)
+
+ controller.dragDownAmount = 500f
+ expect.that(controller.qsSquishTransitionFraction).isEqualTo(0.5f)
+
+ controller.dragDownAmount = 750f
+ expect.that(controller.qsSquishTransitionFraction).isEqualTo(0.75f)
+
+ controller.dragDownAmount = 1000f
+ expect.that(controller.qsSquishTransitionFraction).isEqualTo(1f)
+ }
+
+ @Test
+ fun qsSquishTransitionFraction_startDelay_startFraction0_basedOnTransitionDistanceAndDelay() {
+ setTransitionDelay(100)
+ setSquishStartFraction(0f)
+ setSquishTransitionDistance(1000)
+
+ controller.dragDownAmount = 250f
+ expect.that(controller.qsSquishTransitionFraction).isEqualTo(0.15f)
+
+ controller.dragDownAmount = 500f
+ expect.that(controller.qsSquishTransitionFraction).isEqualTo(0.4f)
+
+ controller.dragDownAmount = 750f
+ expect.that(controller.qsSquishTransitionFraction).isEqualTo(0.65f)
+
+ controller.dragDownAmount = 1000f
+ expect.that(controller.qsSquishTransitionFraction).isEqualTo(0.9f)
+
+ controller.dragDownAmount = 1100f
+ expect.that(controller.qsSquishTransitionFraction).isEqualTo(1f)
+ }
+
+ @Test
+ fun qsSquishTransitionFraction_noStartDelay_startFractionSet_returnsBasedOnStartAndDistance() {
+ setTransitionDelay(0)
+ setSquishStartFraction(0.5f)
+ setSquishTransitionDistance(1000)
+
+ controller.dragDownAmount = 0f
+ expect.that(controller.qsSquishTransitionFraction).isEqualTo(0.5f)
+
+ controller.dragDownAmount = 500f
+ expect.that(controller.qsSquishTransitionFraction).isEqualTo(0.75f)
+
+ controller.dragDownAmount = 1000f
+ expect.that(controller.qsSquishTransitionFraction).isEqualTo(1f)
+ }
+
+ @Test
+ fun qsSquishTransitionFraction_startDelay_startFractionSet_basedOnStartAndDistanceAndDelay() {
+ setTransitionDelay(10)
+ setSquishStartFraction(0.5f)
+ setSquishTransitionDistance(100)
+
+ controller.dragDownAmount = 0f
+ expect.that(controller.qsSquishTransitionFraction).isEqualTo(0.5f)
+
+ controller.dragDownAmount = 50f
+ expect.that(controller.qsSquishTransitionFraction).isEqualTo(0.7f)
+
+ controller.dragDownAmount = 100f
+ expect.that(controller.qsSquishTransitionFraction).isEqualTo(0.95f)
+
+ controller.dragDownAmount = 110f
+ expect.that(controller.qsSquishTransitionFraction).isEqualTo(1f)
+ }
+
+ @Test
+ fun onDragDownAmountChanged_setsValuesOnQS() {
+ val rawDragAmount = 200f
+
+ controller.dragDownAmount = rawDragAmount
+
+ verify(qS)
+ .setTransitionToFullShadeProgress(
+ /* isTransitioningToFullShade= */ true,
+ /* transitionFraction= */ controller.qsTransitionFraction,
+ /* squishinessFraction= */ controller.qsSquishTransitionFraction
+ )
+ }
+
+ private fun setTransitionDistance(value: Int) {
+ overrideResource(R.dimen.lockscreen_shade_qs_transition_distance, value)
+ configurationController.notifyConfigurationChanged()
+ }
+
+ private fun setTransitionDelay(value: Int) {
+ overrideResource(R.dimen.lockscreen_shade_qs_transition_delay, value)
+ configurationController.notifyConfigurationChanged()
+ }
+
+ private fun setSquishTransitionDistance(value: Int) {
+ overrideResource(R.dimen.lockscreen_shade_qs_squish_transition_distance, value)
+ configurationController.notifyConfigurationChanged()
+ }
+
+ private fun setSquishStartFraction(value: Float) {
+ overrideResource(R.dimen.lockscreen_shade_qs_squish_start_fraction, value)
+ configurationController.notifyConfigurationChanged()
+ }
+
+ companion object {
+ private const val TRANSITION_DELAY = 123
+ private const val TRANSITION_DISTANCE = 321
+ private const val SQUISH_START_FRACTION = 0.123f
+ private const val SQUISH_TRANSITION_DISTANCE = 456
+ }
+}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/LockscreenShadeTransitionControllerTest.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/LockscreenShadeTransitionControllerTest.kt
index fe1cd97..8643e86 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/LockscreenShadeTransitionControllerTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/LockscreenShadeTransitionControllerTest.kt
@@ -1,9 +1,9 @@
package com.android.systemui.statusbar
-import android.test.suitebuilder.annotation.SmallTest
import android.testing.AndroidTestingRunner
import android.testing.TestableLooper
import android.testing.TestableLooper.RunWithLooper
+import androidx.test.filters.SmallTest
import com.android.systemui.ExpandHelper
import com.android.systemui.R
import com.android.systemui.SysuiTestCase
@@ -78,6 +78,7 @@
@Mock lateinit var qS: QS
@Mock lateinit var singleShadeOverScroller: SingleShadeLockScreenOverScroller
@Mock lateinit var splitShadeOverScroller: SplitShadeLockScreenOverScroller
+ @Mock lateinit var qsTransitionController: LockscreenShadeQsTransitionController
@JvmField @Rule val mockito = MockitoJUnit.rule()
private val configurationController = FakeConfigurationController()
@@ -120,7 +121,9 @@
context,
configurationController,
dumpManager)
- })
+ },
+ qsTransitionControllerFactory = { qsTransitionController },
+ )
whenever(nsslController.view).thenReturn(stackscroller)
whenever(nsslController.expandHelperCallback).thenReturn(expandHelperCallback)
transitionController.notificationPanelController = notificationPanelController
@@ -249,7 +252,7 @@
verify(scrimController, never()).setTransitionToFullShadeProgress(anyFloat(), anyFloat())
verify(notificationPanelController, never()).setTransitionToFullShadeAmount(anyFloat(),
anyBoolean(), anyLong())
- verify(qS, never()).setTransitionToFullShadeAmount(anyFloat(), anyFloat())
+ verify(qsTransitionController, never()).dragDownAmount = anyFloat()
}
@Test
@@ -260,7 +263,7 @@
verify(scrimController).setTransitionToFullShadeProgress(anyFloat(), anyFloat())
verify(notificationPanelController).setTransitionToFullShadeAmount(anyFloat(),
anyBoolean(), anyLong())
- verify(qS).setTransitionToFullShadeAmount(anyFloat(), anyFloat())
+ verify(qsTransitionController).dragDownAmount = 10f
verify(depthController).transitionToFullShadeProgress = anyFloat()
}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/ScrimControllerTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/ScrimControllerTest.java
index 7cd275d..4d1a52c 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/ScrimControllerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/ScrimControllerTest.java
@@ -59,16 +59,19 @@
import com.android.systemui.dock.DockManager;
import com.android.systemui.keyguard.KeyguardUnlockAnimationController;
import com.android.systemui.scrim.ScrimView;
-import com.android.systemui.statusbar.policy.ConfigurationController;
+import com.android.systemui.statusbar.policy.FakeConfigurationController;
import com.android.systemui.statusbar.policy.KeyguardStateController;
import com.android.systemui.util.concurrency.FakeExecutor;
import com.android.systemui.util.time.FakeSystemClock;
import com.android.systemui.util.wakelock.DelayedWakeLock;
import com.android.systemui.utils.os.FakeHandler;
+import com.google.common.truth.Expect;
+
import org.junit.After;
import org.junit.Assert;
import org.junit.Before;
+import org.junit.Rule;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Mock;
@@ -86,6 +89,11 @@
@SmallTest
public class ScrimControllerTest extends SysuiTestCase {
+ @Rule public Expect mExpect = Expect.create();
+
+ private final FakeConfigurationController mConfigurationController =
+ new FakeConfigurationController();
+
private ScrimController mScrimController;
private ScrimView mScrimBehind;
private ScrimView mNotificationsScrim;
@@ -96,32 +104,19 @@
private int mScrimVisibility;
private boolean mAlwaysOnEnabled;
private TestableLooper mLooper;
- @Mock
- private AlarmManager mAlarmManager;
- @Mock
- private DozeParameters mDozeParameters;
- @Mock
- LightBarController mLightBarController;
- @Mock
- DelayedWakeLock.Builder mDelayedWakeLockBuilder;
- @Mock
- private DelayedWakeLock mWakeLock;
- @Mock
- KeyguardStateController mKeyguardStateController;
- @Mock
- KeyguardUpdateMonitor mKeyguardUpdateMonitor;
- @Mock
- private DockManager mDockManager;
- @Mock
- private ConfigurationController mConfigurationController;
- @Mock
- private ScreenOffAnimationController mScreenOffAnimationController;
- @Mock
- private KeyguardUnlockAnimationController mKeyguardUnlockAnimationController;
+ @Mock private AlarmManager mAlarmManager;
+ @Mock private DozeParameters mDozeParameters;
+ @Mock private LightBarController mLightBarController;
+ @Mock private DelayedWakeLock.Builder mDelayedWakeLockBuilder;
+ @Mock private DelayedWakeLock mWakeLock;
+ @Mock private KeyguardStateController mKeyguardStateController;
+ @Mock private KeyguardUpdateMonitor mKeyguardUpdateMonitor;
+ @Mock private DockManager mDockManager;
+ @Mock private ScreenOffAnimationController mScreenOffAnimationController;
+ @Mock private KeyguardUnlockAnimationController mKeyguardUnlockAnimationController;
// TODO(b/204991468): Use a real PanelExpansionStateManager object once this bug is fixed. (The
// event-dispatch-on-registration pattern caused some of these unit tests to fail.)
- @Mock
- private StatusBarKeyguardViewManager mStatusBarKeyguardViewManager;
+ @Mock private StatusBarKeyguardViewManager mStatusBarKeyguardViewManager;
private static class AnimatorListener implements Animator.AnimatorListener {
private int mNumStarts;
@@ -1450,6 +1445,41 @@
}
@Test
+ public void notificationAlpha_qsNotClipped_alphaMatchesNotificationExpansionProgress() {
+ mScrimController.setClipsQsScrim(false);
+ mScrimController.transitionTo(ScrimState.KEYGUARD);
+ // RawPanelExpansion and QsExpansion are usually used for the notification alpha
+ // calculation.
+ // Here we set them to non-zero values explicitly to make sure that in not clipped mode,
+ // they are not being used even when set.
+ mScrimController.setRawPanelExpansionFraction(0.5f);
+ mScrimController.setQsPosition(/* expansionFraction= */ 0.5f, /* qsPanelBottomY= */ 500);
+ finishAnimationsImmediately();
+
+ float progress = 0.5f;
+
+ float notificationExpansionProgress = 0f;
+ mScrimController.setTransitionToFullShadeProgress(progress, notificationExpansionProgress);
+ mExpect.that(mNotificationsScrim.getViewAlpha()).isEqualTo(notificationExpansionProgress);
+
+ notificationExpansionProgress = 0.25f;
+ mScrimController.setTransitionToFullShadeProgress(progress, notificationExpansionProgress);
+ mExpect.that(mNotificationsScrim.getViewAlpha()).isEqualTo(notificationExpansionProgress);
+
+ notificationExpansionProgress = 0.5f;
+ mScrimController.setTransitionToFullShadeProgress(progress, notificationExpansionProgress);
+ mExpect.that(mNotificationsScrim.getViewAlpha()).isEqualTo(notificationExpansionProgress);
+
+ notificationExpansionProgress = 0.75f;
+ mScrimController.setTransitionToFullShadeProgress(progress, notificationExpansionProgress);
+ mExpect.that(mNotificationsScrim.getViewAlpha()).isEqualTo(notificationExpansionProgress);
+
+ notificationExpansionProgress = 1f;
+ mScrimController.setTransitionToFullShadeProgress(progress, notificationExpansionProgress);
+ mExpect.that(mNotificationsScrim.getViewAlpha()).isEqualTo(notificationExpansionProgress);
+ }
+
+ @Test
public void setNotificationsOverScrollAmount_setsTranslationYOnNotificationsScrim() {
int overScrollAmount = 10;
diff --git a/packages/SystemUI/tests/src/com/android/systemui/ImageWallpaperTest.java b/packages/SystemUI/tests/src/com/android/systemui/wallpapers/ImageWallpaperTest.java
similarity index 97%
rename from packages/SystemUI/tests/src/com/android/systemui/ImageWallpaperTest.java
rename to packages/SystemUI/tests/src/com/android/systemui/wallpapers/ImageWallpaperTest.java
index e1ddaad..e47acd8 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/ImageWallpaperTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/wallpapers/ImageWallpaperTest.java
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-package com.android.systemui;
+package com.android.systemui.wallpapers;
import static com.google.common.truth.Truth.assertWithMessage;
@@ -40,7 +40,8 @@
import android.view.DisplayInfo;
import android.view.SurfaceHolder;
-import com.android.systemui.glwallpaper.ImageWallpaperRenderer;
+import com.android.systemui.SysuiTestCase;
+import com.android.systemui.wallpapers.gl.ImageWallpaperRenderer;
import org.junit.Before;
import org.junit.Ignore;
diff --git a/packages/SystemUI/tests/src/com/android/systemui/glwallpaper/EglHelperTest.java b/packages/SystemUI/tests/src/com/android/systemui/wallpapers/gl/EglHelperTest.java
similarity index 98%
rename from packages/SystemUI/tests/src/com/android/systemui/glwallpaper/EglHelperTest.java
rename to packages/SystemUI/tests/src/com/android/systemui/wallpapers/gl/EglHelperTest.java
index a3221b5..a42bade 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/glwallpaper/EglHelperTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/wallpapers/gl/EglHelperTest.java
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-package com.android.systemui.glwallpaper;
+package com.android.systemui.wallpapers.gl;
import static com.google.common.truth.Truth.assertThat;
diff --git a/packages/SystemUI/tests/src/com/android/systemui/glwallpaper/ImageWallpaperRendererTest.java b/packages/SystemUI/tests/src/com/android/systemui/wallpapers/gl/ImageWallpaperRendererTest.java
similarity index 98%
rename from packages/SystemUI/tests/src/com/android/systemui/glwallpaper/ImageWallpaperRendererTest.java
rename to packages/SystemUI/tests/src/com/android/systemui/wallpapers/gl/ImageWallpaperRendererTest.java
index 510b907..89b2222 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/glwallpaper/ImageWallpaperRendererTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/wallpapers/gl/ImageWallpaperRendererTest.java
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-package com.android.systemui.glwallpaper;
+package com.android.systemui.wallpapers.gl;
import static com.google.common.truth.Truth.assertThat;
diff --git a/services/core/java/android/content/pm/PackageManagerInternal.java b/services/core/java/android/content/pm/PackageManagerInternal.java
index bd1ecb2..7ca6254 100644
--- a/services/core/java/android/content/pm/PackageManagerInternal.java
+++ b/services/core/java/android/content/pm/PackageManagerInternal.java
@@ -48,8 +48,7 @@
import com.android.server.pm.PackageList;
import com.android.server.pm.PackageSetting;
import com.android.server.pm.dex.DynamicCodeLogger;
-import com.android.server.pm.parsing.pkg.AndroidPackage;
-import com.android.server.pm.pkg.AndroidPackageApi;
+import com.android.server.pm.pkg.AndroidPackage;
import com.android.server.pm.pkg.PackageStateInternal;
import com.android.server.pm.pkg.SharedUserApi;
import com.android.server.pm.pkg.component.ParsedMainComponent;
@@ -644,7 +643,7 @@
* Returns the {@link SystemApi} variant of a package for use with mainline.
*/
@Nullable
- public abstract AndroidPackageApi getAndroidPackage(@NonNull String packageName);
+ public abstract AndroidPackage getAndroidPackage(@NonNull String packageName);
@Nullable
public abstract PackageStateInternal getPackageStateInternal(@NonNull String packageName);
diff --git a/services/core/java/com/android/server/am/ActivityManagerService.java b/services/core/java/com/android/server/am/ActivityManagerService.java
index 26899f1..6e52d21 100644
--- a/services/core/java/com/android/server/am/ActivityManagerService.java
+++ b/services/core/java/com/android/server/am/ActivityManagerService.java
@@ -407,8 +407,8 @@
import com.android.server.pm.Computer;
import com.android.server.pm.Installer;
import com.android.server.pm.UserManagerInternal;
-import com.android.server.pm.parsing.pkg.AndroidPackage;
import com.android.server.pm.permission.PermissionManagerServiceInternal;
+import com.android.server.pm.pkg.AndroidPackage;
import com.android.server.pm.pkg.SELinuxUtil;
import com.android.server.pm.pkg.parsing.ParsingPackageUtils;
import com.android.server.pm.snapshot.PackageDataSnapshot;
@@ -16145,8 +16145,7 @@
@Override
public boolean startUserInBackgroundOnSecondaryDisplay(int userId, int displayId) {
// Permission check done inside UserController.
- return mUserController.startUserOnSecondaryDisplay(userId, displayId,
- /* unlockListener= */ null);
+ return mUserController.startUserOnSecondaryDisplay(userId, displayId);
}
/**
diff --git a/services/core/java/com/android/server/am/ContentProviderHelper.java b/services/core/java/com/android/server/am/ContentProviderHelper.java
index a36c298..86c9770 100644
--- a/services/core/java/com/android/server/am/ContentProviderHelper.java
+++ b/services/core/java/com/android/server/am/ContentProviderHelper.java
@@ -81,7 +81,7 @@
import com.android.server.LocalServices;
import com.android.server.RescueParty;
import com.android.server.pm.UserManagerInternal;
-import com.android.server.pm.parsing.pkg.AndroidPackage;
+import com.android.server.pm.pkg.AndroidPackage;
import java.io.FileDescriptor;
import java.io.PrintWriter;
diff --git a/services/core/java/com/android/server/am/ProcessList.java b/services/core/java/com/android/server/am/ProcessList.java
index affb084..992d416 100644
--- a/services/core/java/com/android/server/am/ProcessList.java
+++ b/services/core/java/com/android/server/am/ProcessList.java
@@ -133,7 +133,7 @@
import com.android.server.Watchdog;
import com.android.server.am.ActivityManagerService.ProcessChangeItem;
import com.android.server.compat.PlatformCompat;
-import com.android.server.pm.parsing.pkg.AndroidPackage;
+import com.android.server.pm.pkg.AndroidPackage;
import com.android.server.pm.pkg.PackageStateInternal;
import com.android.server.wm.ActivityServiceConnectionsHolder;
import com.android.server.wm.WindowManagerService;
@@ -2200,16 +2200,25 @@
Map<String, Pair<String, Long>> allowlistedAppDataInfoMap;
boolean bindMountAppStorageDirs = false;
boolean bindMountAppsData = mAppDataIsolationEnabled
- && (UserHandle.isApp(app.uid) || UserHandle.isIsolated(app.uid))
+ && (UserHandle.isApp(app.uid) || UserHandle.isIsolated(app.uid)
+ || app.isSdkSandbox)
&& mPlatformCompat.isChangeEnabled(APP_DATA_DIRECTORY_ISOLATION, app.info);
// Get all packages belongs to the same shared uid. sharedPackages is empty array
// if it doesn't have shared uid.
final PackageManagerInternal pmInt = mService.getPackageManagerInternal();
- final String[] sharedPackages = pmInt.getSharedUserPackagesForPackage(
- app.info.packageName, app.userId);
- final String[] targetPackagesList = sharedPackages.length == 0
- ? new String[]{app.info.packageName} : sharedPackages;
+
+ // In the case of sdk sandbox, the pkgDataInfoMap of only the client app associated with
+ // the sandbox is required to handle app visibility restrictions for the sandbox.
+ final String[] targetPackagesList;
+ if (app.isSdkSandbox) {
+ targetPackagesList = new String[]{app.sdkSandboxClientAppPackage};
+ } else {
+ final String[] sharedPackages = pmInt.getSharedUserPackagesForPackage(
+ app.info.packageName, app.userId);
+ targetPackagesList = sharedPackages.length == 0
+ ? new String[]{app.info.packageName} : sharedPackages;
+ }
final boolean hasAppStorage = hasAppStorage(pmInt, app.info.packageName);
@@ -2235,7 +2244,7 @@
bindMountAppsData = false;
}
- if (!hasAppStorage) {
+ if (!hasAppStorage && !app.isSdkSandbox) {
bindMountAppsData = false;
pkgDataInfoMap = null;
allowlistedAppDataInfoMap = null;
diff --git a/services/core/java/com/android/server/am/UserController.java b/services/core/java/com/android/server/am/UserController.java
index 043da55..1954f76 100644
--- a/services/core/java/com/android/server/am/UserController.java
+++ b/services/core/java/com/android/server/am/UserController.java
@@ -1375,8 +1375,9 @@
}
final int profilesToStartSize = profilesToStart.size();
int i = 0;
- // TODO(b/239982558): pass displayId
for (; i < profilesToStartSize && i < (getMaxRunningUsers() - 1); ++i) {
+ // NOTE: this method is setting the profiles of the current user - which is always
+ // assigned to the default display - so there's no need to pass PARENT_DISPLAY
startUser(profilesToStart.get(i).id, /* foreground= */ false);
}
if (i < profilesToStartSize) {
@@ -1419,8 +1420,10 @@
return false;
}
- // TODO(b/239982558): pass proper displayId
- return startUserNoChecks(userId, Display.DEFAULT_DISPLAY, /* foreground= */ false,
+ int displayId = mInjector.isUsersOnSecondaryDisplaysEnabled()
+ ? UserManagerInternal.PARENT_DISPLAY
+ : Display.DEFAULT_DISPLAY;
+ return startUserNoChecks(userId, displayId, /* foreground= */ false,
/* unlockListener= */ null);
}
@@ -1472,8 +1475,7 @@
// TODO(b/239982558): add javadoc (need to wait until the intents / SystemService callbacks are
// defined
- boolean startUserOnSecondaryDisplay(@UserIdInt int userId, int displayId,
- @Nullable IProgressListener unlockListener) {
+ boolean startUserOnSecondaryDisplay(@UserIdInt int userId, int displayId) {
checkCallingHasOneOfThosePermissions("startUserOnSecondaryDisplay",
MANAGE_USERS, CREATE_USERS);
@@ -1482,7 +1484,8 @@
"Cannot use DEFAULT_DISPLAY");
try {
- return startUserNoChecks(userId, displayId, /* foreground= */ false, unlockListener);
+ return startUserNoChecks(userId, displayId, /* foreground= */ false,
+ /* unlockListener= */ null);
} catch (RuntimeException e) {
Slogf.w(TAG, "startUserOnSecondaryDisplay(%d, %d) failed: %s", userId, displayId, e);
return false;
@@ -1514,8 +1517,6 @@
Preconditions.checkArgument(!foreground, "Cannot start user %d in foreground AND "
+ "on secondary display (%d)", userId, displayId);
}
- mInjector.getUserManagerInternal().assignUserToDisplay(userId, displayId);
-
// TODO(b/239982558): log display id (or use a new event)
EventLog.writeEvent(EventLogTags.UC_START_USER_INTERNAL, userId);
@@ -1571,6 +1572,8 @@
return false;
}
+ mInjector.getUserManagerInternal().assignUserToDisplay(userId, displayId);
+
// TODO(b/239982558): might need something similar for bg users on secondary display
if (foreground && isUserSwitchUiEnabled()) {
t.traceBegin("startFreezingScreen");
@@ -3484,5 +3487,9 @@
}
}, reason);
}
+
+ boolean isUsersOnSecondaryDisplaysEnabled() {
+ return UserManager.isUsersOnSecondaryDisplaysEnabled();
+ }
}
}
diff --git a/services/core/java/com/android/server/am/UserState.java b/services/core/java/com/android/server/am/UserState.java
index 71a5511..4741849 100644
--- a/services/core/java/com/android/server/am/UserState.java
+++ b/services/core/java/com/android/server/am/UserState.java
@@ -35,18 +35,20 @@
public final class UserState {
private static final String TAG = TAG_WITH_CLASS_NAME ? "UserState" : TAG_AM;
+ // user doesn't exist.
+ public static final int STATE_NONE = -1;
// User is first coming up.
- public final static int STATE_BOOTING = 0;
+ public static final int STATE_BOOTING = 0;
// User is in the locked state.
- public final static int STATE_RUNNING_LOCKED = 1;
+ public static final int STATE_RUNNING_LOCKED = 1;
// User is in the unlocking state.
- public final static int STATE_RUNNING_UNLOCKING = 2;
+ public static final int STATE_RUNNING_UNLOCKING = 2;
// User is in the running state.
- public final static int STATE_RUNNING_UNLOCKED = 3;
+ public static final int STATE_RUNNING_UNLOCKED = 3;
// User is in the initial process of being stopped.
- public final static int STATE_STOPPING = 4;
+ public static final int STATE_STOPPING = 4;
// User is in the final phase of stopping, sending Intent.ACTION_SHUTDOWN.
- public final static int STATE_SHUTDOWN = 5;
+ public static final int STATE_SHUTDOWN = 5;
public final UserHandle mHandle;
public final ArrayList<IStopUserCallback> mStopCallbacks = new ArrayList<>();
diff --git a/services/core/java/com/android/server/appop/AppOpsService.java b/services/core/java/com/android/server/appop/AppOpsService.java
index 7bdcfdb..62ae9b8 100644
--- a/services/core/java/com/android/server/appop/AppOpsService.java
+++ b/services/core/java/com/android/server/appop/AppOpsService.java
@@ -177,7 +177,7 @@
import com.android.server.SystemServerInitThreadPool;
import com.android.server.SystemServiceManager;
import com.android.server.pm.PackageList;
-import com.android.server.pm.parsing.pkg.AndroidPackage;
+import com.android.server.pm.pkg.AndroidPackage;
import com.android.server.pm.pkg.component.ParsedAttribution;
import com.android.server.policy.AppOpsPolicy;
diff --git a/services/core/java/com/android/server/connectivity/Vpn.java b/services/core/java/com/android/server/connectivity/Vpn.java
index 9cb1f1d..431be88 100644
--- a/services/core/java/com/android/server/connectivity/Vpn.java
+++ b/services/core/java/com/android/server/connectivity/Vpn.java
@@ -1198,7 +1198,7 @@
mContext.unbindService(mConnection);
cleanupVpnStateLocked();
} else if (mVpnRunner != null) {
- stopVpnRunnerAndNotifyAppLocked(mPackage);
+ stopVpnRunnerAndNotifyAppLocked();
}
try {
@@ -4061,7 +4061,7 @@
}
@GuardedBy("this")
- private void stopVpnRunnerAndNotifyAppLocked(@NonNull String packageName) {
+ private void stopVpnRunnerAndNotifyAppLocked() {
// Build intent first because the sessionKey will be reset after performing
// VpnRunner.exit(). Also, cache mOwnerUID even if ownerUID will not be changed in
// VpnRunner.exit() to prevent design being changed in the future.
@@ -4069,17 +4069,17 @@
// ConnectivityServiceTest.
final int ownerUid = mOwnerUID;
Intent intent = null;
- if (SdkLevel.isAtLeastT() && isVpnApp(packageName)) {
+ if (SdkLevel.isAtLeastT() && isVpnApp(mPackage)) {
intent = buildVpnManagerEventIntent(
VpnManager.CATEGORY_EVENT_DEACTIVATED_BY_USER,
- -1 /* errorClass */, -1 /* errorCode*/, packageName,
+ -1 /* errorClass */, -1 /* errorCode*/, mPackage,
getSessionKeyLocked(), makeVpnProfileStateLocked(),
null /* underlyingNetwork */, null /* nc */, null /* lp */);
}
// cleanupVpnStateLocked() is called from mVpnRunner.exit()
mVpnRunner.exit();
- if (intent != null && isVpnApp(packageName)) {
- notifyVpnManagerVpnStopped(packageName, ownerUid, intent);
+ if (intent != null && isVpnApp(mPackage)) {
+ notifyVpnManagerVpnStopped(mPackage, ownerUid, intent);
}
}
@@ -4099,7 +4099,7 @@
// To stop the VPN profile, the caller must be the current prepared package and must be
// running an Ikev2VpnProfile.
if (isCurrentIkev2VpnLocked(packageName)) {
- stopVpnRunnerAndNotifyAppLocked(packageName);
+ stopVpnRunnerAndNotifyAppLocked();
}
}
diff --git a/services/core/java/com/android/server/inputmethod/InputMethodDeviceConfigs.java b/services/core/java/com/android/server/inputmethod/InputMethodDeviceConfigs.java
new file mode 100644
index 0000000..9d5393f
--- /dev/null
+++ b/services/core/java/com/android/server/inputmethod/InputMethodDeviceConfigs.java
@@ -0,0 +1,59 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server.inputmethod;
+
+import static android.provider.InputMethodManagerDeviceConfig.KEY_HIDE_IME_WHEN_NO_EDITOR_FOCUS;
+
+import android.app.ActivityThread;
+import android.provider.DeviceConfig;
+
+/**
+ * Class for the device-level configuration related to the input method manager
+ * platform features in {@link DeviceConfig}.
+ */
+public final class InputMethodDeviceConfigs {
+ private boolean mHideImeWhenNoEditorFocus;
+ private final DeviceConfig.OnPropertiesChangedListener mDeviceConfigChangedListener;
+
+ public InputMethodDeviceConfigs() {
+ mDeviceConfigChangedListener = properties -> {
+ if (!DeviceConfig.NAMESPACE_INPUT_METHOD_MANAGER.equals(properties.getNamespace())) {
+ return;
+ }
+ for (String name : properties.getKeyset()) {
+ if (KEY_HIDE_IME_WHEN_NO_EDITOR_FOCUS.equals(name)) {
+ mHideImeWhenNoEditorFocus = properties.getBoolean(name,
+ true /* defaultValue */);
+ }
+ }
+ };
+ mHideImeWhenNoEditorFocus = DeviceConfig.getBoolean(
+ DeviceConfig.NAMESPACE_INPUT_METHOD_MANAGER,
+ KEY_HIDE_IME_WHEN_NO_EDITOR_FOCUS, true);
+ DeviceConfig.addOnPropertiesChangedListener(
+ DeviceConfig.NAMESPACE_INPUT_METHOD_MANAGER,
+ ActivityThread.currentApplication().getMainExecutor(),
+ mDeviceConfigChangedListener);
+ }
+
+ /**
+ * Whether the IME should be hidden when the window gained focus without an editor focused.
+ */
+ public boolean shouldHideImeWhenNoEditorFocus() {
+ return mHideImeWhenNoEditorFocus;
+ }
+}
diff --git a/services/core/java/com/android/server/inputmethod/InputMethodManagerService.java b/services/core/java/com/android/server/inputmethod/InputMethodManagerService.java
index 7bd835c..729de41 100644
--- a/services/core/java/com/android/server/inputmethod/InputMethodManagerService.java
+++ b/services/core/java/com/android/server/inputmethod/InputMethodManagerService.java
@@ -303,6 +303,7 @@
final PackageManagerInternal mPackageManagerInternal;
final InputManagerInternal mInputManagerInternal;
final ImePlatformCompatUtils mImePlatformCompatUtils;
+ final InputMethodDeviceConfigs mInputMethodDeviceConfigs;
private final DisplayManagerInternal mDisplayManagerInternal;
final boolean mHasFeature;
private final ArrayMap<String, List<InputMethodSubtype>> mAdditionalSubtypeMap =
@@ -1732,6 +1733,7 @@
mPackageManagerInternal = LocalServices.getService(PackageManagerInternal.class);
mInputManagerInternal = LocalServices.getService(InputManagerInternal.class);
mImePlatformCompatUtils = new ImePlatformCompatUtils();
+ mInputMethodDeviceConfigs = new InputMethodDeviceConfigs();
mImeDisplayValidator = mWindowManagerInternal::getDisplayImePolicy;
mDisplayManagerInternal = LocalServices.getService(DisplayManagerInternal.class);
mAppOpsManager = mContext.getSystemService(AppOpsManager.class);
@@ -3889,6 +3891,18 @@
SoftInputShowHideReason.HIDE_SAME_WINDOW_FOCUSED_WITHOUT_EDITOR);
}
}
+ if (!isTextEditor && mInputShown && startInputByWinGainedFocus
+ && mInputMethodDeviceConfigs.shouldHideImeWhenNoEditorFocus()) {
+ // Hide the soft-keyboard when the system do nothing for softInputModeState
+ // of the window being gained focus without an editor. This behavior benefits
+ // to resolve some unexpected IME visible cases while that window with following
+ // configurations being switched from an IME shown window:
+ // 1) SOFT_INPUT_STATE_UNCHANGED state without an editor
+ // 2) SOFT_INPUT_STATE_VISIBLE state without an editor
+ // 3) SOFT_INPUT_STATE_ALWAYS_VISIBLE state without an editor
+ hideCurrentInputLocked(mCurFocusedWindow, 0, null,
+ SoftInputShowHideReason.HIDE_WINDOW_GAINED_FOCUS_WITHOUT_EDITOR);
+ }
res = startInputUncheckedLocked(cs, inputContext,
remoteAccessibilityInputConnection, editorInfo, startInputFlags,
startInputReason, unverifiedTargetSdkVersion,
diff --git a/services/core/java/com/android/server/media/SystemMediaRoute2Provider.java b/services/core/java/com/android/server/media/SystemMediaRoute2Provider.java
index d91bf8c..9466a6f5 100644
--- a/services/core/java/com/android/server/media/SystemMediaRoute2Provider.java
+++ b/services/core/java/com/android/server/media/SystemMediaRoute2Provider.java
@@ -287,7 +287,7 @@
name = com.android.internal.R.string.default_audio_route_name_dock_speakers;
} else if ((newRoutes.mainType & AudioRoutesInfo.MAIN_HDMI) != 0) {
type = TYPE_HDMI;
- name = com.android.internal.R.string.default_audio_route_name_hdmi;
+ name = com.android.internal.R.string.default_audio_route_name_external_device;
} else if ((newRoutes.mainType & AudioRoutesInfo.MAIN_USB) != 0) {
type = TYPE_USB_DEVICE;
name = com.android.internal.R.string.default_audio_route_name_usb;
diff --git a/services/core/java/com/android/server/om/IdmapManager.java b/services/core/java/com/android/server/om/IdmapManager.java
index f3cb7fb..b611b5d 100644
--- a/services/core/java/com/android/server/om/IdmapManager.java
+++ b/services/core/java/com/android/server/om/IdmapManager.java
@@ -31,7 +31,7 @@
import android.text.TextUtils;
import android.util.Slog;
-import com.android.server.pm.parsing.pkg.AndroidPackage;
+import com.android.server.pm.pkg.AndroidPackage;
import java.io.IOException;
import java.lang.annotation.Retention;
diff --git a/services/core/java/com/android/server/om/OverlayActorEnforcer.java b/services/core/java/com/android/server/om/OverlayActorEnforcer.java
index c4b6485..c35d8631 100644
--- a/services/core/java/com/android/server/om/OverlayActorEnforcer.java
+++ b/services/core/java/com/android/server/om/OverlayActorEnforcer.java
@@ -28,7 +28,7 @@
import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.util.ArrayUtils;
import com.android.internal.util.CollectionUtils;
-import com.android.server.pm.parsing.pkg.AndroidPackage;
+import com.android.server.pm.pkg.AndroidPackage;
import java.io.IOException;
import java.util.List;
diff --git a/services/core/java/com/android/server/om/OverlayManagerService.java b/services/core/java/com/android/server/om/OverlayManagerService.java
index 7159673..ba71438 100644
--- a/services/core/java/com/android/server/om/OverlayManagerService.java
+++ b/services/core/java/com/android/server/om/OverlayManagerService.java
@@ -84,7 +84,7 @@
import com.android.server.SystemService;
import com.android.server.pm.KnownPackages;
import com.android.server.pm.UserManagerService;
-import com.android.server.pm.parsing.pkg.AndroidPackage;
+import com.android.server.pm.pkg.AndroidPackage;
import libcore.util.EmptyArray;
diff --git a/services/core/java/com/android/server/om/OverlayManagerServiceImpl.java b/services/core/java/com/android/server/om/OverlayManagerServiceImpl.java
index dade7aa..ae305ca 100644
--- a/services/core/java/com/android/server/om/OverlayManagerServiceImpl.java
+++ b/services/core/java/com/android/server/om/OverlayManagerServiceImpl.java
@@ -47,7 +47,7 @@
import com.android.internal.content.om.OverlayConfig;
import com.android.internal.util.CollectionUtils;
-import com.android.server.pm.parsing.pkg.AndroidPackage;
+import com.android.server.pm.pkg.AndroidPackage;
import java.io.PrintWriter;
import java.util.ArrayList;
diff --git a/services/core/java/com/android/server/om/OverlayReferenceMapper.java b/services/core/java/com/android/server/om/OverlayReferenceMapper.java
index 539fecf..fdceabe 100644
--- a/services/core/java/com/android/server/om/OverlayReferenceMapper.java
+++ b/services/core/java/com/android/server/om/OverlayReferenceMapper.java
@@ -28,7 +28,7 @@
import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.util.CollectionUtils;
import com.android.server.SystemConfig;
-import com.android.server.pm.parsing.pkg.AndroidPackage;
+import com.android.server.pm.pkg.AndroidPackage;
import java.util.Collection;
import java.util.Collections;
diff --git a/services/core/java/com/android/server/om/PackageManagerHelper.java b/services/core/java/com/android/server/om/PackageManagerHelper.java
index 750f5c3..cbdabdd 100644
--- a/services/core/java/com/android/server/om/PackageManagerHelper.java
+++ b/services/core/java/com/android/server/om/PackageManagerHelper.java
@@ -19,19 +19,14 @@
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.content.om.OverlayableInfo;
-import android.content.pm.PackageInfo;
import android.content.pm.PackageManager;
import android.content.pm.PackageManagerInternal;
-import android.os.RemoteException;
import android.util.ArrayMap;
-import android.util.Slog;
import com.android.server.pm.PackageManagerServiceUtils;
-import com.android.server.pm.parsing.pkg.AndroidPackage;
+import com.android.server.pm.pkg.AndroidPackage;
import java.io.IOException;
-import java.util.HashMap;
-import java.util.List;
import java.util.Map;
/**
diff --git a/services/core/java/com/android/server/pm/ApexManager.java b/services/core/java/com/android/server/pm/ApexManager.java
index 01ddc48..71593e1 100644
--- a/services/core/java/com/android/server/pm/ApexManager.java
+++ b/services/core/java/com/android/server/pm/ApexManager.java
@@ -49,7 +49,7 @@
import com.android.internal.util.IndentingPrintWriter;
import com.android.internal.util.Preconditions;
import com.android.modules.utils.build.UnboundedSdkLevel;
-import com.android.server.pm.parsing.pkg.AndroidPackage;
+import com.android.server.pm.pkg.AndroidPackage;
import com.android.server.pm.pkg.component.ParsedApexSystemService;
import com.android.server.utils.TimingsTraceAndSlog;
diff --git a/services/core/java/com/android/server/pm/ApexPackageInfo.java b/services/core/java/com/android/server/pm/ApexPackageInfo.java
index 73cb0ad..4dd9c49 100644
--- a/services/core/java/com/android/server/pm/ApexPackageInfo.java
+++ b/services/core/java/com/android/server/pm/ApexPackageInfo.java
@@ -31,9 +31,9 @@
import com.android.internal.util.IndentingPrintWriter;
import com.android.internal.util.Preconditions;
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.pm.pkg.AndroidPackage;
import com.android.server.pm.pkg.PackageStateInternal;
import com.android.server.pm.pkg.parsing.ParsingPackageUtils;
diff --git a/services/core/java/com/android/server/pm/ApkChecksums.java b/services/core/java/com/android/server/pm/ApkChecksums.java
index c2f2b0a..a286160 100644
--- a/services/core/java/com/android/server/pm/ApkChecksums.java
+++ b/services/core/java/com/android/server/pm/ApkChecksums.java
@@ -64,7 +64,7 @@
import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.security.VerityUtils;
-import com.android.server.pm.parsing.pkg.AndroidPackage;
+import com.android.server.pm.pkg.AndroidPackage;
import java.io.ByteArrayOutputStream;
import java.io.DataInputStream;
diff --git a/services/core/java/com/android/server/pm/AppDataHelper.java b/services/core/java/com/android/server/pm/AppDataHelper.java
index da8992a..0f5d8fd 100644
--- a/services/core/java/com/android/server/pm/AppDataHelper.java
+++ b/services/core/java/com/android/server/pm/AppDataHelper.java
@@ -45,8 +45,8 @@
import com.android.internal.util.Preconditions;
import com.android.server.SystemServerInitThreadPool;
import com.android.server.pm.dex.ArtManagerService;
-import com.android.server.pm.parsing.pkg.AndroidPackage;
import com.android.server.pm.parsing.pkg.AndroidPackageUtils;
+import com.android.server.pm.pkg.AndroidPackage;
import com.android.server.pm.pkg.PackageStateInternal;
import com.android.server.pm.pkg.SELinuxUtil;
diff --git a/services/core/java/com/android/server/pm/AppsFilterBase.java b/services/core/java/com/android/server/pm/AppsFilterBase.java
index 5b3eff9..14140b5 100644
--- a/services/core/java/com/android/server/pm/AppsFilterBase.java
+++ b/services/core/java/com/android/server/pm/AppsFilterBase.java
@@ -40,7 +40,7 @@
import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.util.function.QuadFunction;
import com.android.server.om.OverlayReferenceMapper;
-import com.android.server.pm.parsing.pkg.AndroidPackage;
+import com.android.server.pm.pkg.AndroidPackage;
import com.android.server.pm.pkg.PackageStateInternal;
import com.android.server.pm.snapshot.PackageDataSnapshot;
import com.android.server.utils.SnapshotCache;
diff --git a/services/core/java/com/android/server/pm/AppsFilterImpl.java b/services/core/java/com/android/server/pm/AppsFilterImpl.java
index 5e0b47a..79d72a3 100644
--- a/services/core/java/com/android/server/pm/AppsFilterImpl.java
+++ b/services/core/java/com/android/server/pm/AppsFilterImpl.java
@@ -51,8 +51,8 @@
import com.android.server.FgThread;
import com.android.server.compat.CompatChange;
import com.android.server.om.OverlayReferenceMapper;
-import com.android.server.pm.parsing.pkg.AndroidPackage;
import com.android.server.pm.parsing.pkg.AndroidPackageUtils;
+import com.android.server.pm.pkg.AndroidPackage;
import com.android.server.pm.pkg.PackageStateInternal;
import com.android.server.pm.pkg.component.ParsedInstrumentation;
import com.android.server.pm.pkg.component.ParsedPermission;
diff --git a/services/core/java/com/android/server/pm/AppsFilterSnapshot.java b/services/core/java/com/android/server/pm/AppsFilterSnapshot.java
index de037f3..dd84e06 100644
--- a/services/core/java/com/android/server/pm/AppsFilterSnapshot.java
+++ b/services/core/java/com/android/server/pm/AppsFilterSnapshot.java
@@ -23,7 +23,7 @@
import android.util.SparseArray;
import com.android.internal.util.function.QuadFunction;
-import com.android.server.pm.parsing.pkg.AndroidPackage;
+import com.android.server.pm.pkg.AndroidPackage;
import com.android.server.pm.pkg.PackageStateInternal;
import com.android.server.pm.snapshot.PackageDataSnapshot;
diff --git a/services/core/java/com/android/server/pm/AppsFilterUtils.java b/services/core/java/com/android/server/pm/AppsFilterUtils.java
index 3a105c0..7daa0b9 100644
--- a/services/core/java/com/android/server/pm/AppsFilterUtils.java
+++ b/services/core/java/com/android/server/pm/AppsFilterUtils.java
@@ -23,7 +23,7 @@
import android.content.IntentFilter;
import com.android.internal.util.ArrayUtils;
-import com.android.server.pm.parsing.pkg.AndroidPackage;
+import com.android.server.pm.pkg.AndroidPackage;
import com.android.server.pm.pkg.PackageStateInternal;
import com.android.server.pm.pkg.component.ParsedComponent;
import com.android.server.pm.pkg.component.ParsedIntentInfo;
diff --git a/services/core/java/com/android/server/pm/Computer.java b/services/core/java/com/android/server/pm/Computer.java
index ab99860..5916196 100644
--- a/services/core/java/com/android/server/pm/Computer.java
+++ b/services/core/java/com/android/server/pm/Computer.java
@@ -48,7 +48,7 @@
import android.util.proto.ProtoOutputStream;
import com.android.internal.annotations.VisibleForTesting;
-import com.android.server.pm.parsing.pkg.AndroidPackage;
+import com.android.server.pm.pkg.AndroidPackage;
import com.android.server.pm.pkg.PackageState;
import com.android.server.pm.pkg.PackageStateInternal;
import com.android.server.pm.pkg.SharedUserApi;
diff --git a/services/core/java/com/android/server/pm/ComputerEngine.java b/services/core/java/com/android/server/pm/ComputerEngine.java
index d442fb2..3211ca1 100644
--- a/services/core/java/com/android/server/pm/ComputerEngine.java
+++ b/services/core/java/com/android/server/pm/ComputerEngine.java
@@ -129,9 +129,9 @@
import com.android.server.pm.dex.DexManager;
import com.android.server.pm.dex.PackageDexUsage;
import com.android.server.pm.parsing.PackageInfoUtils;
-import com.android.server.pm.parsing.pkg.AndroidPackage;
import com.android.server.pm.parsing.pkg.AndroidPackageUtils;
import com.android.server.pm.permission.PermissionManagerServiceInternal;
+import com.android.server.pm.pkg.AndroidPackage;
import com.android.server.pm.pkg.PackageStateInternal;
import com.android.server.pm.pkg.PackageStateUtils;
import com.android.server.pm.pkg.PackageUserStateInternal;
diff --git a/services/core/java/com/android/server/pm/DeletePackageHelper.java b/services/core/java/com/android/server/pm/DeletePackageHelper.java
index 7193587..9f6aa63 100644
--- a/services/core/java/com/android/server/pm/DeletePackageHelper.java
+++ b/services/core/java/com/android/server/pm/DeletePackageHelper.java
@@ -60,8 +60,8 @@
import com.android.internal.annotations.GuardedBy;
import com.android.internal.util.ArrayUtils;
import com.android.internal.util.Preconditions;
-import com.android.server.pm.parsing.pkg.AndroidPackage;
import com.android.server.pm.permission.PermissionManagerServiceInternal;
+import com.android.server.pm.pkg.AndroidPackage;
import com.android.server.pm.pkg.PackageStateInternal;
import com.android.server.pm.pkg.PackageUserState;
import com.android.server.wm.ActivityTaskManagerInternal;
@@ -572,7 +572,7 @@
if (deleteCodeAndResources && (outInfo != null)) {
outInfo.mArgs = new InstallArgs(
ps.getPathString(), getAppDexInstructionSets(
- ps.getPrimaryCpuAbi(), ps.getSecondaryCpuAbi()), mPm);
+ ps.getPrimaryCpuAbi(), ps.getSecondaryCpuAbi()));
if (DEBUG_SD_INSTALL) Slog.i(TAG, "args=" + outInfo.mArgs);
}
}
diff --git a/services/core/java/com/android/server/pm/DexOptHelper.java b/services/core/java/com/android/server/pm/DexOptHelper.java
index d501386..2b8a196 100644
--- a/services/core/java/com/android/server/pm/DexOptHelper.java
+++ b/services/core/java/com/android/server/pm/DexOptHelper.java
@@ -58,8 +58,8 @@
import com.android.internal.logging.MetricsLogger;
import com.android.server.pm.dex.DexManager;
import com.android.server.pm.dex.DexoptOptions;
-import com.android.server.pm.parsing.pkg.AndroidPackage;
import com.android.server.pm.parsing.pkg.AndroidPackageUtils;
+import com.android.server.pm.pkg.AndroidPackage;
import com.android.server.pm.pkg.PackageStateInternal;
import dalvik.system.DexFile;
diff --git a/services/core/java/com/android/server/pm/DomainVerificationConnection.java b/services/core/java/com/android/server/pm/DomainVerificationConnection.java
index 4134671..624d005 100644
--- a/services/core/java/com/android/server/pm/DomainVerificationConnection.java
+++ b/services/core/java/com/android/server/pm/DomainVerificationConnection.java
@@ -26,7 +26,7 @@
import android.os.UserHandle;
import com.android.server.DeviceIdleInternal;
-import com.android.server.pm.parsing.pkg.AndroidPackage;
+import com.android.server.pm.pkg.AndroidPackage;
import com.android.server.pm.verify.domain.DomainVerificationService;
import com.android.server.pm.verify.domain.proxy.DomainVerificationProxyV1;
import com.android.server.pm.verify.domain.proxy.DomainVerificationProxyV2;
diff --git a/services/core/java/com/android/server/pm/FeatureConfig.java b/services/core/java/com/android/server/pm/FeatureConfig.java
index 6e356de..1a57743 100644
--- a/services/core/java/com/android/server/pm/FeatureConfig.java
+++ b/services/core/java/com/android/server/pm/FeatureConfig.java
@@ -19,7 +19,7 @@
import static com.android.internal.annotations.VisibleForTesting.Visibility.PRIVATE;
import com.android.internal.annotations.VisibleForTesting;
-import com.android.server.pm.parsing.pkg.AndroidPackage;
+import com.android.server.pm.pkg.AndroidPackage;
import com.android.server.pm.pkg.PackageStateInternal;
@VisibleForTesting(visibility = PRIVATE)
diff --git a/services/core/java/com/android/server/pm/InitAppsHelper.java b/services/core/java/com/android/server/pm/InitAppsHelper.java
index 52e3fd9..797d4c3 100644
--- a/services/core/java/com/android/server/pm/InitAppsHelper.java
+++ b/services/core/java/com/android/server/pm/InitAppsHelper.java
@@ -52,7 +52,7 @@
import com.android.server.EventLogTags;
import com.android.server.pm.parsing.PackageCacher;
import com.android.server.pm.parsing.PackageParser2;
-import com.android.server.pm.parsing.pkg.AndroidPackage;
+import com.android.server.pm.pkg.AndroidPackage;
import com.android.server.pm.pkg.parsing.ParsingPackageUtils;
import com.android.server.utils.WatchedArrayMap;
@@ -227,7 +227,7 @@
}
}
final OverlayConfig overlayConfig = OverlayConfig.initializeSystemInstance(
- consumer -> mPm.forEachPackage(mPm.snapshotComputer(),
+ consumer -> mPm.forEachPackageInternal(mPm.snapshotComputer(),
pkg -> consumer.accept(pkg, pkg.isSystem(),
apkInApexPreInstalledPaths.get(pkg.getPackageName()))));
diff --git a/services/core/java/com/android/server/pm/InstallArgs.java b/services/core/java/com/android/server/pm/InstallArgs.java
index 616bb8f..65c2378 100644
--- a/services/core/java/com/android/server/pm/InstallArgs.java
+++ b/services/core/java/com/android/server/pm/InstallArgs.java
@@ -65,9 +65,6 @@
// if we move dex files under the common app path.
@Nullable String[] mInstructionSets;
- @NonNull final PackageManagerService mPm;
- @NonNull final RemovePackageHelper mRemovePackageHelper;
-
InstallArgs(OriginInfo originInfo, MoveInfo moveInfo, IPackageInstallObserver2 observer,
int installFlags, InstallSource installSource, String volumeUuid,
UserHandle user, String[] instructionSets,
@@ -76,7 +73,7 @@
int autoRevokePermissionsMode,
String traceMethod, int traceCookie, SigningDetails signingDetails,
int installReason, int installScenario, boolean forceQueryableOverride,
- int dataLoaderType, int packageSource, PackageManagerService pm) {
+ int dataLoaderType, int packageSource) {
mOriginInfo = originInfo;
mMoveInfo = moveInfo;
mInstallFlags = installFlags;
@@ -97,8 +94,6 @@
mForceQueryableOverride = forceQueryableOverride;
mDataLoaderType = dataLoaderType;
mPackageSource = packageSource;
- mPm = pm;
- mRemovePackageHelper = new RemovePackageHelper(mPm);
}
/** New install */
@@ -110,19 +105,19 @@
params.mAutoRevokePermissionsMode,
params.mTraceMethod, params.mTraceCookie, params.mSigningDetails,
params.mInstallReason, params.mInstallScenario, params.mForceQueryableOverride,
- params.mDataLoaderType, params.mPackageSource, params.mPm);
+ params.mDataLoaderType, params.mPackageSource);
}
/**
* Create args that describe an existing installed package. Typically used
* when cleaning up old installs, or used as a move source.
*/
- InstallArgs(String codePath, String[] instructionSets, PackageManagerService pm) {
+ InstallArgs(String codePath, String[] instructionSets) {
this(OriginInfo.fromNothing(), null, null, 0, InstallSource.EMPTY,
null, null, instructionSets, null, null, null, MODE_DEFAULT, null, 0,
SigningDetails.UNKNOWN, PackageManager.INSTALL_REASON_UNKNOWN,
PackageManager.INSTALL_SCENARIO_DEFAULT, false, DataLoaderType.NONE,
- PackageInstaller.PACKAGE_SOURCE_UNSPECIFIED, pm);
+ PackageInstaller.PACKAGE_SOURCE_UNSPECIFIED);
mCodeFile = (codePath != null) ? new File(codePath) : null;
}
diff --git a/services/core/java/com/android/server/pm/InstallPackageHelper.java b/services/core/java/com/android/server/pm/InstallPackageHelper.java
index 8024d41..d201710 100644
--- a/services/core/java/com/android/server/pm/InstallPackageHelper.java
+++ b/services/core/java/com/android/server/pm/InstallPackageHelper.java
@@ -162,11 +162,11 @@
import com.android.server.pm.dex.ViewCompiler;
import com.android.server.pm.parsing.PackageCacher;
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.pm.permission.Permission;
import com.android.server.pm.permission.PermissionManagerServiceInternal;
+import com.android.server.pm.pkg.AndroidPackage;
import com.android.server.pm.pkg.PackageStateInternal;
import com.android.server.pm.pkg.component.ComponentMutateUtils;
import com.android.server.pm.pkg.component.ParsedInstrumentation;
@@ -1937,7 +1937,7 @@
AndroidPackageUtils.getPrimaryCpuAbi(oldPackage,
deletedPkgSetting),
AndroidPackageUtils.getSecondaryCpuAbi(oldPackage,
- deletedPkgSetting)), mPm);
+ deletedPkgSetting)));
} else {
res.mRemovedInfo.mArgs = null;
}
@@ -3311,7 +3311,8 @@
if (disabledPs == null) {
logCriticalInfo(Log.WARN, "System package " + packageName
+ " no longer exists; its data will be wiped");
- mRemovePackageHelper.removePackageData(ps, userIds, null, 0, false);
+ mInjector.getHandler().post(
+ () -> mRemovePackageHelper.removePackageData(ps, userIds, null, 0, false));
} else {
// we still have a disabled system package, but, it still might have
// been removed. check the code path still exists and check there's
@@ -3937,7 +3938,7 @@
final InstallArgs args = new InstallArgs(
pkgSetting.getPathString(), getAppDexInstructionSets(
- pkgSetting.getPrimaryCpuAbi(), pkgSetting.getSecondaryCpuAbi()), mPm);
+ pkgSetting.getPrimaryCpuAbi(), pkgSetting.getSecondaryCpuAbi()));
mRemovePackageHelper.cleanUpResources(args);
synchronized (mPm.mLock) {
mPm.mSettings.enableSystemPackageLPw(pkgSetting.getPackageName());
@@ -4022,8 +4023,7 @@
+ parsedPackage.getPath());
InstallArgs args = new InstallArgs(
pkgSetting.getPathString(), getAppDexInstructionSets(
- pkgSetting.getPrimaryCpuAbi(), pkgSetting.getSecondaryCpuAbi()),
- mPm);
+ pkgSetting.getPrimaryCpuAbi(), pkgSetting.getSecondaryCpuAbi()));
mRemovePackageHelper.cleanUpResources(args);
} else {
// The application on /system is older than the application on /data. Hide
diff --git a/services/core/java/com/android/server/pm/InstallingSession.java b/services/core/java/com/android/server/pm/InstallingSession.java
index 0630ccd..a7f1727 100644
--- a/services/core/java/com/android/server/pm/InstallingSession.java
+++ b/services/core/java/com/android/server/pm/InstallingSession.java
@@ -51,7 +51,7 @@
import com.android.internal.content.NativeLibraryHelper;
import com.android.internal.util.Preconditions;
import com.android.server.pm.parsing.PackageParser2;
-import com.android.server.pm.parsing.pkg.AndroidPackage;
+import com.android.server.pm.pkg.AndroidPackage;
import libcore.io.IoUtils;
diff --git a/services/core/java/com/android/server/pm/InstantAppRegistry.java b/services/core/java/com/android/server/pm/InstantAppRegistry.java
index 39a2839..71bd2d7 100644
--- a/services/core/java/com/android/server/pm/InstantAppRegistry.java
+++ b/services/core/java/com/android/server/pm/InstantAppRegistry.java
@@ -56,9 +56,9 @@
import com.android.internal.util.ArrayUtils;
import com.android.internal.util.XmlUtils;
import com.android.server.pm.parsing.PackageInfoUtils;
-import com.android.server.pm.parsing.pkg.AndroidPackage;
import com.android.server.pm.parsing.pkg.AndroidPackageUtils;
import com.android.server.pm.permission.PermissionManagerServiceInternal;
+import com.android.server.pm.pkg.AndroidPackage;
import com.android.server.pm.pkg.PackageStateInternal;
import com.android.server.pm.pkg.PackageStateUtils;
import com.android.server.pm.pkg.PackageUserStateInternal;
diff --git a/services/core/java/com/android/server/pm/InstructionSets.java b/services/core/java/com/android/server/pm/InstructionSets.java
index 2d42107..f1cfc5b 100644
--- a/services/core/java/com/android/server/pm/InstructionSets.java
+++ b/services/core/java/com/android/server/pm/InstructionSets.java
@@ -21,9 +21,6 @@
import android.text.TextUtils;
import android.util.ArraySet;
-import com.android.server.pm.parsing.pkg.AndroidPackage;
-import com.android.server.pm.parsing.pkg.AndroidPackageUtils;
-
import dalvik.system.VMRuntime;
import java.util.ArrayList;
diff --git a/services/core/java/com/android/server/pm/KeySetManagerService.java b/services/core/java/com/android/server/pm/KeySetManagerService.java
index 5c29833..7774b6a 100644
--- a/services/core/java/com/android/server/pm/KeySetManagerService.java
+++ b/services/core/java/com/android/server/pm/KeySetManagerService.java
@@ -30,7 +30,7 @@
import android.util.TypedXmlPullParser;
import android.util.TypedXmlSerializer;
-import com.android.server.pm.parsing.pkg.AndroidPackage;
+import com.android.server.pm.pkg.AndroidPackage;
import com.android.server.pm.pkg.PackageStateInternal;
import com.android.server.pm.pkg.SharedUserApi;
import com.android.server.utils.WatchedArrayMap;
diff --git a/services/core/java/com/android/server/pm/LauncherAppsService.java b/services/core/java/com/android/server/pm/LauncherAppsService.java
index 59bd427..c38b822 100644
--- a/services/core/java/com/android/server/pm/LauncherAppsService.java
+++ b/services/core/java/com/android/server/pm/LauncherAppsService.java
@@ -96,7 +96,7 @@
import com.android.internal.util.Preconditions;
import com.android.server.LocalServices;
import com.android.server.SystemService;
-import com.android.server.pm.parsing.pkg.AndroidPackage;
+import com.android.server.pm.pkg.AndroidPackage;
import com.android.server.wm.ActivityTaskManagerInternal;
import java.util.ArrayList;
diff --git a/services/core/java/com/android/server/pm/MovePackageHelper.java b/services/core/java/com/android/server/pm/MovePackageHelper.java
index df02223..b27373e 100644
--- a/services/core/java/com/android/server/pm/MovePackageHelper.java
+++ b/services/core/java/com/android/server/pm/MovePackageHelper.java
@@ -55,8 +55,8 @@
import com.android.internal.annotations.GuardedBy;
import com.android.internal.os.SomeArgs;
import com.android.internal.util.FrameworkStatsLog;
-import com.android.server.pm.parsing.pkg.AndroidPackage;
import com.android.server.pm.parsing.pkg.AndroidPackageUtils;
+import com.android.server.pm.pkg.AndroidPackage;
import com.android.server.pm.pkg.PackageStateInternal;
import com.android.server.pm.pkg.PackageStateUtils;
diff --git a/services/core/java/com/android/server/pm/OtaDexoptService.java b/services/core/java/com/android/server/pm/OtaDexoptService.java
index e4dcf1a..5507b44 100644
--- a/services/core/java/com/android/server/pm/OtaDexoptService.java
+++ b/services/core/java/com/android/server/pm/OtaDexoptService.java
@@ -38,8 +38,8 @@
import com.android.server.LocalServices;
import com.android.server.pm.Installer.InstallerException;
import com.android.server.pm.dex.DexoptOptions;
-import com.android.server.pm.parsing.pkg.AndroidPackage;
import com.android.server.pm.parsing.pkg.AndroidPackageUtils;
+import com.android.server.pm.pkg.AndroidPackage;
import com.android.server.pm.pkg.PackageStateInternal;
import java.io.File;
diff --git a/services/core/java/com/android/server/pm/PackageAbiHelper.java b/services/core/java/com/android/server/pm/PackageAbiHelper.java
index 1dbab90..9bea599 100644
--- a/services/core/java/com/android/server/pm/PackageAbiHelper.java
+++ b/services/core/java/com/android/server/pm/PackageAbiHelper.java
@@ -22,9 +22,9 @@
import android.util.Pair;
import com.android.internal.annotations.VisibleForTesting;
-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.pm.pkg.AndroidPackage;
import com.android.server.pm.pkg.PackageStateInternal;
import java.io.File;
diff --git a/services/core/java/com/android/server/pm/PackageAbiHelperImpl.java b/services/core/java/com/android/server/pm/PackageAbiHelperImpl.java
index 73d81ba..75f5f93 100644
--- a/services/core/java/com/android/server/pm/PackageAbiHelperImpl.java
+++ b/services/core/java/com/android/server/pm/PackageAbiHelperImpl.java
@@ -40,8 +40,8 @@
import com.android.internal.content.NativeLibraryHelper;
import com.android.internal.util.ArrayUtils;
-import com.android.server.pm.parsing.pkg.AndroidPackage;
import com.android.server.pm.parsing.pkg.AndroidPackageUtils;
+import com.android.server.pm.pkg.AndroidPackage;
import com.android.server.pm.pkg.PackageStateInternal;
import dalvik.system.VMRuntime;
diff --git a/services/core/java/com/android/server/pm/PackageDexOptimizer.java b/services/core/java/com/android/server/pm/PackageDexOptimizer.java
index 4b6543b..3fb4066 100644
--- a/services/core/java/com/android/server/pm/PackageDexOptimizer.java
+++ b/services/core/java/com/android/server/pm/PackageDexOptimizer.java
@@ -77,8 +77,8 @@
import com.android.server.pm.dex.DexoptOptions;
import com.android.server.pm.dex.DexoptUtils;
import com.android.server.pm.dex.PackageDexUsage;
-import com.android.server.pm.parsing.pkg.AndroidPackage;
import com.android.server.pm.parsing.pkg.AndroidPackageUtils;
+import com.android.server.pm.pkg.AndroidPackage;
import com.android.server.pm.pkg.PackageStateInternal;
import dalvik.system.DexFile;
diff --git a/services/core/java/com/android/server/pm/PackageInstalledInfo.java b/services/core/java/com/android/server/pm/PackageInstalledInfo.java
index 1c25dbb..247abf3 100644
--- a/services/core/java/com/android/server/pm/PackageInstalledInfo.java
+++ b/services/core/java/com/android/server/pm/PackageInstalledInfo.java
@@ -22,7 +22,7 @@
import android.util.ExceptionUtils;
import android.util.Slog;
-import com.android.server.pm.parsing.pkg.AndroidPackage;
+import com.android.server.pm.pkg.AndroidPackage;
import java.util.ArrayList;
diff --git a/services/core/java/com/android/server/pm/PackageInstallerSession.java b/services/core/java/com/android/server/pm/PackageInstallerSession.java
index df02fe1..e9f26e9 100644
--- a/services/core/java/com/android/server/pm/PackageInstallerSession.java
+++ b/services/core/java/com/android/server/pm/PackageInstallerSession.java
@@ -152,7 +152,7 @@
import com.android.server.LocalServices;
import com.android.server.pm.Installer.InstallerException;
import com.android.server.pm.dex.DexManager;
-import com.android.server.pm.parsing.pkg.AndroidPackage;
+import com.android.server.pm.pkg.AndroidPackage;
import com.android.server.pm.pkg.PackageStateInternal;
import com.android.server.pm.pkg.parsing.ParsingPackageUtils;
diff --git a/services/core/java/com/android/server/pm/PackageManagerInternalBase.java b/services/core/java/com/android/server/pm/PackageManagerInternalBase.java
index 330e3313..34d6d29 100644
--- a/services/core/java/com/android/server/pm/PackageManagerInternalBase.java
+++ b/services/core/java/com/android/server/pm/PackageManagerInternalBase.java
@@ -49,9 +49,8 @@
import com.android.server.pm.dex.DexManager;
import com.android.server.pm.dex.DynamicCodeLogger;
-import com.android.server.pm.parsing.pkg.AndroidPackage;
import com.android.server.pm.permission.PermissionManagerServiceInternal;
-import com.android.server.pm.pkg.AndroidPackageApi;
+import com.android.server.pm.pkg.AndroidPackage;
import com.android.server.pm.pkg.PackageStateInternal;
import com.android.server.pm.pkg.PackageStateUtils;
import com.android.server.pm.pkg.SharedUserApi;
@@ -155,7 +154,7 @@
@Nullable
@Override
@Deprecated
- public final AndroidPackageApi getAndroidPackage(@NonNull String packageName) {
+ public final AndroidPackage getAndroidPackage(@NonNull String packageName) {
return snapshot().getPackage(packageName);
}
diff --git a/services/core/java/com/android/server/pm/PackageManagerService.java b/services/core/java/com/android/server/pm/PackageManagerService.java
index 752ebf3..259202f 100644
--- a/services/core/java/com/android/server/pm/PackageManagerService.java
+++ b/services/core/java/com/android/server/pm/PackageManagerService.java
@@ -203,13 +203,14 @@
import com.android.server.pm.dex.ViewCompiler;
import com.android.server.pm.parsing.PackageInfoUtils;
import com.android.server.pm.parsing.PackageParser2;
-import com.android.server.pm.parsing.pkg.AndroidPackage;
+import com.android.server.pm.parsing.pkg.AndroidPackageInternal;
import com.android.server.pm.parsing.pkg.AndroidPackageUtils;
import com.android.server.pm.parsing.pkg.ParsedPackage;
import com.android.server.pm.permission.LegacyPermissionManagerInternal;
import com.android.server.pm.permission.LegacyPermissionManagerService;
import com.android.server.pm.permission.PermissionManagerService;
import com.android.server.pm.permission.PermissionManagerServiceInternal;
+import com.android.server.pm.pkg.AndroidPackage;
import com.android.server.pm.pkg.PackageStateInternal;
import com.android.server.pm.pkg.PackageUserState;
import com.android.server.pm.pkg.PackageUserStateInternal;
@@ -6716,6 +6717,19 @@
}
}
+ void forEachPackageInternal(@NonNull Computer snapshot,
+ @NonNull Consumer<AndroidPackageInternal> consumer) {
+ final ArrayMap<String, ? extends PackageStateInternal> packageStates =
+ snapshot.getPackageStates();
+ int size = packageStates.size();
+ for (int index = 0; index < size; index++) {
+ PackageStateInternal packageState = packageStates.valueAt(index);
+ if (packageState.getPkg() != null) {
+ consumer.accept(packageState.getPkg());
+ }
+ }
+ }
+
private void forEachPackageState(
@NonNull ArrayMap<String, ? extends PackageStateInternal> packageStates,
@NonNull Consumer<PackageStateInternal> consumer) {
diff --git a/services/core/java/com/android/server/pm/PackageManagerServiceTestParams.java b/services/core/java/com/android/server/pm/PackageManagerServiceTestParams.java
index ec1b29e..4391fdd 100644
--- a/services/core/java/com/android/server/pm/PackageManagerServiceTestParams.java
+++ b/services/core/java/com/android/server/pm/PackageManagerServiceTestParams.java
@@ -34,8 +34,8 @@
import com.android.server.pm.dex.DexManager;
import com.android.server.pm.dex.ViewCompiler;
import com.android.server.pm.parsing.PackageParser2;
-import com.android.server.pm.parsing.pkg.AndroidPackage;
import com.android.server.pm.permission.LegacyPermissionManagerInternal;
+import com.android.server.pm.pkg.AndroidPackage;
import java.io.File;
import java.util.List;
diff --git a/services/core/java/com/android/server/pm/PackageManagerServiceUtils.java b/services/core/java/com/android/server/pm/PackageManagerServiceUtils.java
index f466655..77334e5 100644
--- a/services/core/java/com/android/server/pm/PackageManagerServiceUtils.java
+++ b/services/core/java/com/android/server/pm/PackageManagerServiceUtils.java
@@ -93,7 +93,7 @@
import com.android.server.Watchdog;
import com.android.server.compat.PlatformCompat;
import com.android.server.pm.dex.PackageDexUsage;
-import com.android.server.pm.parsing.pkg.AndroidPackage;
+import com.android.server.pm.pkg.AndroidPackage;
import com.android.server.pm.pkg.PackageStateInternal;
import com.android.server.pm.pkg.component.ParsedMainComponent;
import com.android.server.pm.resolution.ComponentResolverApi;
diff --git a/services/core/java/com/android/server/pm/PackageProperty.java b/services/core/java/com/android/server/pm/PackageProperty.java
index 2055537..241f143 100644
--- a/services/core/java/com/android/server/pm/PackageProperty.java
+++ b/services/core/java/com/android/server/pm/PackageProperty.java
@@ -27,12 +27,12 @@
import android.content.pm.PackageManager;
import android.content.pm.PackageManager.Property;
import android.content.pm.PackageManager.PropertyLocation;
-import com.android.server.pm.pkg.component.ParsedComponent;
import android.os.Binder;
import android.os.UserHandle;
import android.util.ArrayMap;
-import com.android.server.pm.parsing.pkg.AndroidPackage;
+import com.android.server.pm.pkg.AndroidPackage;
+import com.android.server.pm.pkg.component.ParsedComponent;
import java.util.ArrayList;
import java.util.Iterator;
diff --git a/services/core/java/com/android/server/pm/PackageSetting.java b/services/core/java/com/android/server/pm/PackageSetting.java
index f84db1f..4764a5c 100644
--- a/services/core/java/com/android/server/pm/PackageSetting.java
+++ b/services/core/java/com/android/server/pm/PackageSetting.java
@@ -41,10 +41,11 @@
import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.util.CollectionUtils;
import com.android.internal.util.DataClass;
-import com.android.server.pm.parsing.pkg.AndroidPackage;
+import com.android.server.pm.parsing.pkg.AndroidPackageInternal;
+import com.android.server.pm.parsing.pkg.ParsedPackage;
import com.android.server.pm.permission.LegacyPermissionDataProvider;
import com.android.server.pm.permission.LegacyPermissionState;
-import com.android.server.pm.pkg.AndroidPackageApi;
+import com.android.server.pm.pkg.AndroidPackage;
import com.android.server.pm.pkg.PackageState;
import com.android.server.pm.pkg.PackageStateInternal;
import com.android.server.pm.pkg.PackageStateUnserialized;
@@ -126,7 +127,7 @@
* @see PackageState#getAndroidPackage()
*/
@Nullable
- private AndroidPackage pkg;
+ private AndroidPackageInternal pkg;
/** @see AndroidPackage#getPath() */
@NonNull
@@ -418,8 +419,9 @@
return hasChanges;
}
+ // TODO: Remove, only commit package when it's actually finalized
public PackageSetting setPkg(AndroidPackage pkg) {
- this.pkg = pkg;
+ this.pkg = (AndroidPackageInternal) pkg;
onChanged();
return this;
}
@@ -1165,7 +1167,7 @@
@Nullable
@Override
- public AndroidPackageApi getAndroidPackage() {
+ public AndroidPackage getAndroidPackage() {
return getPkg();
}
@@ -1366,7 +1368,7 @@
* @see PackageState#getAndroidPackage()
*/
@DataClass.Generated.Member
- public @Nullable AndroidPackage getPkg() {
+ public @Nullable AndroidPackageInternal getPkg() {
return pkg;
}
@@ -1473,10 +1475,10 @@
}
@DataClass.Generated(
- time = 1644270960923L,
+ time = 1659546705292L,
codegenVersion = "1.0.23",
sourceFile = "frameworks/base/services/core/java/com/android/server/pm/PackageSetting.java",
- inputSignatures = "private int mSharedUserAppId\nprivate @android.annotation.Nullable java.util.Map<java.lang.String,java.util.Set<java.lang.String>> mimeGroups\nprivate @java.lang.Deprecated @android.annotation.Nullable java.util.Set<java.lang.String> mOldCodePaths\nprivate @android.annotation.Nullable java.lang.String[] usesSdkLibraries\nprivate @android.annotation.Nullable long[] usesSdkLibrariesVersionsMajor\nprivate @android.annotation.Nullable java.lang.String[] usesStaticLibraries\nprivate @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.Nullable java.lang.String mRealName\nprivate int mAppId\nprivate @android.annotation.Nullable com.android.server.pm.parsing.pkg.AndroidPackage pkg\nprivate @android.annotation.NonNull java.io.File mPath\nprivate @android.annotation.NonNull java.lang.String mPathString\nprivate float mLoadingProgress\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 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.PackageUserStateImpl> mUserStates\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 final @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 com.android.server.pm.PackageSetting setAppId(int)\npublic com.android.server.pm.PackageSetting setCpuAbiOverride(java.lang.String)\npublic com.android.server.pm.PackageSetting setFirstInstallTimeFromReplaced(com.android.server.pm.pkg.PackageStateInternal,int[])\npublic com.android.server.pm.PackageSetting setFirstInstallTime(long,int)\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,android.util.ArraySet<java.lang.String>)\npublic com.android.server.pm.PackageSetting setPkg(com.android.server.pm.parsing.pkg.AndroidPackage)\npublic com.android.server.pm.PackageSetting setPkgStateLibraryFiles(java.util.Collection<java.lang.String>)\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 void setSharedUserAppId(int)\npublic @java.lang.Override int getSharedUserAppId()\npublic @java.lang.Override boolean hasSharedUser()\npublic @java.lang.Override java.lang.String toString()\nprotected void copyMimeGroups(java.util.Map<java.lang.String,java.util.Set<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.PackageUserStateImpl modifyUserState(int)\npublic com.android.server.pm.pkg.PackageUserStateImpl getOrCreateUserState(int)\npublic @android.annotation.NonNull com.android.server.pm.pkg.PackageUserStateInternal readUserState(int)\n void setEnabled(int,int,java.lang.String)\n int getEnabled(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 @android.annotation.NonNull android.content.pm.overlay.OverlayPaths getOverlayPaths(int)\n boolean setOverlayPathsForLibrary(java.lang.String,android.content.pm.overlay.OverlayPaths,int)\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)\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,android.util.ArrayMap<java.lang.String,com.android.server.pm.pkg.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,long)\n void setUserState(int,com.android.server.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.PackageUserStateImpl 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 com.android.server.pm.PackageSetting setPath(java.io.File)\npublic @com.android.internal.annotations.VisibleForTesting boolean overrideNonLocalizedLabelAndIcon(android.content.ComponentName,java.lang.String,java.lang.Integer,int)\npublic void resetOverrideComponentLabelIcon(int)\npublic @android.annotation.Nullable java.lang.String getSplashScreenTheme(int)\npublic boolean isLoading()\npublic com.android.server.pm.PackageSetting setLoadingProgress(float)\npublic @android.annotation.NonNull @java.lang.Override long getVersionCode()\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.NonNull android.content.pm.SigningInfo getSigningInfo()\npublic @android.annotation.NonNull @java.lang.Override java.lang.String[] getUsesSdkLibraries()\npublic @android.annotation.NonNull @java.lang.Override long[] getUsesSdkLibrariesVersionsMajor()\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.NonNull @java.lang.Override long[] getLastPackageUsageTime()\npublic @java.lang.Override boolean isUpdatedSystemApp()\npublic com.android.server.pm.PackageSetting setDomainSetId(java.util.UUID)\npublic com.android.server.pm.PackageSetting setCategoryOverride(int)\npublic com.android.server.pm.PackageSetting setLegacyNativeLibraryPath(java.lang.String)\npublic com.android.server.pm.PackageSetting setMimeGroups(java.util.Map<java.lang.String,java.util.Set<java.lang.String>>)\npublic com.android.server.pm.PackageSetting setOldCodePaths(java.util.Set<java.lang.String>)\npublic com.android.server.pm.PackageSetting setUsesSdkLibraries(java.lang.String[])\npublic com.android.server.pm.PackageSetting setUsesSdkLibrariesVersionsMajor(long[])\npublic com.android.server.pm.PackageSetting setUsesStaticLibraries(java.lang.String[])\npublic com.android.server.pm.PackageSetting setUsesStaticLibrariesVersions(long[])\npublic @android.annotation.NonNull @java.lang.Override com.android.server.pm.pkg.PackageStateUnserialized getTransientState()\npublic @android.annotation.NonNull android.util.SparseArray<? extends PackageUserStateInternal> getUserStates()\npublic com.android.server.pm.PackageSetting addMimeTypes(java.lang.String,java.util.Set<java.lang.String>)\nclass PackageSetting extends com.android.server.pm.SettingBase implements [com.android.server.pm.pkg.PackageStateInternal]\n@com.android.internal.util.DataClass(genGetters=true, genConstructor=false, genSetters=false, genBuilder=false)")
+ inputSignatures = "private int mSharedUserAppId\nprivate @android.annotation.Nullable java.util.Map<java.lang.String,java.util.Set<java.lang.String>> mimeGroups\nprivate @java.lang.Deprecated @android.annotation.Nullable java.util.Set<java.lang.String> mOldCodePaths\nprivate @android.annotation.Nullable java.lang.String[] usesSdkLibraries\nprivate @android.annotation.Nullable long[] usesSdkLibrariesVersionsMajor\nprivate @android.annotation.Nullable java.lang.String[] usesStaticLibraries\nprivate @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.Nullable java.lang.String mRealName\nprivate int mAppId\nprivate @android.annotation.Nullable com.android.server.pm.parsing.pkg.AndroidPackageInternal pkg\nprivate @android.annotation.NonNull java.io.File mPath\nprivate @android.annotation.NonNull java.lang.String mPathString\nprivate float mLoadingProgress\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 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.PackageUserStateImpl> mUserStates\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 final @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 com.android.server.pm.PackageSetting setAppId(int)\npublic com.android.server.pm.PackageSetting setCpuAbiOverride(java.lang.String)\npublic com.android.server.pm.PackageSetting setFirstInstallTimeFromReplaced(com.android.server.pm.pkg.PackageStateInternal,int[])\npublic com.android.server.pm.PackageSetting setFirstInstallTime(long,int)\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,android.util.ArraySet<java.lang.String>)\npublic com.android.server.pm.PackageSetting setPkg(com.android.server.pm.parsing.pkg.AndroidPackageInternal)\npublic com.android.server.pm.PackageSetting setPkgStateLibraryFiles(java.util.Collection<java.lang.String>)\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 void setSharedUserAppId(int)\npublic @java.lang.Override int getSharedUserAppId()\npublic @java.lang.Override boolean hasSharedUser()\npublic @java.lang.Override java.lang.String toString()\nprotected void copyMimeGroups(java.util.Map<java.lang.String,java.util.Set<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,boolean)\n @com.android.internal.annotations.VisibleForTesting com.android.server.pm.pkg.PackageUserStateImpl modifyUserState(int)\npublic com.android.server.pm.pkg.PackageUserStateImpl getOrCreateUserState(int)\npublic @android.annotation.NonNull com.android.server.pm.pkg.PackageUserStateInternal readUserState(int)\n void setEnabled(int,int,java.lang.String)\n int getEnabled(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 @android.annotation.NonNull android.content.pm.overlay.OverlayPaths getOverlayPaths(int)\n boolean setOverlayPathsForLibrary(java.lang.String,android.content.pm.overlay.OverlayPaths,int)\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)\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,android.util.ArrayMap<java.lang.String,com.android.server.pm.pkg.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,long)\n void setUserState(int,com.android.server.pm.pkg.PackageUserStateInternal)\n com.android.server.utils.WatchedArraySet<java.lang.String> getEnabledComponents(int)\n com.android.server.utils.WatchedArraySet<java.lang.String> getDisabledComponents(int)\n void setEnabledComponents(com.android.server.utils.WatchedArraySet<java.lang.String>,int)\n void setDisabledComponents(com.android.server.utils.WatchedArraySet<java.lang.String>,int)\n void setEnabledComponentsCopy(com.android.server.utils.WatchedArraySet<java.lang.String>,int)\n void setDisabledComponentsCopy(com.android.server.utils.WatchedArraySet<java.lang.String>,int)\n com.android.server.pm.pkg.PackageUserStateImpl 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 com.android.server.pm.PackageSetting setPath(java.io.File)\npublic @com.android.internal.annotations.VisibleForTesting boolean overrideNonLocalizedLabelAndIcon(android.content.ComponentName,java.lang.String,java.lang.Integer,int)\npublic void resetOverrideComponentLabelIcon(int)\npublic @android.annotation.Nullable java.lang.String getSplashScreenTheme(int)\npublic boolean isLoading()\npublic com.android.server.pm.PackageSetting setLoadingProgress(float)\npublic @android.annotation.NonNull @java.lang.Override long getVersionCode()\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.AndroidPackage getAndroidPackage()\npublic @android.annotation.NonNull android.content.pm.SigningInfo getSigningInfo()\npublic @android.annotation.NonNull @java.lang.Override java.lang.String[] getUsesSdkLibraries()\npublic @android.annotation.NonNull @java.lang.Override long[] getUsesSdkLibrariesVersionsMajor()\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.NonNull @java.lang.Override long[] getLastPackageUsageTime()\npublic @java.lang.Override boolean isUpdatedSystemApp()\npublic @java.lang.Override boolean isApkInUpdatedApex()\npublic com.android.server.pm.PackageSetting setDomainSetId(java.util.UUID)\npublic com.android.server.pm.PackageSetting setCategoryOverride(int)\npublic com.android.server.pm.PackageSetting setLegacyNativeLibraryPath(java.lang.String)\npublic com.android.server.pm.PackageSetting setMimeGroups(java.util.Map<java.lang.String,java.util.Set<java.lang.String>>)\npublic com.android.server.pm.PackageSetting setOldCodePaths(java.util.Set<java.lang.String>)\npublic com.android.server.pm.PackageSetting setUsesSdkLibraries(java.lang.String[])\npublic com.android.server.pm.PackageSetting setUsesSdkLibrariesVersionsMajor(long[])\npublic com.android.server.pm.PackageSetting setUsesStaticLibraries(java.lang.String[])\npublic com.android.server.pm.PackageSetting setUsesStaticLibrariesVersions(long[])\npublic @android.annotation.NonNull @java.lang.Override com.android.server.pm.pkg.PackageStateUnserialized getTransientState()\npublic @android.annotation.NonNull android.util.SparseArray<? extends PackageUserStateInternal> getUserStates()\npublic com.android.server.pm.PackageSetting addMimeTypes(java.lang.String,java.util.Set<java.lang.String>)\nclass PackageSetting extends com.android.server.pm.SettingBase implements [com.android.server.pm.pkg.PackageStateInternal]\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/PrepareResult.java b/services/core/java/com/android/server/pm/PrepareResult.java
index 4e08e16..e074f44a 100644
--- a/services/core/java/com/android/server/pm/PrepareResult.java
+++ b/services/core/java/com/android/server/pm/PrepareResult.java
@@ -18,8 +18,8 @@
import android.annotation.Nullable;
-import com.android.server.pm.parsing.pkg.AndroidPackage;
import com.android.server.pm.parsing.pkg.ParsedPackage;
+import com.android.server.pm.pkg.AndroidPackage;
/**
* The set of data needed to successfully install the prepared package. This includes data that
diff --git a/services/core/java/com/android/server/pm/ReconcilePackageUtils.java b/services/core/java/com/android/server/pm/ReconcilePackageUtils.java
index d6a133e..0f7c652 100644
--- a/services/core/java/com/android/server/pm/ReconcilePackageUtils.java
+++ b/services/core/java/com/android/server/pm/ReconcilePackageUtils.java
@@ -30,8 +30,8 @@
import android.util.ArrayMap;
import android.util.Log;
-import com.android.server.pm.parsing.pkg.AndroidPackage;
import com.android.server.pm.parsing.pkg.ParsedPackage;
+import com.android.server.pm.pkg.AndroidPackage;
import com.android.server.pm.pkg.parsing.ParsingPackageUtils;
import com.android.server.utils.WatchedLongSparseArray;
diff --git a/services/core/java/com/android/server/pm/ReconcileRequest.java b/services/core/java/com/android/server/pm/ReconcileRequest.java
index 9e4e986..84b292f 100644
--- a/services/core/java/com/android/server/pm/ReconcileRequest.java
+++ b/services/core/java/com/android/server/pm/ReconcileRequest.java
@@ -16,7 +16,7 @@
package com.android.server.pm;
-import com.android.server.pm.parsing.pkg.AndroidPackage;
+import com.android.server.pm.pkg.AndroidPackage;
import java.util.Collections;
import java.util.Map;
diff --git a/services/core/java/com/android/server/pm/ReconciledPackage.java b/services/core/java/com/android/server/pm/ReconciledPackage.java
index 1bfe357..3bb5a1b 100644
--- a/services/core/java/com/android/server/pm/ReconciledPackage.java
+++ b/services/core/java/com/android/server/pm/ReconciledPackage.java
@@ -22,7 +22,7 @@
import android.content.pm.SigningDetails;
import android.util.ArrayMap;
-import com.android.server.pm.parsing.pkg.AndroidPackage;
+import com.android.server.pm.pkg.AndroidPackage;
import java.util.ArrayList;
import java.util.List;
diff --git a/services/core/java/com/android/server/pm/RemovePackageHelper.java b/services/core/java/com/android/server/pm/RemovePackageHelper.java
index f083b67..a025965 100644
--- a/services/core/java/com/android/server/pm/RemovePackageHelper.java
+++ b/services/core/java/com/android/server/pm/RemovePackageHelper.java
@@ -46,9 +46,9 @@
import com.android.internal.annotations.GuardedBy;
import com.android.internal.util.ArrayUtils;
import com.android.server.pm.parsing.PackageCacher;
-import com.android.server.pm.parsing.pkg.AndroidPackage;
import com.android.server.pm.parsing.pkg.PackageImpl;
import com.android.server.pm.permission.PermissionManagerServiceInternal;
+import com.android.server.pm.pkg.AndroidPackage;
import com.android.server.pm.pkg.PackageStateInternal;
import com.android.server.pm.pkg.component.ParsedInstrumentation;
diff --git a/services/core/java/com/android/server/pm/ResolveIntentHelper.java b/services/core/java/com/android/server/pm/ResolveIntentHelper.java
index 24ed621..c2fd637 100644
--- a/services/core/java/com/android/server/pm/ResolveIntentHelper.java
+++ b/services/core/java/com/android/server/pm/ResolveIntentHelper.java
@@ -53,7 +53,7 @@
import com.android.internal.app.ResolverActivity;
import com.android.internal.util.ArrayUtils;
import com.android.server.compat.PlatformCompat;
-import com.android.server.pm.parsing.pkg.AndroidPackage;
+import com.android.server.pm.pkg.AndroidPackage;
import com.android.server.pm.pkg.PackageStateInternal;
import com.android.server.pm.resolution.ComponentResolverApi;
import com.android.server.pm.verify.domain.DomainVerificationManagerInternal;
diff --git a/services/core/java/com/android/server/pm/SELinuxMMAC.java b/services/core/java/com/android/server/pm/SELinuxMMAC.java
index c0e191f..f7e04d4 100644
--- a/services/core/java/com/android/server/pm/SELinuxMMAC.java
+++ b/services/core/java/com/android/server/pm/SELinuxMMAC.java
@@ -27,8 +27,8 @@
import android.util.Xml;
import com.android.server.compat.PlatformCompat;
-import com.android.server.pm.parsing.pkg.AndroidPackage;
import com.android.server.pm.parsing.pkg.AndroidPackageUtils;
+import com.android.server.pm.pkg.AndroidPackage;
import com.android.server.pm.pkg.SharedUserApi;
import libcore.io.IoUtils;
diff --git a/services/core/java/com/android/server/pm/ScanPackageUtils.java b/services/core/java/com/android/server/pm/ScanPackageUtils.java
index 86affdd..9bd8e12 100644
--- a/services/core/java/com/android/server/pm/ScanPackageUtils.java
+++ b/services/core/java/com/android/server/pm/ScanPackageUtils.java
@@ -76,9 +76,9 @@
import com.android.server.SystemConfig;
import com.android.server.pm.parsing.PackageInfoUtils;
import com.android.server.pm.parsing.library.PackageBackwardCompatibility;
-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.pm.pkg.AndroidPackage;
import com.android.server.pm.pkg.PackageStateUtils;
import com.android.server.pm.pkg.component.ComponentMutateUtils;
import com.android.server.pm.pkg.component.ParsedActivity;
diff --git a/services/core/java/com/android/server/pm/ScanRequest.java b/services/core/java/com/android/server/pm/ScanRequest.java
index 98d11bd..e66a72f 100644
--- a/services/core/java/com/android/server/pm/ScanRequest.java
+++ b/services/core/java/com/android/server/pm/ScanRequest.java
@@ -21,8 +21,8 @@
import android.os.UserHandle;
import com.android.internal.annotations.VisibleForTesting;
-import com.android.server.pm.parsing.pkg.AndroidPackage;
import com.android.server.pm.parsing.pkg.ParsedPackage;
+import com.android.server.pm.pkg.AndroidPackage;
import com.android.server.pm.pkg.parsing.ParsingPackageUtils;
/** A package to be scanned */
diff --git a/services/core/java/com/android/server/pm/Settings.java b/services/core/java/com/android/server/pm/Settings.java
index 10e9b54..9037f04 100644
--- a/services/core/java/com/android/server/pm/Settings.java
+++ b/services/core/java/com/android/server/pm/Settings.java
@@ -102,12 +102,12 @@
import com.android.server.backup.PreferredActivityBackupHelper;
import com.android.server.pm.Installer.InstallerException;
import com.android.server.pm.parsing.PackageInfoUtils;
-import com.android.server.pm.parsing.pkg.AndroidPackage;
import com.android.server.pm.parsing.pkg.AndroidPackageUtils;
import com.android.server.pm.permission.LegacyPermissionDataProvider;
import com.android.server.pm.permission.LegacyPermissionSettings;
import com.android.server.pm.permission.LegacyPermissionState;
import com.android.server.pm.permission.LegacyPermissionState.PermissionState;
+import com.android.server.pm.pkg.AndroidPackage;
import com.android.server.pm.pkg.PackageStateInternal;
import com.android.server.pm.pkg.PackageUserState;
import com.android.server.pm.pkg.PackageUserStateInternal;
diff --git a/services/core/java/com/android/server/pm/SharedLibrariesImpl.java b/services/core/java/com/android/server/pm/SharedLibrariesImpl.java
index 7432b84..5905741 100644
--- a/services/core/java/com/android/server/pm/SharedLibrariesImpl.java
+++ b/services/core/java/com/android/server/pm/SharedLibrariesImpl.java
@@ -47,9 +47,9 @@
import com.android.internal.util.ArrayUtils;
import com.android.server.SystemConfig;
import com.android.server.compat.PlatformCompat;
-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.pm.pkg.AndroidPackage;
import com.android.server.pm.pkg.PackageStateInternal;
import com.android.server.utils.Snappable;
import com.android.server.utils.SnapshotCache;
diff --git a/services/core/java/com/android/server/pm/SharedUserSetting.java b/services/core/java/com/android/server/pm/SharedUserSetting.java
index 58be878..fb2ba32 100644
--- a/services/core/java/com/android/server/pm/SharedUserSetting.java
+++ b/services/core/java/com/android/server/pm/SharedUserSetting.java
@@ -26,8 +26,8 @@
import android.util.proto.ProtoOutputStream;
import com.android.internal.util.ArrayUtils;
-import com.android.server.pm.parsing.pkg.AndroidPackage;
import com.android.server.pm.permission.LegacyPermissionState;
+import com.android.server.pm.pkg.AndroidPackage;
import com.android.server.pm.pkg.PackageStateInternal;
import com.android.server.pm.pkg.SharedUserApi;
import com.android.server.pm.pkg.component.ComponentMutateUtils;
diff --git a/services/core/java/com/android/server/pm/StagingManager.java b/services/core/java/com/android/server/pm/StagingManager.java
index 43dde5c..1da442b 100644
--- a/services/core/java/com/android/server/pm/StagingManager.java
+++ b/services/core/java/com/android/server/pm/StagingManager.java
@@ -53,8 +53,8 @@
import com.android.server.LocalServices;
import com.android.server.SystemService;
import com.android.server.SystemServiceManager;
-import com.android.server.pm.parsing.pkg.AndroidPackage;
import com.android.server.pm.parsing.pkg.AndroidPackageUtils;
+import com.android.server.pm.pkg.AndroidPackage;
import com.android.server.pm.pkg.PackageStateInternal;
import com.android.server.pm.pkg.PackageStateUtils;
import com.android.server.rollback.RollbackManagerInternal;
diff --git a/services/core/java/com/android/server/pm/StorageEventHelper.java b/services/core/java/com/android/server/pm/StorageEventHelper.java
index 41c6c0f..477e260 100644
--- a/services/core/java/com/android/server/pm/StorageEventHelper.java
+++ b/services/core/java/com/android/server/pm/StorageEventHelper.java
@@ -48,7 +48,7 @@
import com.android.internal.annotations.GuardedBy;
import com.android.internal.policy.AttributeCache;
import com.android.internal.util.IndentingPrintWriter;
-import com.android.server.pm.parsing.pkg.AndroidPackage;
+import com.android.server.pm.pkg.AndroidPackage;
import com.android.server.pm.pkg.PackageStateInternal;
import com.android.server.pm.pkg.parsing.ParsingPackageUtils;
diff --git a/services/core/java/com/android/server/pm/SuspendPackageHelper.java b/services/core/java/com/android/server/pm/SuspendPackageHelper.java
index 6847b70..df7e375 100644
--- a/services/core/java/com/android/server/pm/SuspendPackageHelper.java
+++ b/services/core/java/com/android/server/pm/SuspendPackageHelper.java
@@ -42,7 +42,7 @@
import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.util.ArrayUtils;
import com.android.internal.util.CollectionUtils;
-import com.android.server.pm.parsing.pkg.AndroidPackage;
+import com.android.server.pm.pkg.AndroidPackage;
import com.android.server.pm.pkg.PackageStateInternal;
import com.android.server.pm.pkg.PackageUserStateInternal;
import com.android.server.pm.pkg.SuspendParams;
@@ -157,9 +157,11 @@
}
}
- // If size one, the package will be unsuspended from this call
- boolean packageUnsuspended =
- !suspended && CollectionUtils.size(suspendParamsMap) <= 1;
+ // If only the callingPackage is suspending this package,
+ // it will be unsuspended when this change is committed
+ boolean packageUnsuspended = !suspended
+ && CollectionUtils.size(suspendParamsMap) == 1
+ && suspendParamsMap.containsKey(callingPackage);
if (suspended || packageUnsuspended) {
changedPackagesList.add(packageName);
changedUids.add(UserHandle.getUid(userId, packageState.getAppId()));
diff --git a/services/core/java/com/android/server/pm/UserManagerInternal.java b/services/core/java/com/android/server/pm/UserManagerInternal.java
index b9a1195..4f5fd02 100644
--- a/services/core/java/com/android/server/pm/UserManagerInternal.java
+++ b/services/core/java/com/android/server/pm/UserManagerInternal.java
@@ -46,6 +46,15 @@
public @interface OwnerType {
}
+ // TODO(b/245963156): move to Display.java (and @hide) if we decide to support profiles on MUMD
+ /**
+ * Used only when starting a profile (on systems that
+ * {@link android.os.UserManager#isUsersOnSecondaryDisplaysSupported() support users running on
+ * secondary displays}), to indicate the profile should be started in the same display as its
+ * parent user.
+ */
+ public static final int PARENT_DISPLAY = -2;
+
public interface UserRestrictionsListener {
/**
* Called when a user restriction changes.
diff --git a/services/core/java/com/android/server/pm/UserManagerService.java b/services/core/java/com/android/server/pm/UserManagerService.java
index 6749ceb..07ec80b 100644
--- a/services/core/java/com/android/server/pm/UserManagerService.java
+++ b/services/core/java/com/android/server/pm/UserManagerService.java
@@ -1862,22 +1862,48 @@
}
// TODO(b/239982558): try to merge with isUserVisibleUnchecked() (once both are unit tested)
+ /**
+ * See {@link UserManagerInternal#isUserVisible(int, int)}.
+ */
boolean isUserVisibleOnDisplay(@UserIdInt int userId, int displayId) {
- // TODO(b/244644281): temporary workaround to let WM use this API without breaking current
- // behavior (otherwise current user / profiles wouldn't be able to launch activities on
- // other non-passenger displays, like cluster, display, or virtual displays)
- if (isCurrentUserOrRunningProfileOfCurrentUser(userId)) {
- return true;
+ if (displayId == Display.INVALID_DISPLAY) {
+ return false;
}
-
- if (displayId == Display.DEFAULT_DISPLAY) {
+ if (!mUsersOnSecondaryDisplaysEnabled) {
return isCurrentUserOrRunningProfileOfCurrentUser(userId);
}
- // Device doesn't support multiple users on multiple displays, so only users checked above
- // can be visible
- if (!mUsersOnSecondaryDisplaysEnabled) {
- return false;
+ // TODO(b/244644281): temporary workaround to let WM use this API without breaking current
+ // behavior - return true for current user / profile for any display (other than those
+ // explicitly assigned to another users), otherwise they wouldn't be able to launch
+ // activities on other non-passenger displays, like cluster, display, or virtual displays).
+ // In the long-term, it should rely just on mUsersOnSecondaryDisplays, which
+ // would be updated by DisplayManagerService when displays are created / initialized.
+ if (isCurrentUserOrRunningProfileOfCurrentUser(userId)) {
+ synchronized (mUsersOnSecondaryDisplays) {
+ boolean assignedToUser = false;
+ boolean assignedToAnotherUser = false;
+ for (int i = 0; i < mUsersOnSecondaryDisplays.size(); i++) {
+ if (mUsersOnSecondaryDisplays.valueAt(i) == displayId) {
+ if (mUsersOnSecondaryDisplays.keyAt(i) == userId) {
+ assignedToUser = true;
+ break;
+ } else {
+ assignedToAnotherUser = true;
+ // Cannot break because it could be assigned to a profile of the user
+ // (and we better not assume that the iteration will check for the
+ // parent user before its profiles)
+ }
+ }
+ }
+ if (DBG_MUMD) {
+ Slogf.d(LOG_TAG, "isUserVisibleOnDisplay(%d, %d): assignedToUser=%b, "
+ + "assignedToAnotherUser=%b, mUsersOnSecondaryDisplays=%s",
+ userId, displayId, assignedToUser, assignedToAnotherUser,
+ mUsersOnSecondaryDisplays);
+ }
+ return assignedToUser || !assignedToAnotherUser;
+ }
}
synchronized (mUsersOnSecondaryDisplays) {
@@ -6578,9 +6604,14 @@
@Override
public boolean isUserRunning(@UserIdInt int userId) {
+ int state;
synchronized (mUserStates) {
- return mUserStates.get(userId, -1) >= 0;
+ state = mUserStates.get(userId, UserState.STATE_NONE);
}
+
+ return state != UserState.STATE_NONE
+ && state != UserState.STATE_STOPPING
+ && state != UserState.STATE_SHUTDOWN;
}
@Override
@@ -6794,53 +6825,44 @@
int currentUserId = getCurrentUserId();
Preconditions.checkArgument(userId != currentUserId,
- "Cannot assign current user to other displays");
-
- boolean isProfile = isProfileUnchecked(userId);
-
- Preconditions.checkArgument(userId != currentUserId,
- "Cannot assign current user to other displays");
-
- Preconditions.checkArgument(
- !isProfile || getProfileParentIdUnchecked(userId) != currentUserId,
- "Cannot assign profile user %d to display %d when its parent is the current "
- + "user (%d)", userId, displayId, currentUserId);
+ "Cannot assign current user (%d) to other displays", currentUserId);
synchronized (mUsersOnSecondaryDisplays) {
- if (DBG_MUMD) {
- Slogf.d(LOG_TAG, "Adding %d->%d to mUsersOnSecondaryDisplays",
- userId, displayId);
- }
-
- if (isProfile) {
+ if (isProfileUnchecked(userId)) {
// Profile can only start in the same display as parent
+ Preconditions.checkArgument(displayId == UserManagerInternal.PARENT_DISPLAY,
+ "Profile user can only be started in the same display as parent");
int parentUserId = getProfileParentId(userId);
int parentDisplayId = mUsersOnSecondaryDisplays.get(parentUserId);
- if (displayId != parentDisplayId) {
- throw new IllegalStateException("Cannot assign profile " + userId + " to "
- + "display " + displayId + " as its parent (user " + parentUserId
- + ") is assigned to display " + parentDisplayId);
+ if (DBG_MUMD) {
+ Slogf.d(LOG_TAG, "Adding profile user %d -> display %d", userId,
+ parentDisplayId);
}
- } else {
- // Check if display is available
- for (int i = 0; i < mUsersOnSecondaryDisplays.size(); i++) {
- // Make sure display is not used by other users...
- // TODO(b/240736142); currently, if a user was started in a display, it
- // would need to be stopped first, so "switching" a user on secondary
- // diplay requires 2 non-atomic operations (stop and start). Once this logic
- // is refactored, it should be atomic.
- if (mUsersOnSecondaryDisplays.valueAt(i) == displayId) {
- throw new IllegalStateException("Cannot assign " + userId + " to "
- + "display " + displayId + " as it's already assigned to "
- + "user " + mUsersOnSecondaryDisplays.keyAt(i));
- }
- // TODO(b/239982558) also check that user is not already assigned to other
- // display (including 0). That would be harder to tested under CTS though
- // (for example, would need to add a new AM method to start user in bg on
- // main display), so it's better to test on unit tests
- }
+ mUsersOnSecondaryDisplays.put(userId, parentDisplayId);
+ return;
}
+ // Check if display is available
+ for (int i = 0; i < mUsersOnSecondaryDisplays.size(); i++) {
+ // Make sure display is not used by other users...
+ // TODO(b/240736142); currently, if a user was started in a display, it
+ // would need to be stopped first, so "switching" a user on secondary
+ // diplay requires 2 non-atomic operations (stop and start). Once this logic
+ // is refactored, it should be atomic.
+ if (mUsersOnSecondaryDisplays.valueAt(i) == displayId) {
+ throw new IllegalStateException("Cannot assign " + userId + " to "
+ + "display " + displayId + " as it's already assigned to "
+ + "user " + mUsersOnSecondaryDisplays.keyAt(i));
+ }
+ // TODO(b/239982558) also check that user is not already assigned to other
+ // display (including 0). That would be harder to tested under CTS though
+ // (for example, would need to add a new AM method to start user in bg on
+ // main display), so it's better to test on unit tests
+ }
+
+ if (DBG_MUMD) {
+ Slogf.d(LOG_TAG, "Adding full user %d -> display %d", userId, displayId);
+ }
mUsersOnSecondaryDisplays.put(userId, displayId);
}
}
diff --git a/services/core/java/com/android/server/pm/UserManagerServiceShellCommand.java b/services/core/java/com/android/server/pm/UserManagerServiceShellCommand.java
index 8f13f7a..6e86123 100644
--- a/services/core/java/com/android/server/pm/UserManagerServiceShellCommand.java
+++ b/services/core/java/com/android/server/pm/UserManagerServiceShellCommand.java
@@ -35,7 +35,6 @@
import android.os.UserManager;
import android.util.IndentingPrintWriter;
import android.util.Slog;
-import android.view.Display;
import com.android.internal.widget.LockPatternUtils;
import com.android.server.LocalServices;
@@ -374,21 +373,16 @@
})
private int runIsUserVisible() {
PrintWriter pw = getOutPrintWriter();
- int displayId = Display.INVALID_DISPLAY;
+ Integer displayId = null;
String opt;
while ((opt = getNextOption()) != null) {
- boolean invalidOption = false;
switch (opt) {
case "--display":
displayId = Integer.parseInt(getNextArgRequired());
- invalidOption = displayId == Display.INVALID_DISPLAY;
break;
default:
- invalidOption = true;
- }
- if (invalidOption) {
- pw.println("Invalid option: " + opt);
- return -1;
+ pw.println("Invalid option: " + opt);
+ return -1;
}
}
int userId = UserHandle.parseUserArg(getNextArgRequired());
@@ -404,7 +398,7 @@
}
boolean isVisible;
- if (displayId != Display.INVALID_DISPLAY) {
+ if (displayId != null) {
isVisible = mService.isUserVisibleOnDisplay(userId, displayId);
} else {
isVisible = getUserManagerForUser(userId).isUserVisible();
diff --git a/services/core/java/com/android/server/pm/UserSystemPackageInstaller.java b/services/core/java/com/android/server/pm/UserSystemPackageInstaller.java
index b57d4d5..2d876ed 100644
--- a/services/core/java/com/android/server/pm/UserSystemPackageInstaller.java
+++ b/services/core/java/com/android/server/pm/UserSystemPackageInstaller.java
@@ -35,7 +35,7 @@
import com.android.internal.annotations.VisibleForTesting;
import com.android.server.LocalServices;
import com.android.server.SystemConfig;
-import com.android.server.pm.parsing.pkg.AndroidPackage;
+import com.android.server.pm.pkg.AndroidPackage;
import com.android.server.pm.pkg.PackageStateInternal;
import java.lang.annotation.Retention;
diff --git a/services/core/java/com/android/server/pm/dex/ArtManagerService.java b/services/core/java/com/android/server/pm/dex/ArtManagerService.java
index cca3b35..6bc323e 100644
--- a/services/core/java/com/android/server/pm/dex/ArtManagerService.java
+++ b/services/core/java/com/android/server/pm/dex/ArtManagerService.java
@@ -54,7 +54,7 @@
import com.android.server.pm.Installer.InstallerException;
import com.android.server.pm.PackageManagerServiceCompilerMapping;
import com.android.server.pm.parsing.PackageInfoUtils;
-import com.android.server.pm.parsing.pkg.AndroidPackage;
+import com.android.server.pm.pkg.AndroidPackage;
import dalvik.system.DexFile;
import dalvik.system.VMRuntime;
diff --git a/services/core/java/com/android/server/pm/dex/ArtUtils.java b/services/core/java/com/android/server/pm/dex/ArtUtils.java
index 068a064..77aefc5c 100644
--- a/services/core/java/com/android/server/pm/dex/ArtUtils.java
+++ b/services/core/java/com/android/server/pm/dex/ArtUtils.java
@@ -21,8 +21,8 @@
import android.annotation.NonNull;
import com.android.server.pm.PackageDexOptimizer;
-import com.android.server.pm.parsing.pkg.AndroidPackage;
import com.android.server.pm.parsing.pkg.AndroidPackageUtils;
+import com.android.server.pm.pkg.AndroidPackage;
import com.android.server.pm.pkg.PackageStateInternal;
import java.io.File;
diff --git a/services/core/java/com/android/server/pm/dex/DexoptUtils.java b/services/core/java/com/android/server/pm/dex/DexoptUtils.java
index beea86d..5ba209d 100644
--- a/services/core/java/com/android/server/pm/dex/DexoptUtils.java
+++ b/services/core/java/com/android/server/pm/dex/DexoptUtils.java
@@ -23,7 +23,7 @@
import com.android.internal.os.ClassLoaderFactory;
import com.android.internal.util.ArrayUtils;
-import com.android.server.pm.parsing.pkg.AndroidPackage;
+import com.android.server.pm.pkg.AndroidPackage;
import java.io.File;
import java.util.List;
diff --git a/services/core/java/com/android/server/pm/dex/ViewCompiler.java b/services/core/java/com/android/server/pm/dex/ViewCompiler.java
index ee66a5586..9ce648f 100644
--- a/services/core/java/com/android/server/pm/dex/ViewCompiler.java
+++ b/services/core/java/com/android/server/pm/dex/ViewCompiler.java
@@ -23,7 +23,7 @@
import com.android.internal.annotations.GuardedBy;
import com.android.server.pm.Installer;
import com.android.server.pm.parsing.PackageInfoUtils;
-import com.android.server.pm.parsing.pkg.AndroidPackage;
+import com.android.server.pm.pkg.AndroidPackage;
import java.io.File;
diff --git a/services/core/java/com/android/server/pm/parsing/PackageInfoUtils.java b/services/core/java/com/android/server/pm/parsing/PackageInfoUtils.java
index 5be81d5..1084145 100644
--- a/services/core/java/com/android/server/pm/parsing/PackageInfoUtils.java
+++ b/services/core/java/com/android/server/pm/parsing/PackageInfoUtils.java
@@ -54,9 +54,9 @@
import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.util.ArrayUtils;
-import com.android.server.pm.parsing.pkg.AndroidPackage;
import com.android.server.pm.parsing.pkg.AndroidPackageUtils;
import com.android.server.pm.parsing.pkg.PackageImpl;
+import com.android.server.pm.pkg.AndroidPackage;
import com.android.server.pm.pkg.PackageStateInternal;
import com.android.server.pm.pkg.PackageStateUnserialized;
import com.android.server.pm.pkg.PackageUserState;
diff --git a/services/core/java/com/android/server/pm/parsing/library/AndroidTestBaseUpdater.java b/services/core/java/com/android/server/pm/parsing/library/AndroidTestBaseUpdater.java
index c67d0d2..7031dc3 100644
--- a/services/core/java/com/android/server/pm/parsing/library/AndroidTestBaseUpdater.java
+++ b/services/core/java/com/android/server/pm/parsing/library/AndroidTestBaseUpdater.java
@@ -28,9 +28,9 @@
import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.compat.IPlatformCompat;
-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.pm.pkg.AndroidPackage;
/**
* Updates a package to ensure that if it targets <= Q that the android.test.base library is
diff --git a/services/core/java/com/android/server/pm/parsing/library/OrgApacheHttpLegacyUpdater.java b/services/core/java/com/android/server/pm/parsing/library/OrgApacheHttpLegacyUpdater.java
index 7de457e..96fead2 100644
--- a/services/core/java/com/android/server/pm/parsing/library/OrgApacheHttpLegacyUpdater.java
+++ b/services/core/java/com/android/server/pm/parsing/library/OrgApacheHttpLegacyUpdater.java
@@ -20,8 +20,8 @@
import android.os.Build;
import com.android.internal.annotations.VisibleForTesting;
-import com.android.server.pm.parsing.pkg.AndroidPackage;
import com.android.server.pm.parsing.pkg.ParsedPackage;
+import com.android.server.pm.pkg.AndroidPackage;
/**
* Updates a package to ensure that if it targets < P that the org.apache.http.legacy library is
diff --git a/services/core/java/com/android/server/pm/parsing/pkg/AndroidPackage.java b/services/core/java/com/android/server/pm/parsing/pkg/AndroidPackageInternal.java
similarity index 86%
rename from services/core/java/com/android/server/pm/parsing/pkg/AndroidPackage.java
rename to services/core/java/com/android/server/pm/parsing/pkg/AndroidPackageInternal.java
index b314fe2..8d43fe7 100644
--- a/services/core/java/com/android/server/pm/parsing/pkg/AndroidPackage.java
+++ b/services/core/java/com/android/server/pm/parsing/pkg/AndroidPackageInternal.java
@@ -17,7 +17,7 @@
package com.android.server.pm.parsing.pkg;
import com.android.internal.content.om.OverlayConfig;
-import com.android.server.pm.pkg.AndroidPackageApi;
+import com.android.server.pm.pkg.AndroidPackage;
/**
* The last state of a package during parsing/install before it is available in {@link
@@ -29,6 +29,7 @@
*
* @hide
*/
-public interface AndroidPackage extends AndroidPackageApi, OverlayConfig.PackageProvider.Package {
+public interface AndroidPackageInternal extends AndroidPackage,
+ OverlayConfig.PackageProvider.Package {
}
diff --git a/services/core/java/com/android/server/pm/parsing/pkg/AndroidPackageUtils.java b/services/core/java/com/android/server/pm/parsing/pkg/AndroidPackageUtils.java
index 76bae37..f6585f6 100644
--- a/services/core/java/com/android/server/pm/parsing/pkg/AndroidPackageUtils.java
+++ b/services/core/java/com/android/server/pm/parsing/pkg/AndroidPackageUtils.java
@@ -33,7 +33,7 @@
import com.android.internal.util.ArrayUtils;
import com.android.server.SystemConfig;
import com.android.server.pm.PackageManagerException;
-import com.android.server.pm.pkg.AndroidPackageApi;
+import com.android.server.pm.pkg.AndroidPackage;
import com.android.server.pm.pkg.PackageStateInternal;
import com.android.server.pm.pkg.component.ParsedActivity;
import com.android.server.pm.pkg.component.ParsedInstrumentation;
@@ -340,7 +340,7 @@
info.versionCodeMajor = ((ParsingPackageHidden) pkg).getVersionCodeMajor();
}
- public static ApplicationInfo toAppInfoWithoutState(AndroidPackageApi pkg) {
+ public static ApplicationInfo toAppInfoWithoutState(AndroidPackage pkg) {
return ((ParsingPackageHidden) pkg).toAppInfoWithoutState();
}
}
diff --git a/services/core/java/com/android/server/pm/parsing/pkg/PackageImpl.java b/services/core/java/com/android/server/pm/parsing/pkg/PackageImpl.java
index 11fb78f..70aca99 100644
--- a/services/core/java/com/android/server/pm/parsing/pkg/PackageImpl.java
+++ b/services/core/java/com/android/server/pm/parsing/pkg/PackageImpl.java
@@ -56,6 +56,7 @@
import com.android.internal.util.Parcelling;
import com.android.internal.util.Parcelling.BuiltIn.ForInternedString;
import com.android.server.pm.parsing.PackageInfoUtils;
+import com.android.server.pm.pkg.AndroidPackage;
import com.android.server.pm.pkg.SELinuxUtil;
import com.android.server.pm.pkg.component.ComponentMutateUtils;
import com.android.server.pm.pkg.component.ParsedActivity;
@@ -102,7 +103,7 @@
*
* @hide
*/
-public class PackageImpl implements ParsedPackage, AndroidPackage,
+public class PackageImpl implements ParsedPackage, AndroidPackageInternal,
AndroidPackageHidden, ParsingPackage, ParsingPackageHidden, Parcelable {
private static final SparseArray<int[]> EMPTY_INT_ARRAY_SPARSE_ARRAY = new SparseArray<>();
@@ -2591,7 +2592,7 @@
}
@Override
- public AndroidPackage hideAsFinal() {
+ public AndroidPackageInternal hideAsFinal() {
// TODO(b/135203078): Lock as immutable
if (mStorageUuid == null) {
assignDerivedFields();
diff --git a/services/core/java/com/android/server/pm/parsing/pkg/ParsedPackage.java b/services/core/java/com/android/server/pm/parsing/pkg/ParsedPackage.java
index 38d87e2..d306341 100644
--- a/services/core/java/com/android/server/pm/parsing/pkg/ParsedPackage.java
+++ b/services/core/java/com/android/server/pm/parsing/pkg/ParsedPackage.java
@@ -18,17 +18,22 @@
import android.content.pm.SigningDetails;
+import com.android.server.pm.pkg.AndroidPackage;
+
/**
* Methods used for mutation after direct package parsing, mostly done inside
* {@link com.android.server.pm.PackageManagerService}.
*
* Java disallows defining this as an inner interface, so this must be a separate file.
*
+ * TODO: Remove extending AndroidPackage, should be an isolated interface with only the methods
+ * necessary to parse and install
+ *
* @hide
*/
public interface ParsedPackage extends AndroidPackage {
- AndroidPackage hideAsFinal();
+ AndroidPackageInternal hideAsFinal();
ParsedPackage addUsesLibrary(int index, String libraryName);
diff --git a/services/core/java/com/android/server/pm/permission/Permission.java b/services/core/java/com/android/server/pm/permission/Permission.java
index d5456e3..69e7bf1 100644
--- a/services/core/java/com/android/server/pm/permission/Permission.java
+++ b/services/core/java/com/android/server/pm/permission/Permission.java
@@ -23,14 +23,14 @@
import android.content.pm.PackageManager;
import android.content.pm.PackageManagerInternal;
import android.content.pm.PermissionInfo;
-import com.android.server.pm.pkg.component.ParsedPermission;
import android.os.Build;
import android.os.UserHandle;
import android.util.Log;
import android.util.Slog;
import com.android.server.pm.PackageManagerService;
-import com.android.server.pm.parsing.pkg.AndroidPackage;
+import com.android.server.pm.pkg.AndroidPackage;
+import com.android.server.pm.pkg.component.ParsedPermission;
import libcore.util.EmptyArray;
diff --git a/services/core/java/com/android/server/pm/permission/PermissionManagerService.java b/services/core/java/com/android/server/pm/permission/PermissionManagerService.java
index 3df412d..3b9f0ba 100644
--- a/services/core/java/com/android/server/pm/permission/PermissionManagerService.java
+++ b/services/core/java/com/android/server/pm/permission/PermissionManagerService.java
@@ -72,8 +72,8 @@
import com.android.server.LocalServices;
import com.android.server.pm.UserManagerInternal;
import com.android.server.pm.UserManagerService;
-import com.android.server.pm.parsing.pkg.AndroidPackage;
import com.android.server.pm.permission.PermissionManagerServiceInternal.HotwordDetectionServiceProvider;
+import com.android.server.pm.pkg.AndroidPackage;
import java.util.ArrayList;
import java.util.Collections;
diff --git a/services/core/java/com/android/server/pm/permission/PermissionManagerServiceImpl.java b/services/core/java/com/android/server/pm/permission/PermissionManagerServiceImpl.java
index 4c095fb..4a80c4a 100644
--- a/services/core/java/com/android/server/pm/permission/PermissionManagerServiceImpl.java
+++ b/services/core/java/com/android/server/pm/permission/PermissionManagerServiceImpl.java
@@ -131,9 +131,8 @@
import com.android.server.pm.UserManagerInternal;
import com.android.server.pm.UserManagerService;
import com.android.server.pm.parsing.PackageInfoUtils;
-import com.android.server.pm.parsing.pkg.AndroidPackage;
import com.android.server.pm.parsing.pkg.AndroidPackageUtils;
-import com.android.server.pm.pkg.AndroidPackageApi;
+import com.android.server.pm.pkg.AndroidPackage;
import com.android.server.pm.pkg.PackageStateInternal;
import com.android.server.pm.pkg.component.ComponentMutateUtils;
import com.android.server.pm.pkg.component.ParsedPermission;
@@ -2612,7 +2611,7 @@
mPackageManagerInt.getSharedUserPackages(ps.getSharedUserAppId());
int packagesSize = packages.size();
for (int i = 0; i < packagesSize; i++) {
- AndroidPackageApi sharedUserPackage =
+ AndroidPackage sharedUserPackage =
packages.valueAt(i).getAndroidPackage();
if (sharedUserPackage == null) {
continue;
diff --git a/services/core/java/com/android/server/pm/permission/PermissionManagerServiceInterface.java b/services/core/java/com/android/server/pm/permission/PermissionManagerServiceInterface.java
index 02d184e..930936b 100644
--- a/services/core/java/com/android/server/pm/permission/PermissionManagerServiceInterface.java
+++ b/services/core/java/com/android/server/pm/permission/PermissionManagerServiceInterface.java
@@ -25,9 +25,10 @@
import android.content.pm.PermissionInfo;
import android.content.pm.permission.SplitPermissionInfoParcelable;
import android.permission.IOnPermissionsChangeListener;
+import android.permission.PermissionManager;
import android.permission.PermissionManagerInternal;
-import com.android.server.pm.parsing.pkg.AndroidPackage;
+import com.android.server.pm.pkg.AndroidPackage;
import java.io.FileDescriptor;
import java.io.PrintWriter;
diff --git a/services/core/java/com/android/server/pm/permission/PermissionManagerServiceInternal.java b/services/core/java/com/android/server/pm/permission/PermissionManagerServiceInternal.java
index 2d5ec39..f20620e 100644
--- a/services/core/java/com/android/server/pm/permission/PermissionManagerServiceInternal.java
+++ b/services/core/java/com/android/server/pm/permission/PermissionManagerServiceInternal.java
@@ -23,7 +23,7 @@
import android.content.pm.PermissionInfo;
import android.permission.PermissionManagerInternal;
-import com.android.server.pm.parsing.pkg.AndroidPackage;
+import com.android.server.pm.pkg.AndroidPackage;
import java.util.ArrayList;
import java.util.Collections;
diff --git a/services/core/java/com/android/server/pm/pkg/AndroidPackageApi.java b/services/core/java/com/android/server/pm/pkg/AndroidPackage.java
similarity index 99%
rename from services/core/java/com/android/server/pm/pkg/AndroidPackageApi.java
rename to services/core/java/com/android/server/pm/pkg/AndroidPackage.java
index a454bcd..6078d4a 100644
--- a/services/core/java/com/android/server/pm/pkg/AndroidPackageApi.java
+++ b/services/core/java/com/android/server/pm/pkg/AndroidPackage.java
@@ -40,7 +40,6 @@
import android.util.SparseIntArray;
import com.android.internal.R;
-import com.android.server.pm.parsing.pkg.AndroidPackage;
import com.android.server.pm.pkg.component.ParsedActivity;
import com.android.server.pm.pkg.component.ParsedApexSystemService;
import com.android.server.pm.pkg.component.ParsedAttribution;
@@ -66,7 +65,7 @@
* @hide
*/
//@SystemApi(client = SystemApi.Client.SYSTEM_SERVER)
-public interface AndroidPackageApi {
+public interface AndroidPackage {
/**
* @see ApplicationInfo#areAttributionsUserVisible()
diff --git a/services/core/java/com/android/server/pm/pkg/PackageState.java b/services/core/java/com/android/server/pm/pkg/PackageState.java
index b5e0e44..f0e386c 100644
--- a/services/core/java/com/android/server/pm/pkg/PackageState.java
+++ b/services/core/java/com/android/server/pm/pkg/PackageState.java
@@ -74,7 +74,7 @@
* app once the device reboots or otherwise re-scans it.
*/
@Nullable
- AndroidPackageApi getAndroidPackage();
+ AndroidPackage getAndroidPackage();
/**
* The non-user-specific UID, or the UID if the user ID is
@@ -86,7 +86,7 @@
* Value set through {@link PackageManager#setApplicationCategoryHint(String, int)}. Only
* applied if the application itself does not declare a category.
*
- * @see AndroidPackageApi#getCategory()
+ * @see AndroidPackage#getCategory()
*/
int getCategoryOverride();
@@ -121,7 +121,7 @@
/**
* Cached here in case the physical code directory on device is unmounted.
- * @see AndroidPackageApi#getLongVersionCode()
+ * @see AndroidPackage#getLongVersionCode()
*/
long getVersionCode();
@@ -134,14 +134,14 @@
Map<String, Set<String>> getMimeGroups();
/**
- * @see AndroidPackageApi#getPackageName()
+ * @see AndroidPackage#getPackageName()
*/
@NonNull
String getPackageName();
/**
* TODO: Rename this to getCodePath
- * @see AndroidPackageApi#getPath()
+ * @see AndroidPackage#getPath()
*/
@NonNull
File getPath();
@@ -227,13 +227,13 @@
long[] getUsesStaticLibrariesVersions();
/**
- * @see AndroidPackageApi#getVolumeUuid()
+ * @see AndroidPackage#getVolumeUuid()
*/
@Nullable
String getVolumeUuid();
/**
- * @see AndroidPackageApi#isExternalStorage()
+ * @see AndroidPackage#isExternalStorage()
*/
boolean isExternalStorage();
@@ -257,22 +257,22 @@
boolean isInstallPermissionsFixed();
/**
- * @see AndroidPackageApi#isOdm()
+ * @see AndroidPackage#isOdm()
*/
boolean isOdm();
/**
- * @see AndroidPackageApi#isOem()
+ * @see AndroidPackage#isOem()
*/
boolean isOem();
/**
- * @see AndroidPackageApi#isPrivileged()
+ * @see AndroidPackage#isPrivileged()
*/
boolean isPrivileged();
/**
- * @see AndroidPackageApi#isProduct()
+ * @see AndroidPackage#isProduct()
*/
boolean isProduct();
@@ -282,12 +282,12 @@
boolean isRequiredForSystemUser();
/**
- * @see AndroidPackageApi#isSystem()
+ * @see AndroidPackage#isSystem()
*/
boolean isSystem();
/**
- * @see AndroidPackageApi#isSystemExt()
+ * @see AndroidPackage#isSystemExt()
*/
boolean isSystemExt();
@@ -308,7 +308,7 @@
boolean isApkInUpdatedApex();
/**
- * @see AndroidPackageApi#isVendor()
+ * @see AndroidPackage#isVendor()
*/
boolean isVendor();
}
diff --git a/services/core/java/com/android/server/pm/pkg/PackageStateImpl.java b/services/core/java/com/android/server/pm/pkg/PackageStateImpl.java
index 878a837..eac0842 100644
--- a/services/core/java/com/android/server/pm/pkg/PackageStateImpl.java
+++ b/services/core/java/com/android/server/pm/pkg/PackageStateImpl.java
@@ -31,7 +31,6 @@
import com.android.server.pm.PackageManagerService;
import com.android.server.pm.PackageSetting;
import com.android.server.pm.Settings;
-import com.android.server.pm.parsing.pkg.AndroidPackage;
import java.io.File;
import java.util.List;
@@ -108,7 +107,7 @@
}
@Nullable
- private final AndroidPackageApi mAndroidPackage;
+ private final AndroidPackage mAndroidPackage;
@NonNull
private final String mPackageName;
@@ -570,7 +569,7 @@
}
@DataClass.Generated.Member
- public @Nullable AndroidPackageApi getAndroidPackage() {
+ public @Nullable AndroidPackage getAndroidPackage() {
return mAndroidPackage;
}
@@ -694,7 +693,7 @@
time = 1644270981543L,
codegenVersion = "1.0.23",
sourceFile = "frameworks/base/services/core/java/com/android/server/pm/pkg/PackageStateImpl.java",
- inputSignatures = "private int mBooleans\nprivate final @android.annotation.Nullable com.android.server.pm.pkg.AndroidPackageApi mAndroidPackage\nprivate final @android.annotation.NonNull java.lang.String mPackageName\nprivate final @android.annotation.Nullable java.lang.String mVolumeUuid\nprivate final int mAppId\nprivate final int mCategoryOverride\nprivate final @android.annotation.Nullable java.lang.String mCpuAbiOverride\nprivate final long mLastModifiedTime\nprivate final long mLastUpdateTime\nprivate final long mLongVersionCode\nprivate final @android.annotation.NonNull java.util.Map<java.lang.String,java.util.Set<java.lang.String>> mMimeGroups\nprivate final @android.annotation.NonNull java.io.File mPath\nprivate final @android.annotation.Nullable java.lang.String mPrimaryCpuAbi\nprivate final @android.annotation.Nullable java.lang.String mSecondaryCpuAbi\nprivate final boolean mHasSharedUser\nprivate final int mSharedUserAppId\nprivate final @android.annotation.NonNull java.lang.String[] mUsesSdkLibraries\nprivate final @android.annotation.NonNull long[] mUsesSdkLibrariesVersionsMajor\nprivate final @android.annotation.NonNull java.lang.String[] mUsesStaticLibraries\nprivate final @android.annotation.NonNull long[] mUsesStaticLibrariesVersions\nprivate final @android.annotation.NonNull java.util.List<android.content.pm.SharedLibraryInfo> mUsesLibraryInfos\nprivate final @android.annotation.NonNull java.util.List<java.lang.String> mUsesLibraryFiles\nprivate final @android.annotation.NonNull long[] mLastPackageUsageTime\nprivate final @android.annotation.NonNull android.content.pm.SigningInfo mSigningInfo\nprivate final @android.annotation.NonNull android.util.SparseArray<com.android.server.pm.pkg.PackageUserState> mUserStates\npublic static com.android.server.pm.pkg.PackageState copy(com.android.server.pm.pkg.PackageStateInternal)\nprivate void setBoolean(int,boolean)\nprivate boolean getBoolean(int)\npublic @java.lang.Override boolean isExternalStorage()\npublic @java.lang.Override boolean isForceQueryableOverride()\npublic @java.lang.Override boolean isHiddenUntilInstalled()\npublic @java.lang.Override boolean isInstallPermissionsFixed()\npublic @java.lang.Override boolean isOdm()\npublic @java.lang.Override boolean isOem()\npublic @java.lang.Override boolean isPrivileged()\npublic @java.lang.Override boolean isProduct()\npublic @java.lang.Override boolean isRequiredForSystemUser()\npublic @java.lang.Override boolean isSystem()\npublic @java.lang.Override boolean isSystemExt()\npublic @java.lang.Override boolean isUpdateAvailable()\npublic @java.lang.Override boolean isUpdatedSystemApp()\npublic @java.lang.Override boolean isVendor()\npublic @java.lang.Override long getVersionCode()\npublic @java.lang.Override boolean hasSharedUser()\npublic @java.lang.Override int getSharedUserAppId()\nclass PackageStateImpl extends java.lang.Object implements [com.android.server.pm.pkg.PackageState]\nprivate static final int SYSTEM\nprivate static final int EXTERNAL_STORAGE\nprivate static final int PRIVILEGED\nprivate static final int OEM\nprivate static final int VENDOR\nprivate static final int PRODUCT\nprivate static final int SYSTEM_EXT\nprivate static final int REQUIRED_FOR_SYSTEM_USER\nprivate static final int ODM\nprivate static final int FORCE_QUERYABLE_OVERRIDE\nprivate static final int HIDDEN_UNTIL_INSTALLED\nprivate static final int INSTALL_PERMISSIONS_FIXED\nprivate static final int UPDATE_AVAILABLE\nprivate static final int UPDATED_SYSTEM_APP\nclass Booleans extends java.lang.Object implements []\n@com.android.internal.util.DataClass(genConstructor=false)")
+ inputSignatures = "private int mBooleans\nprivate final @android.annotation.Nullable com.android.server.pm.pkg.AndroidPackage mAndroidPackage\nprivate final @android.annotation.NonNull java.lang.String mPackageName\nprivate final @android.annotation.Nullable java.lang.String mVolumeUuid\nprivate final int mAppId\nprivate final int mCategoryOverride\nprivate final @android.annotation.Nullable java.lang.String mCpuAbiOverride\nprivate final long mLastModifiedTime\nprivate final long mLastUpdateTime\nprivate final long mLongVersionCode\nprivate final @android.annotation.NonNull java.util.Map<java.lang.String,java.util.Set<java.lang.String>> mMimeGroups\nprivate final @android.annotation.NonNull java.io.File mPath\nprivate final @android.annotation.Nullable java.lang.String mPrimaryCpuAbi\nprivate final @android.annotation.Nullable java.lang.String mSecondaryCpuAbi\nprivate final boolean mHasSharedUser\nprivate final int mSharedUserAppId\nprivate final @android.annotation.NonNull java.lang.String[] mUsesSdkLibraries\nprivate final @android.annotation.NonNull long[] mUsesSdkLibrariesVersionsMajor\nprivate final @android.annotation.NonNull java.lang.String[] mUsesStaticLibraries\nprivate final @android.annotation.NonNull long[] mUsesStaticLibrariesVersions\nprivate final @android.annotation.NonNull java.util.List<android.content.pm.SharedLibraryInfo> mUsesLibraryInfos\nprivate final @android.annotation.NonNull java.util.List<java.lang.String> mUsesLibraryFiles\nprivate final @android.annotation.NonNull long[] mLastPackageUsageTime\nprivate final @android.annotation.NonNull android.content.pm.SigningInfo mSigningInfo\nprivate final @android.annotation.NonNull android.util.SparseArray<com.android.server.pm.pkg.PackageUserState> mUserStates\npublic static com.android.server.pm.pkg.PackageState copy(com.android.server.pm.pkg.PackageStateInternal)\nprivate void setBoolean(int,boolean)\nprivate boolean getBoolean(int)\npublic @java.lang.Override boolean isExternalStorage()\npublic @java.lang.Override boolean isForceQueryableOverride()\npublic @java.lang.Override boolean isHiddenUntilInstalled()\npublic @java.lang.Override boolean isInstallPermissionsFixed()\npublic @java.lang.Override boolean isOdm()\npublic @java.lang.Override boolean isOem()\npublic @java.lang.Override boolean isPrivileged()\npublic @java.lang.Override boolean isProduct()\npublic @java.lang.Override boolean isRequiredForSystemUser()\npublic @java.lang.Override boolean isSystem()\npublic @java.lang.Override boolean isSystemExt()\npublic @java.lang.Override boolean isUpdateAvailable()\npublic @java.lang.Override boolean isUpdatedSystemApp()\npublic @java.lang.Override boolean isVendor()\npublic @java.lang.Override long getVersionCode()\npublic @java.lang.Override boolean hasSharedUser()\npublic @java.lang.Override int getSharedUserAppId()\nclass PackageStateImpl extends java.lang.Object implements [com.android.server.pm.pkg.PackageState]\nprivate static final int SYSTEM\nprivate static final int EXTERNAL_STORAGE\nprivate static final int PRIVILEGED\nprivate static final int OEM\nprivate static final int VENDOR\nprivate static final int PRODUCT\nprivate static final int SYSTEM_EXT\nprivate static final int REQUIRED_FOR_SYSTEM_USER\nprivate static final int ODM\nprivate static final int FORCE_QUERYABLE_OVERRIDE\nprivate static final int HIDDEN_UNTIL_INSTALLED\nprivate static final int INSTALL_PERMISSIONS_FIXED\nprivate static final int UPDATE_AVAILABLE\nprivate static final int UPDATED_SYSTEM_APP\nclass Booleans extends java.lang.Object implements []\n@com.android.internal.util.DataClass(genConstructor=false)")
@Deprecated
private void __metadata() {}
diff --git a/services/core/java/com/android/server/pm/pkg/PackageStateInternal.java b/services/core/java/com/android/server/pm/pkg/PackageStateInternal.java
index 68a00a9..84799ea 100644
--- a/services/core/java/com/android/server/pm/pkg/PackageStateInternal.java
+++ b/services/core/java/com/android/server/pm/pkg/PackageStateInternal.java
@@ -24,7 +24,7 @@
import com.android.server.pm.InstallSource;
import com.android.server.pm.PackageKeySetData;
-import com.android.server.pm.parsing.pkg.AndroidPackage;
+import com.android.server.pm.parsing.pkg.AndroidPackageInternal;
import com.android.server.pm.permission.LegacyPermissionState;
import java.util.UUID;
@@ -35,7 +35,7 @@
public interface PackageStateInternal extends PackageState {
@NonNull
- AndroidPackage getPkg();
+ AndroidPackageInternal getPkg();
// TODO: Remove in favor of exposing APIs directly?
@NonNull
diff --git a/services/core/java/com/android/server/pm/pkg/PackageStateUtils.java b/services/core/java/com/android/server/pm/pkg/PackageStateUtils.java
index 91e9b2f..a883a05 100644
--- a/services/core/java/com/android/server/pm/pkg/PackageStateUtils.java
+++ b/services/core/java/com/android/server/pm/pkg/PackageStateUtils.java
@@ -20,11 +20,9 @@
import android.annotation.Nullable;
import android.content.pm.ComponentInfo;
import android.content.pm.PackageManager;
-import com.android.server.pm.pkg.component.ParsedMainComponent;
-
import android.util.SparseArray;
-import com.android.server.pm.parsing.pkg.AndroidPackage;
+import com.android.server.pm.pkg.component.ParsedMainComponent;
public class PackageStateUtils {
diff --git a/services/core/java/com/android/server/pm/pkg/PackageUserStateUtils.java b/services/core/java/com/android/server/pm/pkg/PackageUserStateUtils.java
index 3bdebd1..15e3d0c 100644
--- a/services/core/java/com/android/server/pm/pkg/PackageUserStateUtils.java
+++ b/services/core/java/com/android/server/pm/pkg/PackageUserStateUtils.java
@@ -26,7 +26,6 @@
import android.util.DebugUtils;
import android.util.Slog;
-import com.android.server.pm.parsing.pkg.AndroidPackage;
import com.android.server.pm.pkg.component.ParsedMainComponent;
/** @hide */
diff --git a/services/core/java/com/android/server/pm/pkg/SharedUserApi.java b/services/core/java/com/android/server/pm/pkg/SharedUserApi.java
index 94a87f3..55c305c 100644
--- a/services/core/java/com/android/server/pm/pkg/SharedUserApi.java
+++ b/services/core/java/com/android/server/pm/pkg/SharedUserApi.java
@@ -22,7 +22,6 @@
import android.util.ArrayMap;
import android.util.ArraySet;
-import com.android.server.pm.parsing.pkg.AndroidPackage;
import com.android.server.pm.permission.LegacyPermissionState;
import com.android.server.pm.pkg.component.ParsedProcess;
diff --git a/services/core/java/com/android/server/pm/resolution/ComponentResolver.java b/services/core/java/com/android/server/pm/resolution/ComponentResolver.java
index 1d95e87..a19beea 100644
--- a/services/core/java/com/android/server/pm/resolution/ComponentResolver.java
+++ b/services/core/java/com/android/server/pm/resolution/ComponentResolver.java
@@ -51,7 +51,7 @@
import com.android.server.pm.UserManagerService;
import com.android.server.pm.UserNeedsBadgingCache;
import com.android.server.pm.parsing.PackageInfoUtils;
-import com.android.server.pm.parsing.pkg.AndroidPackage;
+import com.android.server.pm.pkg.AndroidPackage;
import com.android.server.pm.pkg.PackageStateInternal;
import com.android.server.pm.pkg.PackageStateUtils;
import com.android.server.pm.pkg.PackageUserStateInternal;
diff --git a/services/core/java/com/android/server/pm/resolution/ComponentResolverBase.java b/services/core/java/com/android/server/pm/resolution/ComponentResolverBase.java
index c01cecf..75d7162 100644
--- a/services/core/java/com/android/server/pm/resolution/ComponentResolverBase.java
+++ b/services/core/java/com/android/server/pm/resolution/ComponentResolverBase.java
@@ -32,8 +32,8 @@
import com.android.server.pm.DumpState;
import com.android.server.pm.UserManagerService;
import com.android.server.pm.parsing.PackageInfoUtils;
-import com.android.server.pm.parsing.pkg.AndroidPackage;
import com.android.server.pm.parsing.pkg.AndroidPackageUtils;
+import com.android.server.pm.pkg.AndroidPackage;
import com.android.server.pm.pkg.PackageStateInternal;
import com.android.server.pm.pkg.PackageUserStateInternal;
import com.android.server.pm.pkg.component.ParsedActivity;
diff --git a/services/core/java/com/android/server/pm/verify/domain/DomainVerificationCollector.java b/services/core/java/com/android/server/pm/verify/domain/DomainVerificationCollector.java
index e078120..adef808 100644
--- a/services/core/java/com/android/server/pm/verify/domain/DomainVerificationCollector.java
+++ b/services/core/java/com/android/server/pm/verify/domain/DomainVerificationCollector.java
@@ -22,8 +22,6 @@
import android.compat.annotation.EnabledSince;
import android.content.Intent;
import android.content.IntentFilter;
-import com.android.server.pm.pkg.component.ParsedActivity;
-import com.android.server.pm.pkg.component.ParsedIntentInfo;
import android.os.Build;
import android.text.TextUtils;
import android.util.ArraySet;
@@ -31,7 +29,9 @@
import com.android.server.SystemConfig;
import com.android.server.compat.PlatformCompat;
-import com.android.server.pm.parsing.pkg.AndroidPackage;
+import com.android.server.pm.pkg.AndroidPackage;
+import com.android.server.pm.pkg.component.ParsedActivity;
+import com.android.server.pm.pkg.component.ParsedIntentInfo;
import java.util.List;
import java.util.Objects;
diff --git a/services/core/java/com/android/server/pm/verify/domain/DomainVerificationDebug.java b/services/core/java/com/android/server/pm/verify/domain/DomainVerificationDebug.java
index e06b608..d67613c 100644
--- a/services/core/java/com/android/server/pm/verify/domain/DomainVerificationDebug.java
+++ b/services/core/java/com/android/server/pm/verify/domain/DomainVerificationDebug.java
@@ -31,7 +31,7 @@
import com.android.internal.util.CollectionUtils;
import com.android.server.pm.Computer;
-import com.android.server.pm.parsing.pkg.AndroidPackage;
+import com.android.server.pm.pkg.AndroidPackage;
import com.android.server.pm.pkg.PackageStateInternal;
import com.android.server.pm.verify.domain.models.DomainVerificationInternalUserState;
import com.android.server.pm.verify.domain.models.DomainVerificationPkgState;
diff --git a/services/core/java/com/android/server/pm/verify/domain/DomainVerificationService.java b/services/core/java/com/android/server/pm/verify/domain/DomainVerificationService.java
index 3cd7795..400af36 100644
--- a/services/core/java/com/android/server/pm/verify/domain/DomainVerificationService.java
+++ b/services/core/java/com/android/server/pm/verify/domain/DomainVerificationService.java
@@ -55,7 +55,7 @@
import com.android.server.SystemService;
import com.android.server.compat.PlatformCompat;
import com.android.server.pm.Computer;
-import com.android.server.pm.parsing.pkg.AndroidPackage;
+import com.android.server.pm.pkg.AndroidPackage;
import com.android.server.pm.pkg.PackageStateInternal;
import com.android.server.pm.pkg.PackageStateUtils;
import com.android.server.pm.pkg.PackageUserStateInternal;
diff --git a/services/core/java/com/android/server/pm/verify/domain/DomainVerificationSettings.java b/services/core/java/com/android/server/pm/verify/domain/DomainVerificationSettings.java
index 8d1ae0b..cde72cd 100644
--- a/services/core/java/com/android/server/pm/verify/domain/DomainVerificationSettings.java
+++ b/services/core/java/com/android/server/pm/verify/domain/DomainVerificationSettings.java
@@ -29,7 +29,7 @@
import com.android.internal.annotations.GuardedBy;
import com.android.internal.annotations.VisibleForTesting;
import com.android.server.pm.Computer;
-import com.android.server.pm.parsing.pkg.AndroidPackage;
+import com.android.server.pm.pkg.AndroidPackage;
import com.android.server.pm.pkg.PackageStateInternal;
import com.android.server.pm.verify.domain.models.DomainVerificationInternalUserState;
import com.android.server.pm.verify.domain.models.DomainVerificationPkgState;
diff --git a/services/core/java/com/android/server/pm/verify/domain/DomainVerificationUtils.java b/services/core/java/com/android/server/pm/verify/domain/DomainVerificationUtils.java
index 058b605..3fd00c6 100644
--- a/services/core/java/com/android/server/pm/verify/domain/DomainVerificationUtils.java
+++ b/services/core/java/com/android/server/pm/verify/domain/DomainVerificationUtils.java
@@ -28,7 +28,7 @@
import com.android.internal.util.CollectionUtils;
import com.android.server.compat.PlatformCompat;
import com.android.server.pm.PackageManagerService;
-import com.android.server.pm.parsing.pkg.AndroidPackage;
+import com.android.server.pm.pkg.AndroidPackage;
import java.util.Set;
import java.util.regex.Matcher;
diff --git a/services/core/java/com/android/server/pm/verify/domain/proxy/DomainVerificationProxyV1.java b/services/core/java/com/android/server/pm/verify/domain/proxy/DomainVerificationProxyV1.java
index c8e46b6..752eb53 100644
--- a/services/core/java/com/android/server/pm/verify/domain/proxy/DomainVerificationProxyV1.java
+++ b/services/core/java/com/android/server/pm/verify/domain/proxy/DomainVerificationProxyV1.java
@@ -39,7 +39,7 @@
import android.util.Slog;
import com.android.internal.annotations.GuardedBy;
-import com.android.server.pm.parsing.pkg.AndroidPackage;
+import com.android.server.pm.pkg.AndroidPackage;
import com.android.server.pm.verify.domain.DomainVerificationCollector;
import com.android.server.pm.verify.domain.DomainVerificationDebug;
import com.android.server.pm.verify.domain.DomainVerificationManagerInternal;
diff --git a/services/core/java/com/android/server/policy/PermissionPolicyService.java b/services/core/java/com/android/server/policy/PermissionPolicyService.java
index 7602d33..ffb652e 100644
--- a/services/core/java/com/android/server/policy/PermissionPolicyService.java
+++ b/services/core/java/com/android/server/policy/PermissionPolicyService.java
@@ -96,8 +96,8 @@
import com.android.server.SystemService;
import com.android.server.notification.NotificationManagerInternal;
import com.android.server.pm.UserManagerInternal;
-import com.android.server.pm.parsing.pkg.AndroidPackage;
import com.android.server.pm.permission.PermissionManagerServiceInternal;
+import com.android.server.pm.pkg.AndroidPackage;
import com.android.server.policy.PermissionPolicyInternal.OnInitializedCallback;
import com.android.server.utils.TimingsTraceAndSlog;
import com.android.server.wm.ActivityInterceptorCallback;
diff --git a/services/core/java/com/android/server/policy/SoftRestrictedPermissionPolicy.java b/services/core/java/com/android/server/policy/SoftRestrictedPermissionPolicy.java
index ab71355..33fc6fb 100644
--- a/services/core/java/com/android/server/policy/SoftRestrictedPermissionPolicy.java
+++ b/services/core/java/com/android/server/policy/SoftRestrictedPermissionPolicy.java
@@ -42,7 +42,7 @@
import android.provider.DeviceConfig;
import com.android.server.LocalServices;
-import com.android.server.pm.parsing.pkg.AndroidPackage;
+import com.android.server.pm.pkg.AndroidPackage;
import java.util.Arrays;
import java.util.HashSet;
diff --git a/services/core/java/com/android/server/power/Notifier.java b/services/core/java/com/android/server/power/Notifier.java
index 5a2fb18..dad9584 100644
--- a/services/core/java/com/android/server/power/Notifier.java
+++ b/services/core/java/com/android/server/power/Notifier.java
@@ -571,7 +571,8 @@
/**
* Called when there has been user activity.
*/
- public void onUserActivity(int displayGroupId, int event, int uid) {
+ public void onUserActivity(int displayGroupId, @PowerManager.UserActivityEvent int event,
+ int uid) {
if (DEBUG) {
Slog.d(TAG, "onUserActivity: event=" + event + ", uid=" + uid);
}
diff --git a/services/core/java/com/android/server/power/PowerGroup.java b/services/core/java/com/android/server/power/PowerGroup.java
index fec61ac..9fe53fb 100644
--- a/services/core/java/com/android/server/power/PowerGroup.java
+++ b/services/core/java/com/android/server/power/PowerGroup.java
@@ -74,6 +74,8 @@
private long mLastPowerOnTime;
private long mLastUserActivityTime;
private long mLastUserActivityTimeNoChangeLights;
+ @PowerManager.UserActivityEvent
+ private int mLastUserActivityEvent;
/** Timestamp (milliseconds since boot) of the last time the power group was awoken.*/
private long mLastWakeTime;
/** Timestamp (milliseconds since boot) of the last time the power group was put to sleep. */
@@ -244,7 +246,7 @@
return true;
}
- boolean dozeLocked(long eventTime, int uid, int reason) {
+ boolean dozeLocked(long eventTime, int uid, @PowerManager.GoToSleepReason int reason) {
if (eventTime < getLastWakeTimeLocked() || !isInteractive(mWakefulness)) {
return false;
}
@@ -253,9 +255,14 @@
try {
reason = Math.min(PowerManager.GO_TO_SLEEP_REASON_MAX,
Math.max(reason, PowerManager.GO_TO_SLEEP_REASON_MIN));
+ long millisSinceLastUserActivity = eventTime - Math.max(
+ mLastUserActivityTimeNoChangeLights, mLastUserActivityTime);
Slog.i(TAG, "Powering off display group due to "
- + PowerManager.sleepReasonToString(reason) + " (groupId= " + getGroupId()
- + ", uid= " + uid + ")...");
+ + PowerManager.sleepReasonToString(reason)
+ + " (groupId= " + getGroupId() + ", uid= " + uid
+ + ", millisSinceLastUserActivity=" + millisSinceLastUserActivity
+ + ", lastUserActivityEvent=" + PowerManager.userActivityEventToString(
+ mLastUserActivityEvent) + ")...");
setSandmanSummonedLocked(/* isSandmanSummoned= */ true);
setWakefulnessLocked(WAKEFULNESS_DOZING, eventTime, uid, reason, /* opUid= */ 0,
@@ -266,14 +273,16 @@
return true;
}
- boolean sleepLocked(long eventTime, int uid, int reason) {
+ boolean sleepLocked(long eventTime, int uid, @PowerManager.GoToSleepReason int reason) {
if (eventTime < mLastWakeTime || getWakefulnessLocked() == WAKEFULNESS_ASLEEP) {
return false;
}
Trace.traceBegin(Trace.TRACE_TAG_POWER, "sleepPowerGroup");
try {
- Slog.i(TAG, "Sleeping power group (groupId=" + getGroupId() + ", uid=" + uid + ")...");
+ Slog.i(TAG,
+ "Sleeping power group (groupId=" + getGroupId() + ", uid=" + uid + ", reason="
+ + PowerManager.sleepReasonToString(reason) + ")...");
setSandmanSummonedLocked(/* isSandmanSummoned= */ true);
setWakefulnessLocked(WAKEFULNESS_ASLEEP, eventTime, uid, reason, /* opUid= */0,
/* opPackageName= */ null, /* details= */ null);
@@ -287,16 +296,20 @@
return mLastUserActivityTime;
}
- void setLastUserActivityTimeLocked(long lastUserActivityTime) {
+ void setLastUserActivityTimeLocked(long lastUserActivityTime,
+ @PowerManager.UserActivityEvent int event) {
mLastUserActivityTime = lastUserActivityTime;
+ mLastUserActivityEvent = event;
}
public long getLastUserActivityTimeNoChangeLightsLocked() {
return mLastUserActivityTimeNoChangeLights;
}
- public void setLastUserActivityTimeNoChangeLightsLocked(long time) {
+ public void setLastUserActivityTimeNoChangeLightsLocked(long time,
+ @PowerManager.UserActivityEvent int event) {
mLastUserActivityTimeNoChangeLights = time;
+ mLastUserActivityEvent = event;
}
public int getUserActivitySummaryLocked() {
diff --git a/services/core/java/com/android/server/power/PowerManagerService.java b/services/core/java/com/android/server/power/PowerManagerService.java
index 9ee0df9..2d22b8f 100644
--- a/services/core/java/com/android/server/power/PowerManagerService.java
+++ b/services/core/java/com/android/server/power/PowerManagerService.java
@@ -1216,6 +1216,7 @@
return;
}
+ Slog.i(TAG, "onFlip(): Face " + (isFaceDown ? "down." : "up."));
mIsFaceDown = isFaceDown;
if (isFaceDown) {
final long currentTime = mClock.uptimeMillis();
@@ -1937,12 +1938,13 @@
// Called from native code.
@SuppressWarnings("unused")
- private void userActivityFromNative(long eventTime, int event, int displayId, int flags) {
+ private void userActivityFromNative(long eventTime, @PowerManager.UserActivityEvent int event,
+ int displayId, int flags) {
userActivityInternal(displayId, eventTime, event, flags, Process.SYSTEM_UID);
}
- private void userActivityInternal(int displayId, long eventTime, int event, int flags,
- int uid) {
+ private void userActivityInternal(int displayId, long eventTime,
+ @PowerManager.UserActivityEvent int event, int flags, int uid) {
synchronized (mLock) {
if (displayId == Display.INVALID_DISPLAY) {
if (userActivityNoUpdateLocked(eventTime, event, flags, uid)) {
@@ -1993,11 +1995,12 @@
@GuardedBy("mLock")
private boolean userActivityNoUpdateLocked(final PowerGroup powerGroup, long eventTime,
- int event, int flags, int uid) {
+ @PowerManager.UserActivityEvent int event, int flags, int uid) {
final int groupId = powerGroup.getGroupId();
if (DEBUG_SPEW) {
Slog.d(TAG, "userActivityNoUpdateLocked: groupId=" + groupId
- + ", eventTime=" + eventTime + ", event=" + event
+ + ", eventTime=" + eventTime
+ + ", event=" + PowerManager.userActivityEventToString(event)
+ ", flags=0x" + Integer.toHexString(flags) + ", uid=" + uid);
}
@@ -2032,7 +2035,7 @@
if ((flags & PowerManager.USER_ACTIVITY_FLAG_NO_CHANGE_LIGHTS) != 0) {
if (eventTime > powerGroup.getLastUserActivityTimeNoChangeLightsLocked()
&& eventTime > powerGroup.getLastUserActivityTimeLocked()) {
- powerGroup.setLastUserActivityTimeNoChangeLightsLocked(eventTime);
+ powerGroup.setLastUserActivityTimeNoChangeLightsLocked(eventTime, event);
mDirty |= DIRTY_USER_ACTIVITY;
if (event == PowerManager.USER_ACTIVITY_EVENT_BUTTON) {
mDirty |= DIRTY_QUIESCENT;
@@ -2042,7 +2045,7 @@
}
} else {
if (eventTime > powerGroup.getLastUserActivityTimeLocked()) {
- powerGroup.setLastUserActivityTimeLocked(eventTime);
+ powerGroup.setLastUserActivityTimeLocked(eventTime, event);
mDirty |= DIRTY_USER_ACTIVITY;
if (event == PowerManager.USER_ACTIVITY_EVENT_BUTTON) {
mDirty |= DIRTY_QUIESCENT;
@@ -2069,7 +2072,8 @@
@WakeReason int reason, String details, int uid, String opPackageName, int opUid) {
if (DEBUG_SPEW) {
Slog.d(TAG, "wakePowerGroupLocked: eventTime=" + eventTime
- + ", groupId=" + powerGroup.getGroupId() + ", uid=" + uid);
+ + ", groupId=" + powerGroup.getGroupId()
+ + ", reason=" + PowerManager.wakeReasonToString(reason) + ", uid=" + uid);
}
if (mForceSuspendActive || !mSystemReady) {
return;
@@ -2092,11 +2096,11 @@
@GuardedBy("mLock")
private boolean dozePowerGroupLocked(final PowerGroup powerGroup, long eventTime,
- int reason, int uid) {
+ @GoToSleepReason int reason, int uid) {
if (DEBUG_SPEW) {
Slog.d(TAG, "dozePowerGroup: eventTime=" + eventTime
- + ", groupId=" + powerGroup.getGroupId() + ", reason=" + reason
- + ", uid=" + uid);
+ + ", groupId=" + powerGroup.getGroupId()
+ + ", reason=" + PowerManager.sleepReasonToString(reason) + ", uid=" + uid);
}
if (!mSystemReady || !mBootCompleted) {
@@ -2107,10 +2111,12 @@
}
@GuardedBy("mLock")
- private boolean sleepPowerGroupLocked(final PowerGroup powerGroup, long eventTime, int reason,
- int uid) {
+ private boolean sleepPowerGroupLocked(final PowerGroup powerGroup, long eventTime,
+ @GoToSleepReason int reason, int uid) {
if (DEBUG_SPEW) {
- Slog.d(TAG, "sleepPowerGroup: eventTime=" + eventTime + ", uid=" + uid);
+ Slog.d(TAG, "sleepPowerGroup: eventTime=" + eventTime
+ + ", groupId=" + powerGroup.getGroupId()
+ + ", reason=" + PowerManager.sleepReasonToString(reason) + ", uid=" + uid);
}
if (!mBootCompleted || !mSystemReady) {
return false;
@@ -2172,7 +2178,10 @@
case WAKEFULNESS_DOZING:
traceMethodName = "goToSleep";
Slog.i(TAG, "Going to sleep due to " + PowerManager.sleepReasonToString(reason)
- + " (uid " + uid + ")...");
+ + " (uid " + uid + ", screenOffTimeout=" + mScreenOffTimeoutSetting
+ + ", activityTimeoutWM=" + mUserActivityTimeoutOverrideFromWindowManager
+ + ", maxDimRatio=" + mMaximumScreenDimRatioConfig
+ + ", maxDimDur=" + mMaximumScreenDimDurationConfig + ")...");
mLastGlobalSleepTime = eventTime;
mLastGlobalSleepReason = reason;
mLastGlobalSleepTimeRealtime = mClock.elapsedRealtime();
@@ -4258,7 +4267,7 @@
void onUserActivity() {
synchronized (mLock) {
mPowerGroups.get(Display.DEFAULT_DISPLAY_GROUP).setLastUserActivityTimeLocked(
- mClock.uptimeMillis());
+ mClock.uptimeMillis(), PowerManager.USER_ACTIVITY_EVENT_OTHER);
}
}
@@ -5646,7 +5655,8 @@
}
@Override // Binder call
- public void userActivity(int displayId, long eventTime, int event, int flags) {
+ public void userActivity(int displayId, long eventTime,
+ @PowerManager.UserActivityEvent int event, int flags) {
final long now = mClock.uptimeMillis();
if (mContext.checkCallingOrSelfPermission(android.Manifest.permission.DEVICE_POWER)
!= PackageManager.PERMISSION_GRANTED
diff --git a/services/core/java/com/android/server/power/stats/BatteryStatsImpl.java b/services/core/java/com/android/server/power/stats/BatteryStatsImpl.java
index 03a9642..c6128f9 100644
--- a/services/core/java/com/android/server/power/stats/BatteryStatsImpl.java
+++ b/services/core/java/com/android/server/power/stats/BatteryStatsImpl.java
@@ -178,7 +178,7 @@
// TODO: remove "tcp" from network methods, since we measure total stats.
// Current on-disk Parcel version. Must be updated when the format of the parcelable changes
- public static final int VERSION = 209;
+ public static final int VERSION = 210;
// The maximum number of names wakelocks we will keep track of
// per uid; once the limit is reached, we batch the remaining wakelocks
@@ -5413,7 +5413,8 @@
}
@GuardedBy("this")
- public void noteUserActivityLocked(int uid, int event, long elapsedRealtimeMs, long uptimeMs) {
+ public void noteUserActivityLocked(int uid, @PowerManager.UserActivityEvent int event,
+ long elapsedRealtimeMs, long uptimeMs) {
if (mOnBatteryInternal) {
uid = mapUid(uid);
getUidStatsLocked(uid, elapsedRealtimeMs, uptimeMs).noteUserActivityLocked(event);
@@ -8846,14 +8847,14 @@
}
@Override
- public void noteUserActivityLocked(int type) {
+ public void noteUserActivityLocked(@PowerManager.UserActivityEvent int event) {
if (mUserActivityCounters == null) {
initUserActivityLocked();
}
- if (type >= 0 && type < NUM_USER_ACTIVITY_TYPES) {
- mUserActivityCounters[type].stepAtomic();
+ if (event >= 0 && event < NUM_USER_ACTIVITY_TYPES) {
+ mUserActivityCounters[event].stepAtomic();
} else {
- Slog.w(TAG, "Unknown user activity type " + type + " was specified.",
+ Slog.w(TAG, "Unknown user activity type " + event + " was specified.",
new Throwable());
}
}
diff --git a/services/core/java/com/android/server/rollback/Rollback.java b/services/core/java/com/android/server/rollback/Rollback.java
index 38e6b28..85d93f4 100644
--- a/services/core/java/com/android/server/rollback/Rollback.java
+++ b/services/core/java/com/android/server/rollback/Rollback.java
@@ -52,7 +52,7 @@
import com.android.internal.util.Preconditions;
import com.android.server.LocalServices;
import com.android.server.RescueParty;
-import com.android.server.pm.parsing.pkg.AndroidPackage;
+import com.android.server.pm.pkg.AndroidPackage;
import java.io.File;
import java.io.IOException;
diff --git a/services/core/java/com/android/server/timedetector/GnssTimeUpdateService.java b/services/core/java/com/android/server/timedetector/GnssTimeUpdateService.java
index 88e9fa5..1fb7cf5 100644
--- a/services/core/java/com/android/server/timedetector/GnssTimeUpdateService.java
+++ b/services/core/java/com/android/server/timedetector/GnssTimeUpdateService.java
@@ -18,19 +18,24 @@
import android.annotation.NonNull;
import android.annotation.Nullable;
+import android.annotation.RequiresPermission;
import android.app.AlarmManager;
import android.content.Context;
-import android.location.Location;
import android.location.LocationListener;
import android.location.LocationManager;
import android.location.LocationManagerInternal;
import android.location.LocationRequest;
import android.location.LocationTime;
import android.os.Binder;
+import android.os.Handler;
+import android.os.ResultReceiver;
+import android.os.ShellCallback;
import android.os.SystemClock;
import android.os.TimestampedValue;
+import android.util.LocalLog;
import android.util.Log;
+import com.android.internal.annotations.GuardedBy;
import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.util.DumpUtils;
import com.android.server.FgThread;
@@ -41,6 +46,7 @@
import java.io.PrintWriter;
import java.time.Duration;
import java.util.Objects;
+import java.util.concurrent.Executor;
/**
* Monitors the GNSS time.
@@ -87,7 +93,7 @@
// Instead of polling GNSS time periodically, passive location updates are enabled.
// Once an update is received, the gnss time will be queried and suggested to
// TimeDetectorService.
- mService.requestGnssTimeUpdates();
+ mService.startGnssListeningInternal();
}
}
}
@@ -95,15 +101,28 @@
private static final Duration GNSS_TIME_UPDATE_ALARM_INTERVAL = Duration.ofHours(4);
private static final String ATTRIBUTION_TAG = "GnssTimeUpdateService";
+ /**
+ * A log that records the decisions to fetch a GNSS time update.
+ * This is logged in bug reports to assist with debugging issues with GNSS time suggestions.
+ */
+ private final LocalLog mLocalLog = new LocalLog(10, false /* useLocalTimestamps */);
+ /** The executor used for async operations */
+ private final Executor mExecutor = FgThread.getExecutor();
+ /** The handler used for async operations */
+ private final Handler mHandler = FgThread.getHandler();
+
private final Context mContext;
private final TimeDetectorInternal mTimeDetectorInternal;
private final AlarmManager mAlarmManager;
private final LocationManager mLocationManager;
private final LocationManagerInternal mLocationManagerInternal;
- @Nullable private AlarmManager.OnAlarmListener mAlarmListener;
- @Nullable private LocationListener mLocationListener;
- @Nullable private TimestampedValue<Long> mLastSuggestedGnssTime;
+
+ private final Object mLock = new Object();
+ @GuardedBy("mLock") @Nullable private AlarmManager.OnAlarmListener mAlarmListener;
+ @GuardedBy("mLock") @Nullable private LocationListener mLocationListener;
+
+ @Nullable private volatile TimestampedValue<Long> mLastSuggestedGnssTime;
@VisibleForTesting
GnssTimeUpdateService(@NonNull Context context, @NonNull AlarmManager alarmManager,
@@ -118,87 +137,133 @@
}
/**
- * Request passive location updates. Such a request will not trigger any active locations or
- * power usage itself.
+ * Used by {@link com.android.server.timedetector.GnssTimeUpdateServiceShellCommand} to force
+ * the service into GNSS listening mode.
+ */
+ @RequiresPermission(android.Manifest.permission.SET_TIME)
+ boolean startGnssListening() {
+ mContext.enforceCallingPermission(
+ android.Manifest.permission.SET_TIME, "Start GNSS listening");
+ mLocalLog.log("startGnssListening() called");
+
+ final long token = Binder.clearCallingIdentity();
+ try {
+ return startGnssListeningInternal();
+ } finally {
+ Binder.restoreCallingIdentity(token);
+ }
+ }
+
+ /**
+ * Starts listening for passive location updates. Such a request will not trigger any active
+ * locations or power usage itself. Returns {@code true} if the service is listening after the
+ * method returns and {@code false} otherwise. At present this method only returns {@code false}
+ * if there is no GPS provider on the device.
+ *
+ * <p>If the service is already listening for locations this is a no-op. If the device is in a
+ * "sleeping" state between listening periods then it will return to listening.
*/
@VisibleForTesting
- void requestGnssTimeUpdates() {
- if (D) {
- Log.d(TAG, "requestGnssTimeUpdates()");
+ boolean startGnssListeningInternal() {
+ if (!mLocationManager.hasProvider(LocationManager.GPS_PROVIDER)) {
+ logError("GPS provider does not exist on this device");
+ return false;
}
- if (!mLocationManager.hasProvider(LocationManager.GPS_PROVIDER)) {
- Log.e(TAG, "GPS provider does not exist on this device");
- return;
+ synchronized (mLock) {
+ if (mLocationListener != null) {
+ logDebug("Already listening for GNSS updates");
+ return true;
+ }
+
+ // If startGnssListening() is called during manual tests to jump back into location
+ // listening then there will usually be an alarm set.
+ if (mAlarmListener != null) {
+ mAlarmManager.cancel(mAlarmListener);
+ mAlarmListener = null;
+ }
+
+ startGnssListeningLocked();
+ return true;
}
+ }
+
+ @GuardedBy("mLock")
+ private void startGnssListeningLocked() {
+ logDebug("startGnssListeningLocked()");
// Location Listener triggers onLocationChanged() when GNSS data is available, so
// that the getGnssTimeMillis() function doesn't need to be continuously polled.
- mLocationListener = new LocationListener() {
- @Override
- public void onLocationChanged(Location location) {
- if (D) {
- Log.d(TAG, "onLocationChanged()");
- }
-
- // getGnssTimeMillis() can return null when the Master Location Switch for the
- // foreground user is disabled.
- LocationTime locationTime = mLocationManagerInternal.getGnssTimeMillis();
- if (locationTime != null) {
- suggestGnssTime(locationTime);
- } else {
- if (D) {
- Log.d(TAG, "getGnssTimeMillis() returned null");
- }
- }
-
- mLocationManager.removeUpdates(mLocationListener);
- mLocationListener = null;
-
- mAlarmListener = new AlarmManager.OnAlarmListener() {
- @Override
- public void onAlarm() {
- if (D) {
- Log.d(TAG, "onAlarm()");
- }
- mAlarmListener = null;
- requestGnssTimeUpdates();
- }
- };
-
- // Set next alarm to re-enable location updates.
- long next = SystemClock.elapsedRealtime()
- + GNSS_TIME_UPDATE_ALARM_INTERVAL.toMillis();
- mAlarmManager.set(
- AlarmManager.ELAPSED_REALTIME_WAKEUP,
- next,
- TAG,
- mAlarmListener,
- FgThread.getHandler());
- }
- };
-
+ mLocationListener = location -> handleLocationAvailable();
mLocationManager.requestLocationUpdates(
LocationManager.GPS_PROVIDER,
new LocationRequest.Builder(LocationRequest.PASSIVE_INTERVAL)
.setMinUpdateIntervalMillis(0)
.build(),
- FgThread.getExecutor(),
+ mExecutor,
mLocationListener);
}
+ private void handleLocationAvailable() {
+ logDebug("handleLocationAvailable()");
+
+ // getGnssTimeMillis() can return null when the Master Location Switch for the
+ // foreground user is disabled.
+ LocationTime locationTime = mLocationManagerInternal.getGnssTimeMillis();
+ if (locationTime != null) {
+ String msg = "Passive location time received: " + locationTime;
+ logDebug(msg);
+ mLocalLog.log(msg);
+ suggestGnssTime(locationTime);
+ } else {
+ logDebug("getGnssTimeMillis() returned null");
+ }
+
+ synchronized (mLock) {
+ if (mLocationListener == null) {
+ logWarning("mLocationListener unexpectedly null");
+ } else {
+ mLocationManager.removeUpdates(mLocationListener);
+ mLocationListener = null;
+ }
+
+ if (mAlarmListener != null) {
+ logWarning("mAlarmListener was unexpectedly non-null");
+ mAlarmManager.cancel(mAlarmListener);
+ }
+
+ // Set next alarm to re-enable location updates.
+ long next = SystemClock.elapsedRealtime()
+ + GNSS_TIME_UPDATE_ALARM_INTERVAL.toMillis();
+ mAlarmListener = this::handleAlarmFired;
+ mAlarmManager.set(
+ AlarmManager.ELAPSED_REALTIME_WAKEUP,
+ next,
+ TAG,
+ mAlarmListener,
+ mHandler);
+ }
+ }
+
+ private void handleAlarmFired() {
+ logDebug("handleAlarmFired()");
+
+ synchronized (mLock) {
+ mAlarmListener = null;
+ startGnssListeningLocked();
+ }
+ }
+
/**
* Convert LocationTime to TimestampedValue. Then suggest TimestampedValue to Time Detector.
*/
private void suggestGnssTime(LocationTime locationTime) {
- if (D) {
- Log.d(TAG, "suggestGnssTime()");
- }
+ logDebug("suggestGnssTime()");
+
long gnssTime = locationTime.getTime();
long elapsedRealtimeMs = locationTime.getElapsedRealtimeNanos() / 1_000_000L;
- TimestampedValue<Long> timeSignal = new TimestampedValue<>(
- elapsedRealtimeMs, gnssTime);
+ TimestampedValue<Long> timeSignal = new TimestampedValue<>(elapsedRealtimeMs, gnssTime);
mLastSuggestedGnssTime = timeSignal;
GnssTimeSuggestion timeSuggestion = new GnssTimeSuggestion(timeSignal);
@@ -209,11 +274,38 @@
protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
if (!DumpUtils.checkDumpPermission(mContext, TAG, pw)) return;
pw.println("mLastSuggestedGnssTime: " + mLastSuggestedGnssTime);
- pw.print("state: ");
- if (mLocationListener != null) {
- pw.println("time updates enabled");
- } else {
- pw.println("alarm enabled");
+ synchronized (mLock) {
+ pw.print("state: ");
+ if (mLocationListener != null) {
+ pw.println("time updates enabled");
+ } else {
+ pw.println("alarm enabled");
+ }
+ }
+ pw.println("Log:");
+ mLocalLog.dump(pw);
+ }
+
+ @Override
+ public void onShellCommand(FileDescriptor in, FileDescriptor out, FileDescriptor err,
+ String[] args, ShellCallback callback, ResultReceiver resultReceiver) {
+ new GnssTimeUpdateServiceShellCommand(this).exec(
+ this, in, out, err, args, callback, resultReceiver);
+ }
+
+ private void logError(String msg) {
+ Log.e(TAG, msg);
+ mLocalLog.log(msg);
+ }
+
+ private void logWarning(String msg) {
+ Log.w(TAG, msg);
+ mLocalLog.log(msg);
+ }
+
+ private void logDebug(String msg) {
+ if (D) {
+ Log.d(TAG, msg);
}
}
}
diff --git a/services/core/java/com/android/server/timedetector/GnssTimeUpdateServiceShellCommand.java b/services/core/java/com/android/server/timedetector/GnssTimeUpdateServiceShellCommand.java
new file mode 100644
index 0000000..e757578
--- /dev/null
+++ b/services/core/java/com/android/server/timedetector/GnssTimeUpdateServiceShellCommand.java
@@ -0,0 +1,77 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server.timedetector;
+
+import android.annotation.NonNull;
+import android.os.ShellCommand;
+
+import java.io.PrintWriter;
+import java.util.Objects;
+
+/** Implements the shell command interface for {@link GnssTimeUpdateService}. */
+class GnssTimeUpdateServiceShellCommand extends ShellCommand {
+
+ /**
+ * The name of the service.
+ */
+ private static final String SHELL_COMMAND_SERVICE_NAME = "gnss_time_update_service";
+
+ /**
+ * A shell command that forces the service in to GNSS listening mode if it isn't already.
+ */
+ private static final String SHELL_COMMAND_START_GNSS_LISTENING = "start_gnss_listening";
+
+ @NonNull
+ private final GnssTimeUpdateService mGnssTimeUpdateService;
+
+ GnssTimeUpdateServiceShellCommand(GnssTimeUpdateService gnssTimeUpdateService) {
+ mGnssTimeUpdateService = Objects.requireNonNull(gnssTimeUpdateService);
+ }
+
+ @Override
+ public int onCommand(String cmd) {
+ if (cmd == null) {
+ return handleDefaultCommands(cmd);
+ }
+
+ switch (cmd) {
+ case SHELL_COMMAND_START_GNSS_LISTENING:
+ return runStartGnssListening();
+ default: {
+ return handleDefaultCommands(cmd);
+ }
+ }
+ }
+
+ private int runStartGnssListening() {
+ boolean success = mGnssTimeUpdateService.startGnssListening();
+ getOutPrintWriter().println(success);
+ return 0;
+ }
+
+ @Override
+ public void onHelp() {
+ final PrintWriter pw = getOutPrintWriter();
+ pw.printf("Network Time Update Service (%s) commands:\n", SHELL_COMMAND_SERVICE_NAME);
+ pw.printf(" help\n");
+ pw.printf(" Print this help text.\n");
+ pw.printf(" %s\n", SHELL_COMMAND_START_GNSS_LISTENING);
+ pw.printf(" Forces the service in to GNSS listening mode (if it isn't already).\n");
+ pw.printf(" Prints true if the service is listening after this command.\n");
+ pw.println();
+ }
+}
diff --git a/services/core/java/com/android/server/wm/ActivityClientController.java b/services/core/java/com/android/server/wm/ActivityClientController.java
index cceb58d..ffe24c0 100644
--- a/services/core/java/com/android/server/wm/ActivityClientController.java
+++ b/services/core/java/com/android/server/wm/ActivityClientController.java
@@ -87,7 +87,7 @@
import com.android.server.LocalServices;
import com.android.server.Watchdog;
import com.android.server.pm.KnownPackages;
-import com.android.server.pm.parsing.pkg.AndroidPackage;
+import com.android.server.pm.pkg.AndroidPackage;
import com.android.server.uri.NeededUriGrants;
import com.android.server.vr.VrManagerInternal;
diff --git a/services/core/java/com/android/server/wm/AnrController.java b/services/core/java/com/android/server/wm/AnrController.java
index e0ac37a..01098de 100644
--- a/services/core/java/com/android/server/wm/AnrController.java
+++ b/services/core/java/com/android/server/wm/AnrController.java
@@ -19,6 +19,7 @@
import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION_OVERLAY;
import static com.android.server.wm.ActivityRecord.INVALID_PID;
+import static com.android.server.wm.ActivityTaskManagerService.getInputDispatchingTimeoutMillisLocked;
import static com.android.server.wm.WindowManagerDebugConfig.TAG_WM;
import android.annotation.NonNull;
@@ -72,6 +73,33 @@
+ ". Dropping notifyNoFocusedWindowAnr request");
return;
}
+
+ // App is unresponsive, but we are actively trying to give focus to a window.
+ // Blame the window if possible since the window may not belong to the app.
+ DisplayContent display = mService.mRoot.getDisplayContent(activity.getDisplayId());
+ IBinder focusToken = display == null ? null : display.getInputMonitor().mInputFocus;
+ InputTarget focusTarget = mService.getInputTargetFromToken(focusToken);
+
+ if (focusTarget != null) {
+ // Check if we have a recent focus request, newer than the dispatch timeout, then
+ // ignore the focus request.
+ WindowState targetWindowState = focusTarget.getWindowState();
+ boolean requestIsValid = SystemClock.uptimeMillis()
+ - display.getInputMonitor().mInputFocusRequestTimeMillis
+ >= getInputDispatchingTimeoutMillisLocked(
+ targetWindowState.getActivityRecord());
+
+ if (requestIsValid) {
+ if (notifyWindowUnresponsive(focusToken, timeoutRecord)) {
+ Slog.i(TAG_WM, "Blamed " + focusTarget.getWindowState().getName()
+ + " using pending focus request. Focused activity: "
+ + activity.getName());
+ return;
+ }
+ }
+ }
+
+
Slog.i(TAG_WM, "ANR in " + activity.getName() + ". Reason: " + timeoutRecord.mReason);
dumpAnrStateLocked(activity, null /* windowState */, timeoutRecord.mReason);
mUnresponsiveAppByDisplay.put(activity.getDisplayId(), activity);
@@ -208,6 +236,7 @@
}
}
mService.mAmInternal.inputDispatchingResumed(unresponsiveApp.getPid());
+ mUnresponsiveAppByDisplay.remove(newFocus.getDisplayId());
}
/**
diff --git a/services/core/java/com/android/server/wm/ImeInsetsSourceProvider.java b/services/core/java/com/android/server/wm/ImeInsetsSourceProvider.java
index 3e6e06a..14a1cd0 100644
--- a/services/core/java/com/android/server/wm/ImeInsetsSourceProvider.java
+++ b/services/core/java/com/android/server/wm/ImeInsetsSourceProvider.java
@@ -218,6 +218,12 @@
if (dcTarget == null || mImeRequester == null) {
return false;
}
+ // Not ready to show if there is no IME control target.
+ final InsetsControlTarget controlTarget = mDisplayContent.getImeTarget(IME_TARGET_CONTROL);
+ if (controlTarget == null) {
+ return false;
+ }
+
ProtoLog.d(WM_DEBUG_IME, "dcTarget: %s mImeRequester: %s",
dcTarget.getWindow().getName(), mImeRequester.getWindow() == null
? mImeRequester : mImeRequester.getWindow().getName());
diff --git a/services/core/java/com/android/server/wm/InputMonitor.java b/services/core/java/com/android/server/wm/InputMonitor.java
index 610ce35..7860b15 100644
--- a/services/core/java/com/android/server/wm/InputMonitor.java
+++ b/services/core/java/com/android/server/wm/InputMonitor.java
@@ -52,6 +52,7 @@
import android.os.Handler;
import android.os.IBinder;
import android.os.InputConfig;
+import android.os.SystemClock;
import android.os.Trace;
import android.os.UserHandle;
import android.util.ArrayMap;
@@ -77,7 +78,8 @@
private final WindowManagerService mService;
// Current input focus token for keys and other non-touch events. May be null.
- private IBinder mInputFocus = null;
+ IBinder mInputFocus = null;
+ long mInputFocusRequestTimeMillis = 0;
// When true, need to call updateInputWindowsLw().
private boolean mUpdateInputWindowsNeeded = true;
@@ -479,6 +481,7 @@
}
mInputFocus = focusToken;
+ mInputFocusRequestTimeMillis = SystemClock.uptimeMillis();
mInputTransaction.setFocusedWindow(mInputFocus, windowName, mDisplayId);
EventLog.writeEvent(LOGTAG_INPUT_FOCUS, "Focus request " + windowName,
"reason=UpdateInputWindows");
diff --git a/services/core/java/com/android/server/wm/TaskFragment.java b/services/core/java/com/android/server/wm/TaskFragment.java
index 1f6690ac..f784f71 100644
--- a/services/core/java/com/android/server/wm/TaskFragment.java
+++ b/services/core/java/com/android/server/wm/TaskFragment.java
@@ -97,7 +97,7 @@
import com.android.internal.util.function.pooled.PooledLambda;
import com.android.internal.util.function.pooled.PooledPredicate;
import com.android.server.am.HostingRecord;
-import com.android.server.pm.parsing.pkg.AndroidPackage;
+import com.android.server.pm.pkg.AndroidPackage;
import java.io.FileDescriptor;
import java.io.PrintWriter;
diff --git a/services/core/java/com/android/server/wm/Transition.java b/services/core/java/com/android/server/wm/Transition.java
index 75d6647..32b7532 100644
--- a/services/core/java/com/android/server/wm/Transition.java
+++ b/services/core/java/com/android/server/wm/Transition.java
@@ -2120,8 +2120,12 @@
Slog.w(TAG, "Failed to capture screenshot for " + wc);
return false;
}
+ final boolean isDisplayRotation = wc.asDisplayContent() != null
+ && wc.asDisplayContent().isRotationChanging();
+ // Some tests may check the name "RotationLayer" to detect display rotation.
+ final String name = isDisplayRotation ? "RotationLayer" : "transition snapshot: " + wc;
SurfaceControl snapshotSurface = wc.makeAnimationLeash()
- .setName("transition snapshot: " + wc.toString())
+ .setName(name)
.setOpaque(true)
.setParent(wc.getSurfaceControl())
.setSecure(screenshotBuffer.containsSecureLayers())
@@ -2131,9 +2135,8 @@
mFrozen.add(wc);
final ChangeInfo changeInfo = Objects.requireNonNull(mChanges.get(wc));
changeInfo.mSnapshot = snapshotSurface;
- if (wc.asDisplayContent() != null) {
- // This isn't cheap, so only do it for rotations: assume display-level is rotate
- // since most of the time it is.
+ if (isDisplayRotation) {
+ // This isn't cheap, so only do it for display rotations.
changeInfo.mSnapshotLuma = RotationAnimationUtils.getMedianBorderLuma(
screenshotBuffer.getHardwareBuffer(), screenshotBuffer.getColorSpace());
}
diff --git a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
index 89a2809..bb6bd4a 100644
--- a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
+++ b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
@@ -375,7 +375,7 @@
import com.android.server.pm.UserManagerInternal;
import com.android.server.pm.UserManagerInternal.UserRestrictionsListener;
import com.android.server.pm.UserRestrictionsUtils;
-import com.android.server.pm.parsing.pkg.AndroidPackage;
+import com.android.server.pm.pkg.AndroidPackage;
import com.android.server.storage.DeviceStorageMonitorInternal;
import com.android.server.uri.NeededUriGrants;
import com.android.server.uri.UriGrantsManagerInternal;
diff --git a/services/robotests/src/com/android/server/pm/CrossProfileAppsServiceImplRoboTest.java b/services/robotests/src/com/android/server/pm/CrossProfileAppsServiceImplRoboTest.java
index df1d244..3ef8586a 100644
--- a/services/robotests/src/com/android/server/pm/CrossProfileAppsServiceImplRoboTest.java
+++ b/services/robotests/src/com/android/server/pm/CrossProfileAppsServiceImplRoboTest.java
@@ -60,9 +60,9 @@
import com.android.internal.util.FunctionalUtils.ThrowingRunnable;
import com.android.internal.util.FunctionalUtils.ThrowingSupplier;
import com.android.server.LocalServices;
-import com.android.server.pm.parsing.pkg.AndroidPackage;
import com.android.server.pm.parsing.pkg.PackageImpl;
import com.android.server.pm.parsing.pkg.ParsedPackage;
+import com.android.server.pm.pkg.AndroidPackage;
import com.android.server.testing.shadows.ShadowApplicationPackageManager;
import com.android.server.testing.shadows.ShadowUserManager;
import com.android.server.wm.ActivityTaskManagerInternal;
diff --git a/services/tests/PackageManagerComponentOverrideTests/src/com/android/server/pm/test/override/PackageManagerComponentLabelIconOverrideTest.kt b/services/tests/PackageManagerComponentOverrideTests/src/com/android/server/pm/test/override/PackageManagerComponentLabelIconOverrideTest.kt
index 9c0f713..f3ac7d5 100644
--- a/services/tests/PackageManagerComponentOverrideTests/src/com/android/server/pm/test/override/PackageManagerComponentLabelIconOverrideTest.kt
+++ b/services/tests/PackageManagerComponentOverrideTests/src/com/android/server/pm/test/override/PackageManagerComponentLabelIconOverrideTest.kt
@@ -21,14 +21,25 @@
import android.content.Context
import android.content.pm.ApplicationInfo
import android.content.pm.PackageManager
-import com.android.server.pm.pkg.component.ParsedActivity
import android.os.Binder
import android.os.UserHandle
import android.util.ArrayMap
-import com.android.server.pm.*
-import com.android.server.pm.parsing.pkg.AndroidPackage
+import com.android.server.pm.AppsFilterImpl
+import com.android.server.pm.PackageManagerService
+import com.android.server.pm.PackageManagerServiceInjector
+import com.android.server.pm.PackageManagerServiceTestParams
+import com.android.server.pm.PackageManagerTracedLock
+import com.android.server.pm.PackageSetting
+import com.android.server.pm.PendingPackageBroadcasts
+import com.android.server.pm.Settings
+import com.android.server.pm.SharedLibrariesImpl
+import com.android.server.pm.UserManagerInternal
+import com.android.server.pm.UserManagerService
+import com.android.server.pm.parsing.pkg.AndroidPackageInternal
import com.android.server.pm.parsing.pkg.PackageImpl
import com.android.server.pm.parsing.pkg.ParsedPackage
+import com.android.server.pm.pkg.AndroidPackage
+import com.android.server.pm.pkg.component.ParsedActivity
import com.android.server.pm.resolution.ComponentResolver
import com.android.server.pm.snapshot.PackageDataSnapshot
import com.android.server.pm.test.override.PackageManagerComponentLabelIconOverrideTest.Companion.Params.AppType
@@ -168,7 +179,7 @@
lateinit var params: Params
private lateinit var mockPendingBroadcasts: PendingPackageBroadcasts
- private lateinit var mockPkg: AndroidPackage
+ private lateinit var mockPkg: AndroidPackageInternal
private lateinit var mockPkgSetting: PackageSetting
private lateinit var service: PackageManagerService
@@ -287,7 +298,7 @@
.apply(block)
.hideAsFinal()
- private fun makePkgSetting(pkgName: String, pkg: AndroidPackage) =
+ private fun makePkgSetting(pkgName: String, pkg: AndroidPackageInternal) =
PackageSetting(
pkgName, null, File("/test"),
null, null, null, null, 0, 0, 0, 0, null, null, null, null, null,
@@ -297,7 +308,7 @@
this.flags = this.flags or ApplicationInfo.FLAG_SYSTEM
}
this.pkgState.isUpdatedSystemApp = params.isUpdatedSystemApp
- this.pkg = pkg
+ setPkg(pkg)
}
private fun makeTestData() {
diff --git a/services/tests/PackageManagerServiceTests/unit/src/com/android/server/pm/test/parsing/parcelling/AndroidPackageTest.kt b/services/tests/PackageManagerServiceTests/unit/src/com/android/server/pm/test/parsing/parcelling/AndroidPackageTest.kt
index 391dd36..5361041 100644
--- a/services/tests/PackageManagerServiceTests/unit/src/com/android/server/pm/test/parsing/parcelling/AndroidPackageTest.kt
+++ b/services/tests/PackageManagerServiceTests/unit/src/com/android/server/pm/test/parsing/parcelling/AndroidPackageTest.kt
@@ -31,8 +31,8 @@
import android.util.SparseArray
import android.util.SparseIntArray
import com.android.internal.R
-import com.android.server.pm.parsing.pkg.AndroidPackage
import com.android.server.pm.parsing.pkg.PackageImpl
+import com.android.server.pm.pkg.AndroidPackage
import com.android.server.pm.pkg.component.ParsedActivityImpl
import com.android.server.pm.pkg.component.ParsedApexSystemServiceImpl
import com.android.server.pm.pkg.component.ParsedAttributionImpl
diff --git a/services/tests/PackageManagerServiceTests/unit/src/com/android/server/pm/test/verify/domain/DomainVerificationCollectorTest.kt b/services/tests/PackageManagerServiceTests/unit/src/com/android/server/pm/test/verify/domain/DomainVerificationCollectorTest.kt
index 652dc38..766ab94 100644
--- a/services/tests/PackageManagerServiceTests/unit/src/com/android/server/pm/test/verify/domain/DomainVerificationCollectorTest.kt
+++ b/services/tests/PackageManagerServiceTests/unit/src/com/android/server/pm/test/verify/domain/DomainVerificationCollectorTest.kt
@@ -18,14 +18,15 @@
import android.content.Intent
import android.content.pm.ApplicationInfo
-import com.android.server.pm.pkg.component.ParsedActivityImpl
-import com.android.server.pm.pkg.component.ParsedIntentInfoImpl
import android.os.Build
import android.os.PatternMatcher
import android.util.ArraySet
import com.android.server.SystemConfig
import com.android.server.compat.PlatformCompat
-import com.android.server.pm.parsing.pkg.AndroidPackage
+import com.android.server.pm.parsing.pkg.AndroidPackageInternal
+import com.android.server.pm.pkg.AndroidPackage
+import com.android.server.pm.pkg.component.ParsedActivityImpl
+import com.android.server.pm.pkg.component.ParsedIntentInfoImpl
import com.android.server.pm.verify.domain.DomainVerificationCollector
import com.android.server.testutils.mockThrowOnUnmocked
import com.android.server.testutils.whenever
@@ -87,7 +88,7 @@
@Test
fun verifyV1NoValidIntentFilter() {
- val pkg = mockThrowOnUnmocked<AndroidPackage> {
+ val pkg = mockThrowOnUnmocked<AndroidPackageInternal> {
whenever(packageName) { TEST_PKG_NAME }
whenever(targetSdkVersion) { Build.VERSION_CODES.R }
diff --git a/services/tests/PackageManagerServiceTests/unit/src/com/android/server/pm/test/verify/domain/DomainVerificationEnforcerTest.kt b/services/tests/PackageManagerServiceTests/unit/src/com/android/server/pm/test/verify/domain/DomainVerificationEnforcerTest.kt
index c9601de..e4d124e 100644
--- a/services/tests/PackageManagerServiceTests/unit/src/com/android/server/pm/test/verify/domain/DomainVerificationEnforcerTest.kt
+++ b/services/tests/PackageManagerServiceTests/unit/src/com/android/server/pm/test/verify/domain/DomainVerificationEnforcerTest.kt
@@ -29,7 +29,8 @@
import android.util.SparseArray
import androidx.test.platform.app.InstrumentationRegistry
import com.android.server.pm.Computer
-import com.android.server.pm.parsing.pkg.AndroidPackage
+import com.android.server.pm.parsing.pkg.AndroidPackageInternal
+import com.android.server.pm.pkg.AndroidPackage
import com.android.server.pm.pkg.PackageStateInternal
import com.android.server.pm.pkg.PackageUserStateInternal
import com.android.server.pm.pkg.component.ParsedActivityImpl
@@ -303,7 +304,7 @@
)
}
- fun mockPkg(packageName: String) = mockThrowOnUnmocked<AndroidPackage> {
+ fun mockPkg(packageName: String) = mockThrowOnUnmocked<AndroidPackageInternal> {
whenever(this.packageName) { packageName }
whenever(targetSdkVersion) { Build.VERSION_CODES.S }
whenever(isEnabled) { true }
diff --git a/services/tests/PackageManagerServiceTests/unit/src/com/android/server/pm/test/verify/domain/DomainVerificationManagerApiTest.kt b/services/tests/PackageManagerServiceTests/unit/src/com/android/server/pm/test/verify/domain/DomainVerificationManagerApiTest.kt
index 7273b0b..c22bb53 100644
--- a/services/tests/PackageManagerServiceTests/unit/src/com/android/server/pm/test/verify/domain/DomainVerificationManagerApiTest.kt
+++ b/services/tests/PackageManagerServiceTests/unit/src/com/android/server/pm/test/verify/domain/DomainVerificationManagerApiTest.kt
@@ -29,7 +29,8 @@
import android.os.Process
import android.util.ArraySet
import android.util.SparseArray
-import com.android.server.pm.parsing.pkg.AndroidPackage
+import com.android.server.pm.parsing.pkg.AndroidPackageInternal
+import com.android.server.pm.pkg.AndroidPackage
import com.android.server.pm.pkg.PackageStateInternal
import com.android.server.pm.pkg.PackageUserStateInternal
import com.android.server.pm.pkg.component.ParsedActivityImpl
@@ -520,7 +521,7 @@
pkgUserState1: PackageStateInternal.() -> PackageUserStateInternal = {
PackageUserStateInternal.DEFAULT }
) = mockThrowOnUnmocked<PackageStateInternal> {
- val pkg = mockThrowOnUnmocked<AndroidPackage> {
+ val pkg = mockThrowOnUnmocked<AndroidPackageInternal> {
whenever(packageName) { pkgName }
whenever(targetSdkVersion) { Build.VERSION_CODES.S }
whenever(isEnabled) { true }
diff --git a/services/tests/PackageManagerServiceTests/unit/src/com/android/server/pm/test/verify/domain/DomainVerificationPackageTest.kt b/services/tests/PackageManagerServiceTests/unit/src/com/android/server/pm/test/verify/domain/DomainVerificationPackageTest.kt
index ed60c50..e55ff3b 100644
--- a/services/tests/PackageManagerServiceTests/unit/src/com/android/server/pm/test/verify/domain/DomainVerificationPackageTest.kt
+++ b/services/tests/PackageManagerServiceTests/unit/src/com/android/server/pm/test/verify/domain/DomainVerificationPackageTest.kt
@@ -37,7 +37,8 @@
import android.util.SparseArray
import android.util.Xml
import com.android.server.pm.Computer
-import com.android.server.pm.parsing.pkg.AndroidPackage
+import com.android.server.pm.parsing.pkg.AndroidPackageInternal
+import com.android.server.pm.pkg.AndroidPackage
import com.android.server.pm.pkg.PackageStateInternal
import com.android.server.pm.pkg.PackageUserStateInternal
import com.android.server.pm.pkg.component.ParsedActivityImpl
@@ -1046,7 +1047,7 @@
otherDomains: List<String> = listOf(),
isSystemApp: Boolean = false
) = mockThrowOnUnmocked<PackageStateInternal> {
- val pkg = mockThrowOnUnmocked<AndroidPackage> {
+ val pkg = mockThrowOnUnmocked<AndroidPackageInternal> {
whenever(packageName) { pkgName }
whenever(targetSdkVersion) { Build.VERSION_CODES.S }
whenever(isEnabled) { true }
diff --git a/services/tests/PackageManagerServiceTests/unit/src/com/android/server/pm/test/verify/domain/DomainVerificationProxyTest.kt b/services/tests/PackageManagerServiceTests/unit/src/com/android/server/pm/test/verify/domain/DomainVerificationProxyTest.kt
index 0a54094..b985c04 100644
--- a/services/tests/PackageManagerServiceTests/unit/src/com/android/server/pm/test/verify/domain/DomainVerificationProxyTest.kt
+++ b/services/tests/PackageManagerServiceTests/unit/src/com/android/server/pm/test/verify/domain/DomainVerificationProxyTest.kt
@@ -29,7 +29,7 @@
import android.os.UserHandle
import android.util.ArraySet
import com.android.server.DeviceIdleInternal
-import com.android.server.pm.parsing.pkg.AndroidPackage
+import com.android.server.pm.pkg.AndroidPackage
import com.android.server.pm.verify.domain.DomainVerificationCollector
import com.android.server.pm.verify.domain.DomainVerificationManagerInternal
import com.android.server.pm.verify.domain.proxy.DomainVerificationProxy
diff --git a/services/tests/PackageManagerServiceTests/unit/src/com/android/server/pm/test/verify/domain/DomainVerificationSettingsMutationTest.kt b/services/tests/PackageManagerServiceTests/unit/src/com/android/server/pm/test/verify/domain/DomainVerificationSettingsMutationTest.kt
index fc20c26..427b5b3 100644
--- a/services/tests/PackageManagerServiceTests/unit/src/com/android/server/pm/test/verify/domain/DomainVerificationSettingsMutationTest.kt
+++ b/services/tests/PackageManagerServiceTests/unit/src/com/android/server/pm/test/verify/domain/DomainVerificationSettingsMutationTest.kt
@@ -19,16 +19,16 @@
import android.content.Context
import android.content.Intent
import android.content.pm.PackageManager
-import com.android.server.pm.pkg.component.ParsedActivityImpl
-import com.android.server.pm.pkg.component.ParsedIntentInfoImpl
-import com.android.server.pm.pkg.PackageUserStateInternal
import android.content.pm.verify.domain.DomainVerificationState
import android.os.Build
import android.os.Process
import android.util.ArraySet
import android.util.SparseArray
-import com.android.server.pm.parsing.pkg.AndroidPackage
+import com.android.server.pm.parsing.pkg.AndroidPackageInternal
import com.android.server.pm.pkg.PackageStateInternal
+import com.android.server.pm.pkg.PackageUserStateInternal
+import com.android.server.pm.pkg.component.ParsedActivityImpl
+import com.android.server.pm.pkg.component.ParsedIntentInfoImpl
import com.android.server.pm.verify.domain.DomainVerificationManagerInternal
import com.android.server.pm.verify.domain.DomainVerificationService
import com.android.server.pm.verify.domain.proxy.DomainVerificationProxy
@@ -187,7 +187,7 @@
}
- fun mockPkg() = mockThrowOnUnmocked<AndroidPackage> {
+ fun mockPkg() = mockThrowOnUnmocked<AndroidPackageInternal> {
whenever(packageName) { TEST_PKG }
whenever(targetSdkVersion) { Build.VERSION_CODES.S }
whenever(isEnabled) { true }
diff --git a/services/tests/PackageManagerServiceTests/unit/src/com/android/server/pm/test/verify/domain/DomainVerificationUserSelectionOverrideTest.kt b/services/tests/PackageManagerServiceTests/unit/src/com/android/server/pm/test/verify/domain/DomainVerificationUserSelectionOverrideTest.kt
index 589633c..6bb5f39 100644
--- a/services/tests/PackageManagerServiceTests/unit/src/com/android/server/pm/test/verify/domain/DomainVerificationUserSelectionOverrideTest.kt
+++ b/services/tests/PackageManagerServiceTests/unit/src/com/android/server/pm/test/verify/domain/DomainVerificationUserSelectionOverrideTest.kt
@@ -18,8 +18,6 @@
import android.content.Intent
import android.content.pm.PackageManager
-import com.android.server.pm.pkg.component.ParsedActivityImpl
-import com.android.server.pm.pkg.component.ParsedIntentInfoImpl
import android.content.pm.verify.domain.DomainVerificationManager
import android.content.pm.verify.domain.DomainVerificationState
import android.content.pm.verify.domain.DomainVerificationUserState
@@ -28,9 +26,12 @@
import android.os.Process
import android.util.ArraySet
import android.util.SparseArray
-import com.android.server.pm.parsing.pkg.AndroidPackage
+import com.android.server.pm.parsing.pkg.AndroidPackageInternal
+import com.android.server.pm.pkg.AndroidPackage
import com.android.server.pm.pkg.PackageStateInternal
import com.android.server.pm.pkg.PackageUserStateInternal
+import com.android.server.pm.pkg.component.ParsedActivityImpl
+import com.android.server.pm.pkg.component.ParsedIntentInfoImpl
import com.android.server.pm.verify.domain.DomainVerificationService
import com.android.server.testutils.mockThrowOnUnmocked
import com.android.server.testutils.whenever
@@ -107,7 +108,7 @@
fun mockPkgState(pkgName: String, domainSetId: UUID) =
mockThrowOnUnmocked<PackageStateInternal> {
- val pkg = mockThrowOnUnmocked<AndroidPackage> {
+ val pkg = mockThrowOnUnmocked<AndroidPackageInternal> {
whenever(packageName) { pkgName }
whenever(targetSdkVersion) { Build.VERSION_CODES.S }
whenever(isEnabled) { true }
diff --git a/services/tests/mockingservicestests/src/com/android/server/alarm/AlarmManagerServiceTest.java b/services/tests/mockingservicestests/src/com/android/server/alarm/AlarmManagerServiceTest.java
index f9a60b6..d9c622d 100644
--- a/services/tests/mockingservicestests/src/com/android/server/alarm/AlarmManagerServiceTest.java
+++ b/services/tests/mockingservicestests/src/com/android/server/alarm/AlarmManagerServiceTest.java
@@ -167,9 +167,9 @@
import com.android.server.DeviceIdleInternal;
import com.android.server.LocalServices;
import com.android.server.SystemService;
-import com.android.server.pm.parsing.pkg.AndroidPackage;
import com.android.server.pm.permission.PermissionManagerService;
import com.android.server.pm.permission.PermissionManagerServiceInternal;
+import com.android.server.pm.pkg.AndroidPackage;
import com.android.server.tare.EconomyManagerInternal;
import com.android.server.usage.AppStandbyInternal;
diff --git a/services/tests/mockingservicestests/src/com/android/server/appop/AppOpsServiceTest.java b/services/tests/mockingservicestests/src/com/android/server/appop/AppOpsServiceTest.java
index 82334f2..9acc5b9 100644
--- a/services/tests/mockingservicestests/src/com/android/server/appop/AppOpsServiceTest.java
+++ b/services/tests/mockingservicestests/src/com/android/server/appop/AppOpsServiceTest.java
@@ -58,7 +58,7 @@
import com.android.dx.mockito.inline.extended.StaticMockitoSession;
import com.android.server.LocalServices;
-import com.android.server.pm.parsing.pkg.AndroidPackage;
+import com.android.server.pm.pkg.AndroidPackage;
import com.android.server.pm.pkg.PackageStateInternal;
import org.junit.After;
diff --git a/services/tests/mockingservicestests/src/com/android/server/pm/MockSystem.kt b/services/tests/mockingservicestests/src/com/android/server/pm/MockSystem.kt
index efc1b58..bb5b1d8 100644
--- a/services/tests/mockingservicestests/src/com/android/server/pm/MockSystem.kt
+++ b/services/tests/mockingservicestests/src/com/android/server/pm/MockSystem.kt
@@ -62,7 +62,7 @@
import com.android.server.extendedtestutils.wheneverStatic
import com.android.server.pm.dex.DexManager
import com.android.server.pm.parsing.PackageParser2
-import com.android.server.pm.parsing.pkg.AndroidPackage
+import com.android.server.pm.pkg.AndroidPackage
import com.android.server.pm.parsing.pkg.PackageImpl
import com.android.server.pm.parsing.pkg.ParsedPackage
import com.android.server.pm.permission.PermissionManagerServiceInternal
diff --git a/services/tests/mockingservicestests/src/com/android/server/pm/PackageManagerServiceBootTest.kt b/services/tests/mockingservicestests/src/com/android/server/pm/PackageManagerServiceBootTest.kt
index c9b36f0..987192d 100644
--- a/services/tests/mockingservicestests/src/com/android/server/pm/PackageManagerServiceBootTest.kt
+++ b/services/tests/mockingservicestests/src/com/android/server/pm/PackageManagerServiceBootTest.kt
@@ -21,7 +21,7 @@
import android.os.Build
import android.os.Process
import android.util.Log
-import com.android.server.pm.parsing.pkg.AndroidPackage
+import com.android.server.pm.pkg.AndroidPackage
import com.android.server.testutils.whenever
import org.hamcrest.MatcherAssert.assertThat
import org.hamcrest.Matchers.equalTo
diff --git a/services/tests/mockingservicestests/src/com/android/server/pm/SharedLibrariesImplTest.kt b/services/tests/mockingservicestests/src/com/android/server/pm/SharedLibrariesImplTest.kt
index e59a404..8744f32 100644
--- a/services/tests/mockingservicestests/src/com/android/server/pm/SharedLibrariesImplTest.kt
+++ b/services/tests/mockingservicestests/src/com/android/server/pm/SharedLibrariesImplTest.kt
@@ -28,7 +28,7 @@
import com.android.server.compat.PlatformCompat
import com.android.server.extendedtestutils.wheneverStatic
import com.android.server.pm.PackageManagerService.PLATFORM_PACKAGE_NAME
-import com.android.server.pm.parsing.pkg.AndroidPackage
+import com.android.server.pm.pkg.AndroidPackage
import com.android.server.pm.parsing.pkg.PackageImpl
import com.android.server.pm.parsing.pkg.ParsedPackage
import com.android.server.testutils.any
diff --git a/services/tests/mockingservicestests/src/com/android/server/pm/UserManagerInternalTest.java b/services/tests/mockingservicestests/src/com/android/server/pm/UserManagerInternalTest.java
index 86a5c90..574bab2 100644
--- a/services/tests/mockingservicestests/src/com/android/server/pm/UserManagerInternalTest.java
+++ b/services/tests/mockingservicestests/src/com/android/server/pm/UserManagerInternalTest.java
@@ -19,6 +19,8 @@
import static android.view.Display.DEFAULT_DISPLAY;
import static android.view.Display.INVALID_DISPLAY;
+import static com.android.server.pm.UserManagerInternal.PARENT_DISPLAY;
+
import static com.google.common.truth.Truth.assertWithMessage;
import static org.junit.Assert.assertThrows;
@@ -119,9 +121,6 @@
() -> mUmi.assignUserToDisplay(PROFILE_USER_ID, SECONDARY_DISPLAY_ID));
Log.v(TAG, "Exception: " + e);
- assertWithMessage("exception (%s) message", e).that(e).hasMessageThat()
- .matches("Cannot.*" + PROFILE_USER_ID + ".*" + SECONDARY_DISPLAY_ID
- + ".*parent.*current.*" + PARENT_USER_ID + ".*");
assertNoUserAssignedToDisplay();
}
@@ -136,10 +135,6 @@
() -> mUmi.assignUserToDisplay(PROFILE_USER_ID, SECONDARY_DISPLAY_ID));
Log.v(TAG, "Exception: " + e);
- assertWithMessage("exception (%s) message", e).that(e).hasMessageThat()
- .matches("Cannot.*" + PROFILE_USER_ID + ".*" + SECONDARY_DISPLAY_ID
- + ".*parent.*current.*" + PARENT_USER_ID + ".*");
-
assertNoUserAssignedToDisplay();
}
@@ -173,7 +168,7 @@
addDefaultProfileAndParent();
mUmi.assignUserToDisplay(PARENT_USER_ID, SECONDARY_DISPLAY_ID);
- mUmi.assignUserToDisplay(PROFILE_USER_ID, SECONDARY_DISPLAY_ID);
+ mUmi.assignUserToDisplay(PROFILE_USER_ID, PARENT_DISPLAY);
assertUsersAssignedToDisplays(PARENT_USER_ID, SECONDARY_DISPLAY_ID,
pair(PROFILE_USER_ID, SECONDARY_DISPLAY_ID));
@@ -185,13 +180,10 @@
addDefaultProfileAndParent();
mUmi.assignUserToDisplay(PARENT_USER_ID, SECONDARY_DISPLAY_ID);
- IllegalStateException e = assertThrows(IllegalStateException.class,
- () -> mUmi.assignUserToDisplay(PROFILE_USER_ID, OTHER_SECONDARY_DISPLAY_ID));
+ IllegalArgumentException e = assertThrows(IllegalArgumentException.class,
+ () -> mUmi.assignUserToDisplay(PROFILE_USER_ID, SECONDARY_DISPLAY_ID));
Log.v(TAG, "Exception: " + e);
- assertWithMessage("exception (%s) message", e).that(e).hasMessageThat()
- .matches("Cannot.*" + PROFILE_USER_ID + ".*" + OTHER_SECONDARY_DISPLAY_ID
- + ".*parent.*" + PARENT_USER_ID + ".*" + SECONDARY_DISPLAY_ID + ".*");
assertUserAssignedToDisplay(PARENT_USER_ID, SECONDARY_DISPLAY_ID);
}
diff --git a/services/tests/mockingservicestests/src/com/android/server/pm/UserManagerServiceOrInternalTestCase.java b/services/tests/mockingservicestests/src/com/android/server/pm/UserManagerServiceOrInternalTestCase.java
index 991053a1..538adb2 100644
--- a/services/tests/mockingservicestests/src/com/android/server/pm/UserManagerServiceOrInternalTestCase.java
+++ b/services/tests/mockingservicestests/src/com/android/server/pm/UserManagerServiceOrInternalTestCase.java
@@ -267,7 +267,7 @@
mockCurrentUser(USER_ID);
assertWithMessage("isUserVisibleOnDisplay(%s, %s)", USER_ID, INVALID_DISPLAY)
- .that(isUserVisibleOnDisplay(USER_ID, INVALID_DISPLAY)).isTrue();
+ .that(isUserVisibleOnDisplay(USER_ID, INVALID_DISPLAY)).isFalse();
}
@Test
@@ -287,6 +287,49 @@
}
@Test
+ public void testIsUserVisibleOnDisplay_mumd_currentUserUnassignedSecondaryDisplay() {
+ enableUsersOnSecondaryDisplays();
+ mockCurrentUser(USER_ID);
+
+ assertWithMessage("isUserVisibleOnDisplay(%s, %s)", USER_ID, SECONDARY_DISPLAY_ID)
+ .that(isUserVisibleOnDisplay(USER_ID, SECONDARY_DISPLAY_ID)).isTrue();
+ }
+
+ @Test
+ public void testIsUserVisibleOnDisplay_mumd_currentUserSecondaryDisplayAssignedToAnotherUser() {
+ enableUsersOnSecondaryDisplays();
+ mockCurrentUser(USER_ID);
+ assignUserToDisplay(OTHER_USER_ID, SECONDARY_DISPLAY_ID);
+
+ assertWithMessage("isUserVisibleOnDisplay(%s, %s)", USER_ID, SECONDARY_DISPLAY_ID)
+ .that(isUserVisibleOnDisplay(USER_ID, SECONDARY_DISPLAY_ID)).isFalse();
+ }
+
+ @Test
+ public void testIsUserVisibleOnDisplay_mumd_startedProfileOfCurrentUserSecondaryDisplayAssignedToAnotherUser() {
+ enableUsersOnSecondaryDisplays();
+ addDefaultProfileAndParent();
+ startDefaultProfile();
+ mockCurrentUser(PARENT_USER_ID);
+ assignUserToDisplay(OTHER_USER_ID, SECONDARY_DISPLAY_ID);
+
+ assertWithMessage("isUserVisibleOnDisplay(%s, %s)", PROFILE_USER_ID, SECONDARY_DISPLAY_ID)
+ .that(isUserVisibleOnDisplay(PROFILE_USER_ID, SECONDARY_DISPLAY_ID)).isFalse();
+ }
+
+ @Test
+ public void testIsUserVisibleOnDisplay_mumd_stoppedProfileOfCurrentUserSecondaryDisplayAssignedToAnotherUser() {
+ enableUsersOnSecondaryDisplays();
+ addDefaultProfileAndParent();
+ stopDefaultProfile();
+ mockCurrentUser(PARENT_USER_ID);
+ assignUserToDisplay(OTHER_USER_ID, SECONDARY_DISPLAY_ID);
+
+ assertWithMessage("isUserVisibleOnDisplay(%s, %s)", PROFILE_USER_ID, SECONDARY_DISPLAY_ID)
+ .that(isUserVisibleOnDisplay(PROFILE_USER_ID, SECONDARY_DISPLAY_ID)).isFalse();
+ }
+
+ @Test
public void testIsUserVisibleOnDisplay_nonCurrentUserDefaultDisplay() {
mockCurrentUser(OTHER_USER_ID);
@@ -358,7 +401,7 @@
}
@Test
- public void testIsUserVisibleOnDisplay_bgUserOnSecondaryDisplay() {
+ public void testIsUserVisibleOnDisplay_mumd_bgUserOnSecondaryDisplay() {
enableUsersOnSecondaryDisplays();
mockCurrentUser(OTHER_USER_ID);
assignUserToDisplay(USER_ID, SECONDARY_DISPLAY_ID);
@@ -367,6 +410,16 @@
.that(isUserVisibleOnDisplay(USER_ID, SECONDARY_DISPLAY_ID)).isTrue();
}
+ @Test
+ public void testIsUserVisibleOnDisplay_mumd_bgUserOnAnotherSecondaryDisplay() {
+ enableUsersOnSecondaryDisplays();
+ mockCurrentUser(OTHER_USER_ID);
+ assignUserToDisplay(USER_ID, SECONDARY_DISPLAY_ID);
+
+ assertWithMessage("isUserVisibleOnDisplay(%s, %s)", USER_ID, SECONDARY_DISPLAY_ID)
+ .that(isUserVisibleOnDisplay(USER_ID, OTHER_SECONDARY_DISPLAY_ID)).isFalse();
+ }
+
// NOTE: we don't need to add tests for profiles (started / stopped profiles of bg user), as
// isUserVisibleOnDisplay() for bg users relies only on the user / display assignments
@@ -535,8 +588,7 @@
}
protected final void stopDefaultProfile() {
- // TODO(b/244798930): should set it to STATE_STOPPING or STATE_SHUTDOWN instead
- removeUserState(PROFILE_USER_ID);
+ setUserState(PROFILE_USER_ID, UserState.STATE_STOPPING);
}
// NOTE: should only called by tests that indirectly needs to check user assignments (like
diff --git a/services/tests/mockingservicestests/src/com/android/server/tare/AgentTest.java b/services/tests/mockingservicestests/src/com/android/server/tare/AgentTest.java
index 831a69a..94fff22 100644
--- a/services/tests/mockingservicestests/src/com/android/server/tare/AgentTest.java
+++ b/services/tests/mockingservicestests/src/com/android/server/tare/AgentTest.java
@@ -18,6 +18,7 @@
import static com.android.dx.mockito.inline.extended.ExtendedMockito.doReturn;
import static com.android.dx.mockito.inline.extended.ExtendedMockito.mockitoSession;
+import static com.android.server.tare.TareTestUtils.assertLedgersEqual;
import static org.junit.Assert.assertEquals;
import static org.mockito.ArgumentMatchers.anyInt;
@@ -89,6 +90,33 @@
}
@Test
+ public void testAppRemoval() {
+ final long consumptionLimit = 1_000_000L;
+ final long remainingCakes = consumptionLimit / 2;
+ mScribe.setConsumptionLimitLocked(consumptionLimit);
+ mScribe.adjustRemainingConsumableCakesLocked(remainingCakes - consumptionLimit);
+ assertEquals(remainingCakes, mScribe.getRemainingConsumableCakesLocked());
+
+ final int userId = 0;
+ final String pkgName = "com.test";
+ final Agent agent = new Agent(mIrs, mScribe, mAnalyst);
+ final Ledger ledger = mScribe.getLedgerLocked(userId, pkgName);
+
+ doReturn(consumptionLimit).when(mIrs).getConsumptionLimitLocked();
+ doReturn(consumptionLimit).when(mEconomicPolicy)
+ .getMaxSatiatedBalance(anyInt(), anyString());
+
+ Ledger.Transaction transaction = new Ledger.Transaction(0, 0, 0, null, 5, 10);
+ agent.recordTransactionLocked(userId, pkgName, ledger, transaction, false);
+ assertEquals(5, ledger.getCurrentBalance());
+ assertEquals(remainingCakes - 10, mScribe.getRemainingConsumableCakesLocked());
+
+ agent.onPackageRemovedLocked(userId, pkgName);
+ assertEquals(remainingCakes - 10, mScribe.getRemainingConsumableCakesLocked());
+ assertLedgersEqual(new Ledger(), mScribe.getLedgerLocked(userId, pkgName));
+ }
+
+ @Test
public void testRecordTransaction_UnderMax() {
Agent agent = new Agent(mIrs, mScribe, mAnalyst);
Ledger ledger = new Ledger();
diff --git a/services/tests/mockingservicestests/src/com/android/server/tare/ScribeTest.java b/services/tests/mockingservicestests/src/com/android/server/tare/ScribeTest.java
index 5cf026e..4ce268f 100644
--- a/services/tests/mockingservicestests/src/com/android/server/tare/ScribeTest.java
+++ b/services/tests/mockingservicestests/src/com/android/server/tare/ScribeTest.java
@@ -18,6 +18,7 @@
import static com.android.dx.mockito.inline.extended.ExtendedMockito.inOrder;
import static com.android.dx.mockito.inline.extended.ExtendedMockito.mockitoSession;
+import static com.android.server.tare.TareTestUtils.assertLedgersEqual;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;
@@ -30,7 +31,6 @@
import android.os.UserHandle;
import android.util.Log;
import android.util.SparseArrayMap;
-import android.util.SparseLongArray;
import androidx.test.InstrumentationRegistry;
import androidx.test.filters.SmallTest;
@@ -345,43 +345,6 @@
assertEquals(900, mScribeUnderTest.getRemainingConsumableCakesLocked());
}
- private void assertLedgersEqual(Ledger expected, Ledger actual) {
- if (expected == null) {
- assertNull(actual);
- return;
- }
- assertNotNull(actual);
- assertEquals(expected.getCurrentBalance(), actual.getCurrentBalance());
-
- List<Ledger.Transaction> expectedTransactions = expected.getTransactions();
- List<Ledger.Transaction> actualTransactions = actual.getTransactions();
- assertEquals(expectedTransactions.size(), actualTransactions.size());
- for (int i = 0; i < expectedTransactions.size(); ++i) {
- assertTransactionsEqual(expectedTransactions.get(i), actualTransactions.get(i));
- }
-
- List<Ledger.RewardBucket> expectedRewardBuckets = expected.getRewardBuckets();
- List<Ledger.RewardBucket> actualRewardBuckets = actual.getRewardBuckets();
- assertEquals(expectedRewardBuckets.size(), actualRewardBuckets.size());
- for (int i = 0; i < expectedRewardBuckets.size(); ++i) {
- assertRewardBucketsEqual(expectedRewardBuckets.get(i), actualRewardBuckets.get(i));
- }
- }
-
- private void assertSparseLongArraysEqual(SparseLongArray expected, SparseLongArray actual) {
- if (expected == null) {
- assertNull(actual);
- return;
- }
- assertNotNull(actual);
- final int size = expected.size();
- assertEquals(size, actual.size());
- for (int i = 0; i < size; ++i) {
- assertEquals(expected.keyAt(i), actual.keyAt(i));
- assertEquals(expected.valueAt(i), actual.valueAt(i));
- }
- }
-
private void assertReportListsEqual(List<Analyst.Report> expected,
List<Analyst.Report> actual) {
if (expected == null) {
@@ -425,31 +388,6 @@
}
}
- private void assertRewardBucketsEqual(Ledger.RewardBucket expected,
- Ledger.RewardBucket actual) {
- if (expected == null) {
- assertNull(actual);
- return;
- }
- assertNotNull(actual);
- assertEquals(expected.startTimeMs, actual.startTimeMs);
- assertSparseLongArraysEqual(expected.cumulativeDelta, actual.cumulativeDelta);
- }
-
- private void assertTransactionsEqual(Ledger.Transaction expected, Ledger.Transaction actual) {
- if (expected == null) {
- assertNull(actual);
- return;
- }
- assertNotNull(actual);
- assertEquals(expected.startTimeMs, actual.startTimeMs);
- assertEquals(expected.endTimeMs, actual.endTimeMs);
- assertEquals(expected.eventId, actual.eventId);
- assertEquals(expected.tag, actual.tag);
- assertEquals(expected.delta, actual.delta);
- assertEquals(expected.ctp, actual.ctp);
- }
-
private void addInstalledPackage(int userId, String pkgName) {
PackageInfo pkgInfo = new PackageInfo();
pkgInfo.packageName = pkgName;
diff --git a/services/tests/mockingservicestests/src/com/android/server/tare/TareTestUtils.java b/services/tests/mockingservicestests/src/com/android/server/tare/TareTestUtils.java
new file mode 100644
index 0000000..1e4684b
--- /dev/null
+++ b/services/tests/mockingservicestests/src/com/android/server/tare/TareTestUtils.java
@@ -0,0 +1,89 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server.tare;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertNull;
+
+import android.util.SparseLongArray;
+
+import java.util.List;
+
+public class TareTestUtils {
+ static void assertLedgersEqual(Ledger expected, Ledger actual) {
+ if (expected == null) {
+ assertNull(actual);
+ return;
+ }
+ assertNotNull(actual);
+ assertEquals(expected.getCurrentBalance(), actual.getCurrentBalance());
+
+ List<Ledger.Transaction> expectedTransactions = expected.getTransactions();
+ List<Ledger.Transaction> actualTransactions = actual.getTransactions();
+ assertEquals(expectedTransactions.size(), actualTransactions.size());
+ for (int i = 0; i < expectedTransactions.size(); ++i) {
+ assertTransactionsEqual(expectedTransactions.get(i), actualTransactions.get(i));
+ }
+
+ List<Ledger.RewardBucket> expectedRewardBuckets = expected.getRewardBuckets();
+ List<Ledger.RewardBucket> actualRewardBuckets = actual.getRewardBuckets();
+ assertEquals(expectedRewardBuckets.size(), actualRewardBuckets.size());
+ for (int i = 0; i < expectedRewardBuckets.size(); ++i) {
+ assertRewardBucketsEqual(expectedRewardBuckets.get(i), actualRewardBuckets.get(i));
+ }
+ }
+
+
+ static void assertSparseLongArraysEqual(SparseLongArray expected, SparseLongArray actual) {
+ if (expected == null) {
+ assertNull(actual);
+ return;
+ }
+ assertNotNull(actual);
+ final int size = expected.size();
+ assertEquals(size, actual.size());
+ for (int i = 0; i < size; ++i) {
+ assertEquals(expected.keyAt(i), actual.keyAt(i));
+ assertEquals(expected.valueAt(i), actual.valueAt(i));
+ }
+ }
+
+ static void assertRewardBucketsEqual(Ledger.RewardBucket expected, Ledger.RewardBucket actual) {
+ if (expected == null) {
+ assertNull(actual);
+ return;
+ }
+ assertNotNull(actual);
+ assertEquals(expected.startTimeMs, actual.startTimeMs);
+ assertSparseLongArraysEqual(expected.cumulativeDelta, actual.cumulativeDelta);
+ }
+
+ static void assertTransactionsEqual(Ledger.Transaction expected, Ledger.Transaction actual) {
+ if (expected == null) {
+ assertNull(actual);
+ return;
+ }
+ assertNotNull(actual);
+ assertEquals(expected.startTimeMs, actual.startTimeMs);
+ assertEquals(expected.endTimeMs, actual.endTimeMs);
+ assertEquals(expected.eventId, actual.eventId);
+ assertEquals(expected.tag, actual.tag);
+ assertEquals(expected.delta, actual.delta);
+ assertEquals(expected.ctp, actual.ctp);
+ }
+}
diff --git a/services/tests/servicestests/src/com/android/server/am/UserControllerTest.java b/services/tests/servicestests/src/com/android/server/am/UserControllerTest.java
index db12092..fe079f4 100644
--- a/services/tests/servicestests/src/com/android/server/am/UserControllerTest.java
+++ b/services/tests/servicestests/src/com/android/server/am/UserControllerTest.java
@@ -48,6 +48,7 @@
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertNull;
+import static org.junit.Assert.assertThrows;
import static org.junit.Assert.assertTrue;
import static org.mockito.ArgumentMatchers.anyString;
import static org.mockito.Matchers.any;
@@ -64,7 +65,6 @@
import static org.mockito.Mockito.validateMockitoUsage;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
-import static org.testng.Assert.assertThrows;
import android.annotation.Nullable;
import android.annotation.UserIdInt;
@@ -90,6 +90,7 @@
import android.os.storage.IStorageManager;
import android.platform.test.annotations.Presubmit;
import android.util.Log;
+import android.view.Display;
import androidx.test.filters.SmallTest;
@@ -177,10 +178,11 @@
doNothing().when(mInjector).activityManagerOnUserStopped(anyInt());
doNothing().when(mInjector).clearBroadcastQueueForUser(anyInt());
doNothing().when(mInjector).taskSupervisorRemoveUser(anyInt());
+ mockIsUsersOnSecondaryDisplaysEnabled(false);
// All UserController params are set to default.
mUserController = new UserController(mInjector);
setUpUser(TEST_USER_ID, NO_USERINFO_FLAGS);
- setUpUser(TEST_PRE_CREATED_USER_ID, NO_USERINFO_FLAGS, /* preCreated=*/ true, null);
+ setUpUser(TEST_PRE_CREATED_USER_ID, NO_USERINFO_FLAGS, /* preCreated= */ true, null);
});
}
@@ -199,11 +201,37 @@
verify(mInjector.getWindowManager()).setSwitchingUser(true);
verify(mInjector).clearAllLockedTasks(anyString());
startForegroundUserAssertions();
+ verifyUserAssignedToDisplay(TEST_USER_ID, Display.DEFAULT_DISPLAY);
}
@Test
public void testStartUser_background() {
- mUserController.startUser(TEST_USER_ID, false /* foreground */);
+ boolean started = mUserController.startUser(TEST_USER_ID, /* foreground= */ false);
+ assertWithMessage("startUser(%s, foreground=false)", TEST_USER_ID).that(started).isTrue();
+ verify(mInjector.getWindowManager(), never()).startFreezingScreen(anyInt(), anyInt());
+ verify(mInjector.getWindowManager(), never()).setSwitchingUser(anyBoolean());
+ verify(mInjector, never()).clearAllLockedTasks(anyString());
+ startBackgroundUserAssertions();
+ verifyUserAssignedToDisplay(TEST_USER_ID, Display.DEFAULT_DISPLAY);
+ }
+
+ @Test
+ public void testStartUserOnSecondaryDisplay_defaultDisplay() {
+ assertThrows(IllegalArgumentException.class, () -> mUserController
+ .startUserOnSecondaryDisplay(TEST_USER_ID, Display.DEFAULT_DISPLAY));
+
+ verifyUserNeverAssignedToDisplay();
+ }
+
+ @Test
+ public void testStartUserOnSecondaryDisplay() {
+ boolean started = mUserController.startUserOnSecondaryDisplay(TEST_USER_ID, 42);
+
+ assertWithMessage("startUserOnSecondaryDisplay(%s, %s)", TEST_USER_ID, 42).that(started)
+ .isTrue();
+ verifyUserAssignedToDisplay(TEST_USER_ID, 42);
+
+ // TODO(b/239982558): might need to change assertions
verify(mInjector.getWindowManager(), never()).startFreezingScreen(anyInt(), anyInt());
verify(mInjector.getWindowManager(), never()).setSwitchingUser(anyBoolean());
verify(mInjector, never()).clearAllLockedTasks(anyString());
@@ -611,6 +639,7 @@
setUpAndStartUserInBackground(TEST_USER_ID1);
assertThrows(IllegalArgumentException.class,
() -> mUserController.stopProfile(TEST_USER_ID1));
+ verifyUserUnassignedFromDisplayNeverCalled(TEST_USER_ID);
}
@Test
@@ -623,13 +652,26 @@
@Test
public void testStartProfile() throws Exception {
setUpAndStartProfileInBackground(TEST_USER_ID1);
+
startBackgroundUserAssertions();
+ verifyUserAssignedToDisplay(TEST_USER_ID1, Display.DEFAULT_DISPLAY);
+ }
+
+ @Test
+ public void testStartProfile_whenUsersOnSecondaryDisplaysIsEnabled() throws Exception {
+ mockIsUsersOnSecondaryDisplaysEnabled(true);
+
+ setUpAndStartProfileInBackground(TEST_USER_ID1);
+
+ startBackgroundUserAssertions();
+ verifyUserAssignedToDisplay(TEST_USER_ID1, UserManagerInternal.PARENT_DISPLAY);
}
@Test
public void testStopProfile() throws Exception {
setUpAndStartProfileInBackground(TEST_USER_ID1);
assertProfileLockedOrUnlockedAfterStopping(TEST_USER_ID1, /* expectLocking= */ true);
+ verifyUserUnassignedFromDisplay(TEST_USER_ID1);
}
/** Tests handleIncomingUser() for a variety of permissions and situations. */
@@ -680,7 +722,7 @@
eq(INTERACT_ACROSS_PROFILES), anyInt(), anyInt(), any())).thenReturn(false);
checkHandleIncomingUser(user1a.id, user2.id, ALLOW_NON_FULL, true);
- checkHandleIncomingUser(user1a.id, user2.id, ALLOW_NON_FULL_IN_PROFILE, false);
+ checkHandleIncomingUser(user1a.id, user2.id, ALLOW_NON_FULL_IN_PROFILE, false);
checkHandleIncomingUser(user1a.id, user2.id, ALLOW_FULL_ONLY, false);
checkHandleIncomingUser(user1a.id, user2.id, ALLOW_PROFILES_OR_NON_FULL, true);
@@ -876,6 +918,26 @@
}
}
+ private void mockIsUsersOnSecondaryDisplaysEnabled(boolean value) {
+ when(mInjector.isUsersOnSecondaryDisplaysEnabled()).thenReturn(value);
+ }
+
+ private void verifyUserAssignedToDisplay(@UserIdInt int userId, int displayId) {
+ verify(mInjector.getUserManagerInternal()).assignUserToDisplay(userId, displayId);
+ }
+
+ private void verifyUserNeverAssignedToDisplay() {
+ verify(mInjector.getUserManagerInternal(), never()).assignUserToDisplay(anyInt(), anyInt());
+ }
+
+ private void verifyUserUnassignedFromDisplay(@UserIdInt int userId) {
+ verify(mInjector.getUserManagerInternal()).unassignUserFromDisplay(userId);
+ }
+
+ private void verifyUserUnassignedFromDisplayNeverCalled(@UserIdInt int userId) {
+ verify(mInjector.getUserManagerInternal(), never()).unassignUserFromDisplay(userId);
+ }
+
// Should be public to allow mocking
private static class TestInjector extends UserController.Injector {
public final TestHandler mHandler;
diff --git a/services/tests/servicestests/src/com/android/server/net/NetworkPolicyManagerServiceTest.java b/services/tests/servicestests/src/com/android/server/net/NetworkPolicyManagerServiceTest.java
index 821ce5e..3bcde6a 100644
--- a/services/tests/servicestests/src/com/android/server/net/NetworkPolicyManagerServiceTest.java
+++ b/services/tests/servicestests/src/com/android/server/net/NetworkPolicyManagerServiceTest.java
@@ -168,13 +168,13 @@
import com.android.internal.util.test.FsUtil;
import com.android.server.DeviceIdleInternal;
import com.android.server.LocalServices;
-import com.android.server.pm.parsing.pkg.AndroidPackage;
+import com.android.server.pm.pkg.AndroidPackage;
import com.android.server.usage.AppStandbyInternal;
-import com.google.common.util.concurrent.AbstractFuture;
-
import libcore.io.Streams;
+import com.google.common.util.concurrent.AbstractFuture;
+
import org.junit.After;
import org.junit.Before;
import org.junit.Rule;
diff --git a/services/tests/servicestests/src/com/android/server/om/OverlayActorEnforcerTests.kt b/services/tests/servicestests/src/com/android/server/om/OverlayActorEnforcerTests.kt
index 38125c7..8f6dd5d 100644
--- a/services/tests/servicestests/src/com/android/server/om/OverlayActorEnforcerTests.kt
+++ b/services/tests/servicestests/src/com/android/server/om/OverlayActorEnforcerTests.kt
@@ -23,7 +23,7 @@
import android.os.Process
import android.util.ArrayMap
import com.android.server.om.OverlayActorEnforcer.ActorState
-import com.android.server.pm.parsing.pkg.AndroidPackage
+import com.android.server.pm.pkg.AndroidPackage
import com.android.server.testutils.mockThrowOnUnmocked
import com.android.server.testutils.whenever
import com.google.common.truth.Truth.assertThat
diff --git a/services/tests/servicestests/src/com/android/server/om/OverlayManagerServiceImplTestsBase.java b/services/tests/servicestests/src/com/android/server/om/OverlayManagerServiceImplTestsBase.java
index b793482..301697d 100644
--- a/services/tests/servicestests/src/com/android/server/om/OverlayManagerServiceImplTestsBase.java
+++ b/services/tests/servicestests/src/com/android/server/om/OverlayManagerServiceImplTestsBase.java
@@ -33,13 +33,11 @@
import android.text.TextUtils;
import android.util.ArrayMap;
import android.util.ArraySet;
-import android.util.Pair;
import androidx.annotation.Nullable;
import com.android.internal.content.om.OverlayConfig;
-import com.android.internal.util.CollectionUtils;
-import com.android.server.pm.parsing.pkg.AndroidPackage;
+import com.android.server.pm.pkg.AndroidPackage;
import org.junit.Assert;
import org.junit.Before;
diff --git a/services/tests/servicestests/src/com/android/server/om/OverlayReferenceMapperTests.kt b/services/tests/servicestests/src/com/android/server/om/OverlayReferenceMapperTests.kt
index 876c845..7be4921 100644
--- a/services/tests/servicestests/src/com/android/server/om/OverlayReferenceMapperTests.kt
+++ b/services/tests/servicestests/src/com/android/server/om/OverlayReferenceMapperTests.kt
@@ -17,7 +17,7 @@
package com.android.server.om
import android.net.Uri
-import com.android.server.pm.parsing.pkg.AndroidPackage
+import com.android.server.pm.pkg.AndroidPackage
import com.android.server.testutils.mockThrowOnUnmocked
import com.android.server.testutils.whenever
import com.google.common.truth.Truth.assertThat
diff --git a/services/tests/servicestests/src/com/android/server/people/data/DataManagerTest.java b/services/tests/servicestests/src/com/android/server/people/data/DataManagerTest.java
index 66c3f07..050fbea 100644
--- a/services/tests/servicestests/src/com/android/server/people/data/DataManagerTest.java
+++ b/services/tests/servicestests/src/com/android/server/people/data/DataManagerTest.java
@@ -93,7 +93,7 @@
import com.android.server.LocalServices;
import com.android.server.notification.NotificationManagerInternal;
import com.android.server.people.PeopleService;
-import com.android.server.pm.parsing.pkg.AndroidPackage;
+import com.android.server.pm.pkg.AndroidPackage;
import com.google.common.collect.Iterables;
diff --git a/services/tests/servicestests/src/com/android/server/pm/ApexManagerTest.java b/services/tests/servicestests/src/com/android/server/pm/ApexManagerTest.java
index 503ca69..a7739ed 100644
--- a/services/tests/servicestests/src/com/android/server/pm/ApexManagerTest.java
+++ b/services/tests/servicestests/src/com/android/server/pm/ApexManagerTest.java
@@ -47,7 +47,7 @@
import com.android.server.pm.parsing.PackageParser2;
import com.android.server.pm.parsing.TestPackageParser2;
-import com.android.server.pm.parsing.pkg.AndroidPackage;
+import com.android.server.pm.pkg.AndroidPackage;
import org.junit.Before;
import org.junit.Test;
diff --git a/services/tests/servicestests/src/com/android/server/pm/AppsFilterImplTest.java b/services/tests/servicestests/src/com/android/server/pm/AppsFilterImplTest.java
index af3b52f..c321639 100644
--- a/services/tests/servicestests/src/com/android/server/pm/AppsFilterImplTest.java
+++ b/services/tests/servicestests/src/com/android/server/pm/AppsFilterImplTest.java
@@ -47,9 +47,9 @@
import androidx.annotation.NonNull;
import com.android.server.om.OverlayReferenceMapper;
-import com.android.server.pm.parsing.pkg.AndroidPackage;
import com.android.server.pm.parsing.pkg.PackageImpl;
import com.android.server.pm.parsing.pkg.ParsedPackage;
+import com.android.server.pm.pkg.AndroidPackage;
import com.android.server.pm.pkg.component.ParsedActivity;
import com.android.server.pm.pkg.component.ParsedActivityImpl;
import com.android.server.pm.pkg.component.ParsedComponentImpl;
diff --git a/services/tests/servicestests/src/com/android/server/pm/PackageParserTest.java b/services/tests/servicestests/src/com/android/server/pm/PackageParserTest.java
index b32ace5..67eeb4e 100644
--- a/services/tests/servicestests/src/com/android/server/pm/PackageParserTest.java
+++ b/services/tests/servicestests/src/com/android/server/pm/PackageParserTest.java
@@ -62,11 +62,11 @@
import com.android.server.pm.parsing.PackageInfoUtils;
import com.android.server.pm.parsing.PackageParser2;
import com.android.server.pm.parsing.TestPackageParser2;
-import com.android.server.pm.parsing.pkg.AndroidPackage;
import com.android.server.pm.parsing.pkg.AndroidPackageUtils;
import com.android.server.pm.parsing.pkg.PackageImpl;
import com.android.server.pm.parsing.pkg.ParsedPackage;
import com.android.server.pm.permission.CompatibilityPermissionInfo;
+import com.android.server.pm.pkg.AndroidPackage;
import com.android.server.pm.pkg.PackageUserStateInternal;
import com.android.server.pm.pkg.component.ParsedActivity;
import com.android.server.pm.pkg.component.ParsedActivityImpl;
diff --git a/services/tests/servicestests/src/com/android/server/pm/PackageSettingBuilder.java b/services/tests/servicestests/src/com/android/server/pm/PackageSettingBuilder.java
index 94d8358..42be3d3 100644
--- a/services/tests/servicestests/src/com/android/server/pm/PackageSettingBuilder.java
+++ b/services/tests/servicestests/src/com/android/server/pm/PackageSettingBuilder.java
@@ -19,7 +19,8 @@
import android.content.pm.SigningDetails;
import android.util.SparseArray;
-import com.android.server.pm.parsing.pkg.AndroidPackage;
+import com.android.server.pm.parsing.pkg.ParsedPackage;
+import com.android.server.pm.pkg.AndroidPackage;
import com.android.server.pm.pkg.PackageUserStateImpl;
import java.io.File;
@@ -166,7 +167,7 @@
packageSetting.setSignatures(mSigningDetails != null
? new PackageSignatures(mSigningDetails)
: new PackageSignatures());
- packageSetting.setPkg(mPkg);
+ packageSetting.setPkg((ParsedPackage) mPkg);
packageSetting.setAppId(mAppId);
packageSetting.setVolumeUuid(this.mVolumeUuid);
if (mInstallSource != null) {
diff --git a/services/tests/servicestests/src/com/android/server/pm/SELinuxMMACTest.java b/services/tests/servicestests/src/com/android/server/pm/SELinuxMMACTest.java
index 901b200..eb91671 100644
--- a/services/tests/servicestests/src/com/android/server/pm/SELinuxMMACTest.java
+++ b/services/tests/servicestests/src/com/android/server/pm/SELinuxMMACTest.java
@@ -26,9 +26,9 @@
import android.platform.test.annotations.Presubmit;
import com.android.server.compat.PlatformCompat;
-import com.android.server.pm.parsing.pkg.AndroidPackage;
import com.android.server.pm.parsing.pkg.PackageImpl;
import com.android.server.pm.parsing.pkg.ParsedPackage;
+import com.android.server.pm.pkg.AndroidPackage;
import org.junit.Test;
import org.junit.runner.RunWith;
diff --git a/services/tests/servicestests/src/com/android/server/pm/ScanRequestBuilder.java b/services/tests/servicestests/src/com/android/server/pm/ScanRequestBuilder.java
index 9962a3c..1c3673e 100644
--- a/services/tests/servicestests/src/com/android/server/pm/ScanRequestBuilder.java
+++ b/services/tests/servicestests/src/com/android/server/pm/ScanRequestBuilder.java
@@ -20,8 +20,8 @@
import android.annotation.Nullable;
import android.os.UserHandle;
-import com.android.server.pm.parsing.pkg.AndroidPackage;
import com.android.server.pm.parsing.pkg.ParsedPackage;
+import com.android.server.pm.pkg.AndroidPackage;
class ScanRequestBuilder {
private final ParsedPackage mPkg;
diff --git a/services/tests/servicestests/src/com/android/server/pm/ScanTests.java b/services/tests/servicestests/src/com/android/server/pm/ScanTests.java
index 8e53ca1..084f4f1 100644
--- a/services/tests/servicestests/src/com/android/server/pm/ScanTests.java
+++ b/services/tests/servicestests/src/com/android/server/pm/ScanTests.java
@@ -43,8 +43,6 @@
import android.content.pm.ApplicationInfo;
import android.content.pm.PackageInfo;
import android.content.pm.SharedLibraryInfo;
-import com.android.server.pm.pkg.parsing.ParsingPackage;
-import com.android.server.pm.pkg.component.ParsedUsesPermissionImpl;
import android.content.res.TypedArray;
import android.os.Environment;
import android.os.UserHandle;
@@ -53,9 +51,11 @@
import com.android.server.compat.PlatformCompat;
import com.android.server.pm.parsing.PackageInfoUtils;
-import com.android.server.pm.parsing.pkg.AndroidPackage;
import com.android.server.pm.parsing.pkg.PackageImpl;
import com.android.server.pm.parsing.pkg.ParsedPackage;
+import com.android.server.pm.pkg.AndroidPackage;
+import com.android.server.pm.pkg.component.ParsedUsesPermissionImpl;
+import com.android.server.pm.pkg.parsing.ParsingPackage;
import com.android.server.pm.verify.domain.DomainVerificationManagerInternal;
import org.hamcrest.BaseMatcher;
diff --git a/services/tests/servicestests/src/com/android/server/pm/UserSystemPackageInstallerTest.java b/services/tests/servicestests/src/com/android/server/pm/UserSystemPackageInstallerTest.java
index ba7a103..b7729bb 100644
--- a/services/tests/servicestests/src/com/android/server/pm/UserSystemPackageInstallerTest.java
+++ b/services/tests/servicestests/src/com/android/server/pm/UserSystemPackageInstallerTest.java
@@ -55,9 +55,9 @@
import com.android.server.LocalServices;
import com.android.server.SystemConfig;
-import com.android.server.pm.parsing.pkg.AndroidPackage;
import com.android.server.pm.parsing.pkg.PackageImpl;
import com.android.server.pm.parsing.pkg.ParsedPackage;
+import com.android.server.pm.pkg.AndroidPackage;
import org.junit.After;
import org.junit.Before;
diff --git a/services/tests/servicestests/src/com/android/server/pm/dex/DexMetadataHelperTest.java b/services/tests/servicestests/src/com/android/server/pm/dex/DexMetadataHelperTest.java
index b7b55ba..b2843d8 100644
--- a/services/tests/servicestests/src/com/android/server/pm/dex/DexMetadataHelperTest.java
+++ b/services/tests/servicestests/src/com/android/server/pm/dex/DexMetadataHelperTest.java
@@ -39,9 +39,9 @@
import com.android.frameworks.servicestests.R;
import com.android.server.pm.PackageManagerException;
import com.android.server.pm.parsing.TestPackageParser2;
-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.pm.pkg.AndroidPackage;
import org.junit.Assert;
import org.junit.Before;
diff --git a/services/tests/servicestests/src/com/android/server/pm/dex/DexoptUtilsTest.java b/services/tests/servicestests/src/com/android/server/pm/dex/DexoptUtilsTest.java
index 7c8bbec..ad9f920 100644
--- a/services/tests/servicestests/src/com/android/server/pm/dex/DexoptUtilsTest.java
+++ b/services/tests/servicestests/src/com/android/server/pm/dex/DexoptUtilsTest.java
@@ -23,16 +23,16 @@
import static org.junit.Assert.fail;
import android.content.pm.SharedLibraryInfo;
-import com.android.server.pm.pkg.parsing.ParsingPackage;
import android.platform.test.annotations.Presubmit;
import android.util.SparseArray;
import androidx.test.filters.SmallTest;
import androidx.test.runner.AndroidJUnit4;
-import com.android.server.pm.parsing.pkg.AndroidPackage;
import com.android.server.pm.parsing.pkg.PackageImpl;
import com.android.server.pm.parsing.pkg.ParsedPackage;
+import com.android.server.pm.pkg.AndroidPackage;
+import com.android.server.pm.pkg.parsing.ParsingPackage;
import dalvik.system.DelegateLastClassLoader;
import dalvik.system.DexClassLoader;
diff --git a/services/tests/servicestests/src/com/android/server/pm/parsing/PackageParserLegacyCoreTest.java b/services/tests/servicestests/src/com/android/server/pm/parsing/PackageParserLegacyCoreTest.java
index f013ecc..9cd97ff3 100644
--- a/services/tests/servicestests/src/com/android/server/pm/parsing/PackageParserLegacyCoreTest.java
+++ b/services/tests/servicestests/src/com/android/server/pm/parsing/PackageParserLegacyCoreTest.java
@@ -46,14 +46,13 @@
import com.android.frameworks.servicestests.R;
import com.android.internal.util.ArrayUtils;
import com.android.server.pm.PackageManagerException;
-import com.android.server.pm.parsing.pkg.AndroidPackage;
import com.android.server.pm.parsing.pkg.ParsedPackage;
+import com.android.server.pm.pkg.AndroidPackage;
import com.android.server.pm.pkg.component.ParsedActivityUtils;
import com.android.server.pm.pkg.component.ParsedComponent;
import com.android.server.pm.pkg.component.ParsedIntentInfo;
import com.android.server.pm.pkg.component.ParsedPermission;
import com.android.server.pm.pkg.component.ParsedPermissionUtils;
-import com.android.server.pm.pkg.parsing.ParsingPackage;
import com.android.server.pm.pkg.parsing.ParsingPackageUtils;
import com.google.common.truth.Expect;
diff --git a/services/tests/servicestests/src/com/android/server/pm/parsing/library/AndroidHidlUpdaterTest.java b/services/tests/servicestests/src/com/android/server/pm/parsing/library/AndroidHidlUpdaterTest.java
index 6b60042..d3107b0 100644
--- a/services/tests/servicestests/src/com/android/server/pm/parsing/library/AndroidHidlUpdaterTest.java
+++ b/services/tests/servicestests/src/com/android/server/pm/parsing/library/AndroidHidlUpdaterTest.java
@@ -24,9 +24,9 @@
import androidx.test.filters.SmallTest;
-import com.android.server.pm.parsing.pkg.AndroidPackage;
import com.android.server.pm.parsing.pkg.PackageImpl;
import com.android.server.pm.parsing.pkg.ParsedPackage;
+import com.android.server.pm.pkg.AndroidPackage;
import org.junit.Test;
import org.junit.runner.RunWith;
diff --git a/services/tests/servicestests/src/com/android/server/pm/parsing/library/AndroidNetIpSecIkeUpdaterTest.java b/services/tests/servicestests/src/com/android/server/pm/parsing/library/AndroidNetIpSecIkeUpdaterTest.java
index 70d85b6..36308d2 100644
--- a/services/tests/servicestests/src/com/android/server/pm/parsing/library/AndroidNetIpSecIkeUpdaterTest.java
+++ b/services/tests/servicestests/src/com/android/server/pm/parsing/library/AndroidNetIpSecIkeUpdaterTest.java
@@ -21,9 +21,9 @@
import androidx.test.filters.SmallTest;
-import com.android.server.pm.parsing.pkg.AndroidPackage;
import com.android.server.pm.parsing.pkg.PackageImpl;
import com.android.server.pm.parsing.pkg.ParsedPackage;
+import com.android.server.pm.pkg.AndroidPackage;
import org.junit.Test;
import org.junit.runner.RunWith;
diff --git a/services/tests/servicestests/src/com/android/server/pm/parsing/library/AndroidTestBaseUpdaterTest.java b/services/tests/servicestests/src/com/android/server/pm/parsing/library/AndroidTestBaseUpdaterTest.java
index f536052..3782f5d 100644
--- a/services/tests/servicestests/src/com/android/server/pm/parsing/library/AndroidTestBaseUpdaterTest.java
+++ b/services/tests/servicestests/src/com/android/server/pm/parsing/library/AndroidTestBaseUpdaterTest.java
@@ -23,9 +23,9 @@
import androidx.test.filters.SmallTest;
-import com.android.server.pm.parsing.pkg.AndroidPackage;
import com.android.server.pm.parsing.pkg.PackageImpl;
import com.android.server.pm.parsing.pkg.ParsedPackage;
+import com.android.server.pm.pkg.AndroidPackage;
import org.junit.Test;
import org.junit.runner.RunWith;
diff --git a/services/tests/servicestests/src/com/android/server/pm/parsing/library/AndroidTestRunnerSplitUpdaterTest.java b/services/tests/servicestests/src/com/android/server/pm/parsing/library/AndroidTestRunnerSplitUpdaterTest.java
index 77197e3..a739607 100644
--- a/services/tests/servicestests/src/com/android/server/pm/parsing/library/AndroidTestRunnerSplitUpdaterTest.java
+++ b/services/tests/servicestests/src/com/android/server/pm/parsing/library/AndroidTestRunnerSplitUpdaterTest.java
@@ -25,9 +25,9 @@
import androidx.test.filters.SmallTest;
import com.android.server.pm.parsing.library.PackageBackwardCompatibility.AndroidTestRunnerSplitUpdater;
-import com.android.server.pm.parsing.pkg.AndroidPackage;
import com.android.server.pm.parsing.pkg.PackageImpl;
import com.android.server.pm.parsing.pkg.ParsedPackage;
+import com.android.server.pm.pkg.AndroidPackage;
import org.junit.Test;
import org.junit.runner.RunWith;
diff --git a/services/tests/servicestests/src/com/android/server/pm/parsing/library/ApexSharedLibraryUpdaterTest.java b/services/tests/servicestests/src/com/android/server/pm/parsing/library/ApexSharedLibraryUpdaterTest.java
index 0b144dc..3977d0d 100644
--- a/services/tests/servicestests/src/com/android/server/pm/parsing/library/ApexSharedLibraryUpdaterTest.java
+++ b/services/tests/servicestests/src/com/android/server/pm/parsing/library/ApexSharedLibraryUpdaterTest.java
@@ -23,9 +23,9 @@
import androidx.test.filters.SmallTest;
import com.android.server.SystemConfig;
-import com.android.server.pm.parsing.pkg.AndroidPackage;
import com.android.server.pm.parsing.pkg.PackageImpl;
import com.android.server.pm.parsing.pkg.ParsedPackage;
+import com.android.server.pm.pkg.AndroidPackage;
import org.junit.Before;
import org.junit.Test;
diff --git a/services/tests/servicestests/src/com/android/server/pm/parsing/library/ComGoogleAndroidMapsUpdaterTest.java b/services/tests/servicestests/src/com/android/server/pm/parsing/library/ComGoogleAndroidMapsUpdaterTest.java
index 404f29c..a31c781 100644
--- a/services/tests/servicestests/src/com/android/server/pm/parsing/library/ComGoogleAndroidMapsUpdaterTest.java
+++ b/services/tests/servicestests/src/com/android/server/pm/parsing/library/ComGoogleAndroidMapsUpdaterTest.java
@@ -21,9 +21,9 @@
import androidx.test.filters.SmallTest;
-import com.android.server.pm.parsing.pkg.AndroidPackage;
import com.android.server.pm.parsing.pkg.PackageImpl;
import com.android.server.pm.parsing.pkg.ParsedPackage;
+import com.android.server.pm.pkg.AndroidPackage;
import org.junit.Test;
import org.junit.runner.RunWith;
diff --git a/services/tests/servicestests/src/com/android/server/pm/parsing/library/OrgApacheHttpLegacyUpdaterTest.java b/services/tests/servicestests/src/com/android/server/pm/parsing/library/OrgApacheHttpLegacyUpdaterTest.java
index 95b8d3f..f5e3f4e 100644
--- a/services/tests/servicestests/src/com/android/server/pm/parsing/library/OrgApacheHttpLegacyUpdaterTest.java
+++ b/services/tests/servicestests/src/com/android/server/pm/parsing/library/OrgApacheHttpLegacyUpdaterTest.java
@@ -23,9 +23,9 @@
import androidx.test.filters.SmallTest;
-import com.android.server.pm.parsing.pkg.AndroidPackage;
import com.android.server.pm.parsing.pkg.PackageImpl;
import com.android.server.pm.parsing.pkg.ParsedPackage;
+import com.android.server.pm.pkg.AndroidPackage;
import org.junit.Test;
import org.junit.runner.RunWith;
diff --git a/services/tests/servicestests/src/com/android/server/pm/parsing/library/PackageBackwardCompatibilityTest.java b/services/tests/servicestests/src/com/android/server/pm/parsing/library/PackageBackwardCompatibilityTest.java
index b28446b..b3648b1 100644
--- a/services/tests/servicestests/src/com/android/server/pm/parsing/library/PackageBackwardCompatibilityTest.java
+++ b/services/tests/servicestests/src/com/android/server/pm/parsing/library/PackageBackwardCompatibilityTest.java
@@ -23,16 +23,16 @@
import static com.google.common.truth.Truth.assertThat;
-import com.android.server.pm.pkg.parsing.ParsingPackage;
import android.os.Build;
import android.platform.test.annotations.Presubmit;
import androidx.test.filters.SmallTest;
import com.android.server.pm.parsing.library.PackageBackwardCompatibility.RemoveUnnecessaryAndroidTestBaseLibrary;
-import com.android.server.pm.parsing.pkg.AndroidPackage;
import com.android.server.pm.parsing.pkg.PackageImpl;
import com.android.server.pm.parsing.pkg.ParsedPackage;
+import com.android.server.pm.pkg.AndroidPackage;
+import com.android.server.pm.pkg.parsing.ParsingPackage;
import org.junit.Assume;
import org.junit.Test;
diff --git a/services/tests/servicestests/src/com/android/server/pm/parsing/library/PackageSharedLibraryUpdaterTest.java b/services/tests/servicestests/src/com/android/server/pm/parsing/library/PackageSharedLibraryUpdaterTest.java
index a71572f..2450a14 100644
--- a/services/tests/servicestests/src/com/android/server/pm/parsing/library/PackageSharedLibraryUpdaterTest.java
+++ b/services/tests/servicestests/src/com/android/server/pm/parsing/library/PackageSharedLibraryUpdaterTest.java
@@ -18,8 +18,8 @@
import static org.junit.Assert.assertEquals;
-import com.android.server.pm.parsing.pkg.AndroidPackage;
import com.android.server.pm.parsing.pkg.ParsedPackage;
+import com.android.server.pm.pkg.AndroidPackage;
import java.util.function.Supplier;
diff --git a/services/tests/servicestests/src/com/android/server/pm/parsing/library/RemoveUnnecessaryAndroidTestBaseLibraryTest.java b/services/tests/servicestests/src/com/android/server/pm/parsing/library/RemoveUnnecessaryAndroidTestBaseLibraryTest.java
index 1122490..2825c69 100644
--- a/services/tests/servicestests/src/com/android/server/pm/parsing/library/RemoveUnnecessaryAndroidTestBaseLibraryTest.java
+++ b/services/tests/servicestests/src/com/android/server/pm/parsing/library/RemoveUnnecessaryAndroidTestBaseLibraryTest.java
@@ -24,9 +24,9 @@
import androidx.test.filters.SmallTest;
import com.android.server.pm.parsing.library.PackageBackwardCompatibility.RemoveUnnecessaryAndroidTestBaseLibrary;
-import com.android.server.pm.parsing.pkg.AndroidPackage;
import com.android.server.pm.parsing.pkg.PackageImpl;
import com.android.server.pm.parsing.pkg.ParsedPackage;
+import com.android.server.pm.pkg.AndroidPackage;
import org.junit.Test;
import org.junit.runner.RunWith;
diff --git a/services/tests/servicestests/src/com/android/server/pm/parsing/library/RemoveUnnecessaryOrgApacheHttpLegacyLibraryTest.java b/services/tests/servicestests/src/com/android/server/pm/parsing/library/RemoveUnnecessaryOrgApacheHttpLegacyLibraryTest.java
index 3cc8475..c0da8a7 100644
--- a/services/tests/servicestests/src/com/android/server/pm/parsing/library/RemoveUnnecessaryOrgApacheHttpLegacyLibraryTest.java
+++ b/services/tests/servicestests/src/com/android/server/pm/parsing/library/RemoveUnnecessaryOrgApacheHttpLegacyLibraryTest.java
@@ -24,9 +24,9 @@
import androidx.test.filters.SmallTest;
import com.android.server.pm.parsing.library.PackageBackwardCompatibility.RemoveUnnecessaryOrgApacheHttpLegacyLibrary;
-import com.android.server.pm.parsing.pkg.AndroidPackage;
import com.android.server.pm.parsing.pkg.PackageImpl;
import com.android.server.pm.parsing.pkg.ParsedPackage;
+import com.android.server.pm.pkg.AndroidPackage;
import org.junit.Test;
import org.junit.runner.RunWith;
diff --git a/services/tests/servicestests/src/com/android/server/timedetector/GnssTimeUpdateServiceTest.java b/services/tests/servicestests/src/com/android/server/timedetector/GnssTimeUpdateServiceTest.java
index 6402e12..3f550d0 100644
--- a/services/tests/servicestests/src/com/android/server/timedetector/GnssTimeUpdateServiceTest.java
+++ b/services/tests/servicestests/src/com/android/server/timedetector/GnssTimeUpdateServiceTest.java
@@ -16,15 +16,18 @@
package com.android.server.timedetector;
+import static org.junit.Assert.assertTrue;
import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.Mockito.any;
import static org.mockito.Mockito.anyLong;
import static org.mockito.Mockito.doReturn;
-import static org.mockito.Mockito.never;
+import static org.mockito.Mockito.reset;
import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.verifyZeroInteractions;
import static org.mockito.Mockito.when;
import android.app.AlarmManager;
+import android.app.AlarmManager.OnAlarmListener;
import android.content.Context;
import android.location.Location;
import android.location.LocationListener;
@@ -36,9 +39,6 @@
import androidx.test.runner.AndroidJUnit4;
-import com.android.server.LocalServices;
-
-import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
@@ -64,19 +64,13 @@
public void setUp() {
MockitoAnnotations.initMocks(this);
- when(mMockLocationManager.hasProvider(LocationManager.GPS_PROVIDER))
- .thenReturn(true);
+ installGpsProviderInMockLocationManager();
mGnssTimeUpdateService = new GnssTimeUpdateService(
mMockContext, mMockAlarmManager, mMockLocationManager, mMockLocationManagerInternal,
mMockTimeDetectorInternal);
}
- @After
- public void tearDown() {
- LocalServices.removeServiceForTest(LocationManagerInternal.class);
- }
-
@Test
public void testLocationListenerOnLocationChanged_validLocationTime_suggestsGnssTime() {
TimestampedValue<Long> timeSignal = new TimestampedValue<>(
@@ -85,9 +79,9 @@
LocationTime locationTime = new LocationTime(GNSS_TIME, ELAPSED_REALTIME_NS);
doReturn(locationTime).when(mMockLocationManagerInternal).getGnssTimeMillis();
- mGnssTimeUpdateService.requestGnssTimeUpdates();
+ assertTrue(mGnssTimeUpdateService.startGnssListeningInternal());
- ArgumentCaptor<LocationListener> argumentCaptor =
+ ArgumentCaptor<LocationListener> locationListenerCaptor =
ArgumentCaptor.forClass(LocationListener.class);
verify(mMockLocationManager).requestLocationUpdates(
eq(LocationManager.GPS_PROVIDER),
@@ -95,8 +89,8 @@
.setMinUpdateIntervalMillis(0)
.build()),
any(),
- argumentCaptor.capture());
- LocationListener locationListener = argumentCaptor.getValue();
+ locationListenerCaptor.capture());
+ LocationListener locationListener = locationListenerCaptor.getValue();
Location location = new Location(LocationManager.GPS_PROVIDER);
locationListener.onLocationChanged(location);
@@ -115,9 +109,9 @@
public void testLocationListenerOnLocationChanged_nullLocationTime_doesNotSuggestGnssTime() {
doReturn(null).when(mMockLocationManagerInternal).getGnssTimeMillis();
- mGnssTimeUpdateService.requestGnssTimeUpdates();
+ assertTrue(mGnssTimeUpdateService.startGnssListeningInternal());
- ArgumentCaptor<LocationListener> argumentCaptor =
+ ArgumentCaptor<LocationListener> locationListenerCaptor =
ArgumentCaptor.forClass(LocationListener.class);
verify(mMockLocationManager).requestLocationUpdates(
eq(LocationManager.GPS_PROVIDER),
@@ -125,14 +119,14 @@
.setMinUpdateIntervalMillis(0)
.build()),
any(),
- argumentCaptor.capture());
- LocationListener locationListener = argumentCaptor.getValue();
+ locationListenerCaptor.capture());
+ LocationListener locationListener = locationListenerCaptor.getValue();
Location location = new Location(LocationManager.GPS_PROVIDER);
locationListener.onLocationChanged(location);
verify(mMockLocationManager).removeUpdates(locationListener);
- verify(mMockTimeDetectorInternal, never()).suggestGnssTime(any());
+ verifyZeroInteractions(mMockTimeDetectorInternal);
verify(mMockAlarmManager).set(
eq(AlarmManager.ELAPSED_REALTIME_WAKEUP),
anyLong(),
@@ -140,4 +134,90 @@
any(),
any());
}
+
+ @Test
+ public void testLocationListeningRestartsAfterSleep() {
+ ArgumentCaptor<LocationListener> locationListenerCaptor =
+ ArgumentCaptor.forClass(LocationListener.class);
+ ArgumentCaptor<OnAlarmListener> alarmListenerCaptor =
+ ArgumentCaptor.forClass(OnAlarmListener.class);
+
+ advanceServiceToSleepingState(locationListenerCaptor, alarmListenerCaptor);
+
+ // Simulate the alarm manager's wake-up call.
+ OnAlarmListener wakeUpListener = alarmListenerCaptor.getValue();
+ wakeUpListener.onAlarm();
+
+ // Verify the service returned to location listening.
+ verify(mMockLocationManager).requestLocationUpdates(any(), any(), any(), any());
+ verifyZeroInteractions(mMockAlarmManager, mMockTimeDetectorInternal);
+ }
+
+ // Tests what happens when a call is made to startGnssListeningInternal() when service is
+ // sleeping. This can happen when the start_gnss_listening shell command is used.
+ @Test
+ public void testStartGnssListeningInternalCalledWhenSleeping() {
+ ArgumentCaptor<LocationListener> locationListenerCaptor =
+ ArgumentCaptor.forClass(LocationListener.class);
+ ArgumentCaptor<OnAlarmListener> alarmListenerCaptor =
+ ArgumentCaptor.forClass(OnAlarmListener.class);
+
+ advanceServiceToSleepingState(locationListenerCaptor, alarmListenerCaptor);
+
+ // Call startGnssListeningInternal(), as can happen if the start_gnss_listening shell
+ // command is used.
+ assertTrue(mGnssTimeUpdateService.startGnssListeningInternal());
+
+ // Verify the alarm manager is told to stopped sleeping and the location manager is
+ // listening again.
+ verify(mMockAlarmManager).cancel(alarmListenerCaptor.getValue());
+ verify(mMockLocationManager).requestLocationUpdates(any(), any(), any(), any());
+ verifyZeroInteractions(mMockTimeDetectorInternal);
+ }
+
+ private void advanceServiceToSleepingState(
+ ArgumentCaptor<LocationListener> locationListenerCaptor,
+ ArgumentCaptor<OnAlarmListener> alarmListenerCaptor) {
+ TimestampedValue<Long> timeSignal = new TimestampedValue<>(
+ ELAPSED_REALTIME_MS, GNSS_TIME);
+ GnssTimeSuggestion timeSuggestion = new GnssTimeSuggestion(timeSignal);
+ LocationTime locationTime = new LocationTime(GNSS_TIME, ELAPSED_REALTIME_NS);
+ doReturn(locationTime).when(mMockLocationManagerInternal).getGnssTimeMillis();
+
+ assertTrue(mGnssTimeUpdateService.startGnssListeningInternal());
+
+ verify(mMockLocationManager).requestLocationUpdates(
+ any(), any(), any(), locationListenerCaptor.capture());
+ LocationListener locationListener = locationListenerCaptor.getValue();
+ Location location = new Location(LocationManager.GPS_PROVIDER);
+ verifyZeroInteractions(mMockAlarmManager, mMockTimeDetectorInternal);
+
+ locationListener.onLocationChanged(location);
+
+ verify(mMockLocationManager).removeUpdates(locationListener);
+ verify(mMockTimeDetectorInternal).suggestGnssTime(timeSuggestion);
+
+ // Verify the service is now "sleeping", i.e. waiting for a period before listening for
+ // GNSS locations again.
+ verify(mMockAlarmManager).set(
+ eq(AlarmManager.ELAPSED_REALTIME_WAKEUP),
+ anyLong(),
+ any(),
+ alarmListenerCaptor.capture(),
+ any());
+
+ // Reset mocks making it easier to verify the calls that follow.
+ reset(mMockAlarmManager, mMockTimeDetectorInternal, mMockLocationManager,
+ mMockLocationManagerInternal);
+ installGpsProviderInMockLocationManager();
+ }
+
+ /**
+ * Configures the mock response to ensure {@code
+ * locationManager.hasProvider(LocationManager.GPS_PROVIDER) == true }
+ */
+ private void installGpsProviderInMockLocationManager() {
+ when(mMockLocationManager.hasProvider(LocationManager.GPS_PROVIDER))
+ .thenReturn(true);
+ }
}
diff --git a/services/tests/wmtests/src/com/android/server/wm/ActivityStarterTests.java b/services/tests/wmtests/src/com/android/server/wm/ActivityStarterTests.java
index 2204ae3..85e5bfd 100644
--- a/services/tests/wmtests/src/com/android/server/wm/ActivityStarterTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/ActivityStarterTests.java
@@ -102,7 +102,7 @@
import androidx.test.filters.SmallTest;
-import com.android.server.pm.parsing.pkg.AndroidPackage;
+import com.android.server.pm.pkg.AndroidPackage;
import com.android.server.wm.LaunchParamsController.LaunchParamsModifier;
import com.android.server.wm.utils.MockTracker;
diff --git a/services/tests/wmtests/src/com/android/server/wm/ImeInsetsSourceProviderTest.java b/services/tests/wmtests/src/com/android/server/wm/ImeInsetsSourceProviderTest.java
index ca8481a..c839d12 100644
--- a/services/tests/wmtests/src/com/android/server/wm/ImeInsetsSourceProviderTest.java
+++ b/services/tests/wmtests/src/com/android/server/wm/ImeInsetsSourceProviderTest.java
@@ -63,6 +63,7 @@
public void testInputMethodInputTargetCanShowIme() {
WindowState target = createWindow(null, TYPE_APPLICATION, "app");
mDisplayContent.setImeLayeringTarget(target);
+ mDisplayContent.updateImeInputAndControlTarget(target);
mImeProvider.scheduleShowImePostLayout(target);
assertTrue(mImeProvider.isReadyToShowIme());
}
diff --git a/tests/FlickerTests/src/com/android/server/wm/flicker/ime/OpenImeWindowFromFixedOrientationAppTest.kt b/tests/FlickerTests/src/com/android/server/wm/flicker/ime/OpenImeWindowFromFixedOrientationAppTest.kt
index c41c659..5f025f9 100644
--- a/tests/FlickerTests/src/com/android/server/wm/flicker/ime/OpenImeWindowFromFixedOrientationAppTest.kt
+++ b/tests/FlickerTests/src/com/android/server/wm/flicker/ime/OpenImeWindowFromFixedOrientationAppTest.kt
@@ -76,7 +76,7 @@
}
/** {@inheritDoc} */
- @Postsubmit
+ @Presubmit
@Test
override fun navBarLayerIsVisibleAtStartAndEnd() = super.navBarLayerIsVisibleAtStartAndEnd()
diff --git a/tests/FlickerTests/src/com/android/server/wm/flicker/ime/OpenImeWindowToOverViewTest.kt b/tests/FlickerTests/src/com/android/server/wm/flicker/ime/OpenImeWindowToOverViewTest.kt
index 1af8820..f4d8f5b 100644
--- a/tests/FlickerTests/src/com/android/server/wm/flicker/ime/OpenImeWindowToOverViewTest.kt
+++ b/tests/FlickerTests/src/com/android/server/wm/flicker/ime/OpenImeWindowToOverViewTest.kt
@@ -130,6 +130,7 @@
@Presubmit
@Test
fun navBarLayerIsInvisibleInLandscapeGestural() {
+ Assume.assumeFalse(testSpec.isTablet)
Assume.assumeTrue(testSpec.isLandscapeOrSeascapeAtStart)
Assume.assumeTrue(testSpec.isGesturalNavigation)
Assume.assumeTrue(isShellTransitionsEnabled)
diff --git a/tests/FlickerTests/src/com/android/server/wm/flicker/launch/OpenAppFromNotificationCold.kt b/tests/FlickerTests/src/com/android/server/wm/flicker/launch/OpenAppFromNotificationCold.kt
index 24f2ae9..8d349a6 100644
--- a/tests/FlickerTests/src/com/android/server/wm/flicker/launch/OpenAppFromNotificationCold.kt
+++ b/tests/FlickerTests/src/com/android/server/wm/flicker/launch/OpenAppFromNotificationCold.kt
@@ -24,7 +24,6 @@
import com.android.server.wm.flicker.annotation.Group1
import com.android.server.wm.flicker.dsl.FlickerBuilder
import org.junit.FixMethodOrder
-import org.junit.Test
import org.junit.runner.RunWith
import org.junit.runners.MethodSorters
import org.junit.runners.Parameterized
@@ -59,91 +58,6 @@
}
}
- /** {@inheritDoc} */
- @Postsubmit
- @Test
- override fun navBarLayerPositionAtStartAndEnd() = super.navBarLayerPositionAtStartAndEnd()
-
- /** {@inheritDoc} */
- @Postsubmit
- @Test
- override fun statusBarLayerIsVisibleAtStartAndEnd() =
- super.statusBarLayerIsVisibleAtStartAndEnd()
-
- /** {@inheritDoc} */
- @Postsubmit
- @Test
- override fun statusBarLayerPositionAtStartAndEnd() =
- super.statusBarLayerPositionAtStartAndEnd()
-
- /** {@inheritDoc} */
- @Postsubmit
- @Test
- override fun visibleLayersShownMoreThanOneConsecutiveEntry() =
- super.visibleLayersShownMoreThanOneConsecutiveEntry()
-
- /** {@inheritDoc} */
- @Postsubmit
- @Test
- override fun statusBarWindowIsAlwaysVisible() = super.statusBarWindowIsAlwaysVisible()
-
- /** {@inheritDoc} */
- @Postsubmit
- @Test
- override fun entireScreenCovered() = super.entireScreenCovered()
-
- /** {@inheritDoc} */
- @Postsubmit
- @Test
- override fun navBarLayerIsVisibleAtStartAndEnd() = super.navBarLayerIsVisibleAtStartAndEnd()
-
- /** {@inheritDoc} */
- @Postsubmit
- @Test
- override fun navBarWindowIsAlwaysVisible() = super.navBarWindowIsAlwaysVisible()
-
- /** {@inheritDoc} */
- @Postsubmit
- @Test
- override fun visibleWindowsShownMoreThanOneConsecutiveEntry() =
- super.visibleWindowsShownMoreThanOneConsecutiveEntry()
-
- /** {@inheritDoc} */
- @Postsubmit
- @Test
- override fun notificationAppWindowVisibleAtEnd() = super.notificationAppWindowVisibleAtEnd()
-
- /** {@inheritDoc} */
- @Postsubmit
- @Test
- override fun notificationAppWindowOnTopAtEnd() = super.notificationAppWindowOnTopAtEnd()
-
- /** {@inheritDoc} */
- @Postsubmit
- @Test
- override fun notificationAppLayerVisibleAtEnd() = super.notificationAppLayerVisibleAtEnd()
-
- /** {@inheritDoc} */
- @Postsubmit
- @Test
- override fun appWindowBecomesTopWindow() = super.appWindowBecomesTopWindow()
-
- /** {@inheritDoc} */
- @Test
- @Postsubmit
- override fun appWindowBecomesVisible() = appWindowBecomesVisible_coldStart()
-
- /** {@inheritDoc} */
- @Test
- @Postsubmit
- override fun appLayerBecomesVisible() = appLayerBecomesVisible_coldStart()
-
- /** {@inheritDoc} */
- @Postsubmit
- @Test
- override fun appWindowIsTopWindowAtEnd() =
- super.appWindowIsTopWindowAtEnd()
-
companion object {
/**
* Creates the test configurations.
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 d09507f..f24f71e 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
@@ -127,12 +127,6 @@
override fun navBarLayerPositionAtStartAndEnd() =
super.navBarLayerPositionAtStartAndEnd()
- /** {@inheritDoc} */
- @FlakyTest
- @Test
- override fun visibleLayersShownMoreThanOneConsecutiveEntry() =
- super.visibleLayersShownMoreThanOneConsecutiveEntry()
-
companion object {
/**
* Creates the test configurations.
diff --git a/tools/codegen/BUILD.bazel b/tools/codegen/BUILD.bazel
new file mode 100644
index 0000000..c14046d
--- /dev/null
+++ b/tools/codegen/BUILD.bazel
@@ -0,0 +1,21 @@
+# TODO(b/245731902): auto-generate these with bp2build.
+load("@rules_kotlin//kotlin:jvm_library.bzl", "kt_jvm_library")
+
+java_binary(
+ name = "codegen_cli",
+ main_class = "com.android.codegen.MainKt",
+ runtime_deps = [
+ ":codegen_cli_kt_lib",
+ ],
+)
+
+kt_jvm_library(
+ name = "codegen_cli_kt_lib",
+ srcs = glob(["src/**/*.kt"]),
+ deps = ["//external/javaparser"],
+)
+
+kt_jvm_library(
+ name = "codegen-version-info",
+ srcs = glob(["src/**/SharedConstants.kt"]),
+)