Merge "Revert^2 "Filter memory tombstone fields before DropBox logging"" into main
diff --git a/core/java/android/app/NotificationManager.java b/core/java/android/app/NotificationManager.java
index 05b3316..1e1ec60 100644
--- a/core/java/android/app/NotificationManager.java
+++ b/core/java/android/app/NotificationManager.java
@@ -1656,7 +1656,8 @@
if (Flags.modesApi() && Flags.modesUi()) {
PackageManager pm = mContext.getPackageManager();
return !pm.hasSystemFeature(PackageManager.FEATURE_WATCH)
- && !pm.hasSystemFeature(PackageManager.FEATURE_AUTOMOTIVE);
+ && !pm.hasSystemFeature(PackageManager.FEATURE_AUTOMOTIVE)
+ && !pm.hasSystemFeature(PackageManager.FEATURE_LEANBACK);
} else {
return false;
}
diff --git a/core/java/android/app/supervision/flags.aconfig b/core/java/android/app/supervision/flags.aconfig
index 4ee3a03..18182b8 100644
--- a/core/java/android/app/supervision/flags.aconfig
+++ b/core/java/android/app/supervision/flags.aconfig
@@ -40,3 +40,11 @@
description: "Flag to enable the SupervisionAppService"
bug: "389123070"
}
+
+flag {
+ name: "enable_supervision_settings_screen"
+ is_exported: true
+ namespace: "supervision"
+ description: "Flag that enables the Supervision settings screen with top-level Android settings entry point"
+ bug: "383404606"
+}
diff --git a/core/java/android/os/Parcel.java b/core/java/android/os/Parcel.java
index 4aa7462..c6a63a7 100644
--- a/core/java/android/os/Parcel.java
+++ b/core/java/android/os/Parcel.java
@@ -50,6 +50,7 @@
import dalvik.annotation.optimization.CriticalNative;
import dalvik.annotation.optimization.FastNative;
+import dalvik.annotation.optimization.NeverInline;
import libcore.util.SneakyThrow;
@@ -628,6 +629,19 @@
}
}
+ @NeverInline
+ private void errorUsedWhileRecycling() {
+ String error = "Parcel used while recycled. "
+ + Log.getStackTraceString(new Throwable())
+ + " Original recycle call (if DEBUG_RECYCLE): ", mStack;
+ Log.wtf(TAG, error);
+ // TODO(b/381155347): harder error
+ }
+
+ private void assertNotRecycled() {
+ if (mRecycled) errorUsedWhileRecycling();
+ }
+
/**
* Set a {@link ReadWriteHelper}, which can be used to avoid having duplicate strings, for
* example.
@@ -1180,6 +1194,7 @@
* growing dataCapacity() if needed.
*/
public final void writeInt(int val) {
+ assertNotRecycled();
int err = nativeWriteInt(mNativePtr, val);
if (err != OK) {
nativeSignalExceptionForError(err);
@@ -3282,6 +3297,7 @@
* Read an integer value from the parcel at the current dataPosition().
*/
public final int readInt() {
+ assertNotRecycled();
return nativeReadInt(mNativePtr);
}
diff --git a/core/java/android/permission/flags.aconfig b/core/java/android/permission/flags.aconfig
index 70d8891..a480a3b 100644
--- a/core/java/android/permission/flags.aconfig
+++ b/core/java/android/permission/flags.aconfig
@@ -493,3 +493,9 @@
bug: "341941666"
}
+flag {
+ name: "sqlite_discrete_op_event_logging_enabled"
+ namespace: "permissions"
+ description: "Collect sqlite performance metrics for discrete ops."
+ bug: "377584611"
+}
diff --git a/core/java/android/provider/Settings.java b/core/java/android/provider/Settings.java
index a22333b..9626808 100644
--- a/core/java/android/provider/Settings.java
+++ b/core/java/android/provider/Settings.java
@@ -353,6 +353,18 @@
*/
public static final String ACTION_ONE_HANDED_SETTINGS =
"android.settings.action.ONE_HANDED_SETTINGS";
+
+ /**
+ * Activity Action: Show Double tap power gesture Settings page.
+ * <p>
+ * Input: Nothing
+ * <p>
+ * Output: Nothing
+ * @hide
+ */
+ public static final String ACTION_DOUBLE_TAP_POWER_SETTINGS =
+ "android.settings.action.DOUBLE_TAP_POWER_SETTINGS";
+
/**
* The return values for {@link Settings.Config#set}
* @hide
@@ -12356,12 +12368,6 @@
public static final String CAMERA_EXTENSIONS_FALLBACK = "camera_extensions_fallback";
/**
- * Controls whether contextual suggestions can be shown in the media controls.
- * @hide
- */
- public static final String MEDIA_CONTROLS_RECOMMENDATION = "qs_media_recommend";
-
- /**
* Controls magnification mode when magnification is enabled via a system-wide triple tap
* gesture or the accessibility shortcut.
*
diff --git a/core/java/android/view/Choreographer.java b/core/java/android/view/Choreographer.java
index 992790e..053ccdd 100644
--- a/core/java/android/view/Choreographer.java
+++ b/core/java/android/view/Choreographer.java
@@ -250,11 +250,14 @@
/**
* Set flag to indicate that client is blocked waiting for buffer release and
- * buffer stuffing recovery should soon begin.
+ * buffer stuffing recovery should soon begin. This is provided with the
+ * duration of time in nanoseconds that the client was blocked for.
* @hide
*/
- public void onWaitForBufferRelease() {
- mBufferStuffingState.isStuffed.set(true);
+ public void onWaitForBufferRelease(long durationNanos) {
+ if (durationNanos > mLastFrameIntervalNanos / 2) {
+ mBufferStuffingState.isStuffed.set(true);
+ }
}
/**
diff --git a/core/java/android/view/SurfaceView.java b/core/java/android/view/SurfaceView.java
index 780e761..dd32947 100644
--- a/core/java/android/view/SurfaceView.java
+++ b/core/java/android/view/SurfaceView.java
@@ -2391,4 +2391,9 @@
}
}
}
+
+ @Override
+ public CharSequence getAccessibilityClassName() {
+ return SurfaceView.class.getName();
+ }
}
diff --git a/core/java/android/view/TextureView.java b/core/java/android/view/TextureView.java
index ebc86ee..0c6eaae 100644
--- a/core/java/android/view/TextureView.java
+++ b/core/java/android/view/TextureView.java
@@ -918,6 +918,11 @@
mLastFrameTimeMillis = now;
}
+ @Override
+ public CharSequence getAccessibilityClassName() {
+ return TextureView.class.getName();
+ }
+
@UnsupportedAppUsage
private final SurfaceTexture.OnFrameAvailableListener mUpdateListener =
surfaceTexture -> {
diff --git a/core/java/android/window/flags/windowing_sdk.aconfig b/core/java/android/window/flags/windowing_sdk.aconfig
index f178b0e..1b946af 100644
--- a/core/java/android/window/flags/windowing_sdk.aconfig
+++ b/core/java/android/window/flags/windowing_sdk.aconfig
@@ -178,3 +178,10 @@
purpose: PURPOSE_BUGFIX
}
}
+
+flag {
+ namespace: "windowing_sdk"
+ name: "safe_region_letterboxing"
+ description: "Enables letterboxing for a safe region"
+ bug: "380132497"
+}
diff --git a/core/jni/android_graphics_BLASTBufferQueue.cpp b/core/jni/android_graphics_BLASTBufferQueue.cpp
index 7b61a5d..10d6d33 100644
--- a/core/jni/android_graphics_BLASTBufferQueue.cpp
+++ b/core/jni/android_graphics_BLASTBufferQueue.cpp
@@ -107,10 +107,11 @@
}
}
- void onWaitForBufferRelease() {
+ void onWaitForBufferRelease(const nsecs_t durationNanos) {
JNIEnv* env = getenv(mVm);
getenv(mVm)->CallVoidMethod(mWaitForBufferReleaseObject,
- gWaitForBufferReleaseCallback.onWaitForBufferRelease);
+ gWaitForBufferReleaseCallback.onWaitForBufferRelease,
+ durationNanos);
DieIfException(env, "Uncaught exception in WaitForBufferReleaseCallback.");
}
@@ -255,7 +256,9 @@
} else {
sp<WaitForBufferReleaseCallbackWrapper> wrapper =
new WaitForBufferReleaseCallbackWrapper{env, waitForBufferReleaseCallback};
- queue->setWaitForBufferReleaseCallback([wrapper]() { wrapper->onWaitForBufferRelease(); });
+ queue->setWaitForBufferReleaseCallback([wrapper](const nsecs_t durationNanos) {
+ wrapper->onWaitForBufferRelease(durationNanos);
+ });
}
}
@@ -305,7 +308,7 @@
jclass waitForBufferReleaseClass =
FindClassOrDie(env, "android/graphics/BLASTBufferQueue$WaitForBufferReleaseCallback");
gWaitForBufferReleaseCallback.onWaitForBufferRelease =
- GetMethodIDOrDie(env, waitForBufferReleaseClass, "onWaitForBufferRelease", "()V");
+ GetMethodIDOrDie(env, waitForBufferReleaseClass, "onWaitForBufferRelease", "(J)V");
return 0;
}
diff --git a/core/tests/coretests/src/android/app/NotificationManagerTest.java b/core/tests/coretests/src/android/app/NotificationManagerTest.java
index a201f1f..4143229 100644
--- a/core/tests/coretests/src/android/app/NotificationManagerTest.java
+++ b/core/tests/coretests/src/android/app/NotificationManagerTest.java
@@ -30,8 +30,10 @@
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
+import android.annotation.Nullable;
import android.content.Context;
import android.content.ContextWrapper;
+import android.content.pm.PackageManager;
import android.content.pm.ParceledListSlice;
import android.os.UserHandle;
import android.platform.test.annotations.EnableFlags;
@@ -441,6 +443,46 @@
.getOrCreateNotificationChannels(any(), any(), anyInt(), anyBoolean());
}
+ @Test
+ @EnableFlags({Flags.FLAG_MODES_API, Flags.FLAG_MODES_UI})
+ public void areAutomaticZenRulesUserManaged_handheld_isTrue() {
+ PackageManager pm = mock(PackageManager.class);
+ when(pm.hasSystemFeature(any())).thenReturn(false);
+ mContext.setPackageManager(pm);
+
+ assertThat(mNotificationManager.areAutomaticZenRulesUserManaged()).isTrue();
+ }
+
+ @Test
+ @EnableFlags({Flags.FLAG_MODES_API, Flags.FLAG_MODES_UI})
+ public void areAutomaticZenRulesUserManaged_auto_isFalse() {
+ PackageManager pm = mock(PackageManager.class);
+ when(pm.hasSystemFeature(eq(PackageManager.FEATURE_AUTOMOTIVE))).thenReturn(true);
+ mContext.setPackageManager(pm);
+
+ assertThat(mNotificationManager.areAutomaticZenRulesUserManaged()).isFalse();
+ }
+
+ @Test
+ @EnableFlags({Flags.FLAG_MODES_API, Flags.FLAG_MODES_UI})
+ public void areAutomaticZenRulesUserManaged_tv_isFalse() {
+ PackageManager pm = mock(PackageManager.class);
+ when(pm.hasSystemFeature(eq(PackageManager.FEATURE_LEANBACK))).thenReturn(true);
+ mContext.setPackageManager(pm);
+
+ assertThat(mNotificationManager.areAutomaticZenRulesUserManaged()).isFalse();
+ }
+
+ @Test
+ @EnableFlags({Flags.FLAG_MODES_API, Flags.FLAG_MODES_UI})
+ public void areAutomaticZenRulesUserManaged_watch_isFalse() {
+ PackageManager pm = mock(PackageManager.class);
+ when(pm.hasSystemFeature(eq(PackageManager.FEATURE_WATCH))).thenReturn(true);
+ mContext.setPackageManager(pm);
+
+ assertThat(mNotificationManager.areAutomaticZenRulesUserManaged()).isFalse();
+ }
+
private Notification exampleNotification() {
return new Notification.Builder(mContext, "channel")
.setSmallIcon(android.R.drawable.star_big_on)
@@ -470,6 +512,7 @@
// Helper context wrapper class where we can control just the return values of getPackageName,
// getOpPackageName, and getUserId (used in getNotificationChannels).
private static class PackageTestableContext extends ContextWrapper {
+ private PackageManager mPm;
private String mPackage;
private String mOpPackage;
private Integer mUserId;
@@ -478,6 +521,10 @@
super(base);
}
+ void setPackageManager(@Nullable PackageManager pm) {
+ mPm = pm;
+ }
+
void setParameters(String packageName, String opPackageName, int userId) {
mPackage = packageName;
mOpPackage = opPackageName;
@@ -485,6 +532,12 @@
}
@Override
+ public PackageManager getPackageManager() {
+ if (mPm != null) return mPm;
+ return super.getPackageManager();
+ }
+
+ @Override
public String getPackageName() {
if (mPackage != null) return mPackage;
return super.getPackageName();
diff --git a/graphics/java/android/graphics/BLASTBufferQueue.java b/graphics/java/android/graphics/BLASTBufferQueue.java
index 1c34e0d..9b9be244 100644
--- a/graphics/java/android/graphics/BLASTBufferQueue.java
+++ b/graphics/java/android/graphics/BLASTBufferQueue.java
@@ -61,8 +61,10 @@
/**
* Indicates that the client is waiting on buffer release
* due to no free buffers being available to render into.
+ * @param durationNanos The length of time in nanoseconds
+ * that the client was blocked on buffer release.
*/
- void onWaitForBufferRelease();
+ void onWaitForBufferRelease(long durationNanos);
}
/** Create a new connection with the surface flinger. */
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleController.java b/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleController.java
index 12dfbd9..30d6790 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleController.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleController.java
@@ -1440,9 +1440,9 @@
*
* @param intent the intent for the bubble.
*/
- public void expandStackAndSelectBubble(Intent intent) {
+ public void expandStackAndSelectBubble(Intent intent, UserHandle user) {
if (!Flags.enableBubbleAnything()) return;
- Bubble b = mBubbleData.getOrCreateBubble(intent); // Removes from overflow
+ Bubble b = mBubbleData.getOrCreateBubble(intent, user); // Removes from overflow
ProtoLog.v(WM_SHELL_BUBBLES, "expandStackAndSelectBubble - intent=%s", intent);
if (b.isInflated()) {
mBubbleData.setSelectedBubbleAndExpandStack(b);
@@ -2649,8 +2649,8 @@
}
@Override
- public void showAppBubble(Intent intent) {
- mMainExecutor.execute(() -> mController.expandStackAndSelectBubble(intent));
+ public void showAppBubble(Intent intent, UserHandle user) {
+ mMainExecutor.execute(() -> mController.expandStackAndSelectBubble(intent, user));
}
@Override
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleData.java b/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleData.java
index dc2025b..76d91ed 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleData.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleData.java
@@ -461,10 +461,8 @@
return bubbleToReturn;
}
- Bubble getOrCreateBubble(Intent intent) {
- UserHandle user = UserHandle.of(mCurrentUserId);
- String bubbleKey = Bubble.getAppBubbleKeyForApp(intent.getPackage(),
- user);
+ Bubble getOrCreateBubble(Intent intent, UserHandle user) {
+ String bubbleKey = Bubble.getAppBubbleKeyForApp(intent.getPackage(), user);
Bubble bubbleToReturn = findAndRemoveBubbleFromOverflow(bubbleKey);
if (bubbleToReturn == null) {
bubbleToReturn = Bubble.createAppBubble(intent, user, null, mMainExecutor, mBgExecutor);
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/IBubbles.aidl b/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/IBubbles.aidl
index 9c2d3543..0a4d79a 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/IBubbles.aidl
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/IBubbles.aidl
@@ -17,8 +17,9 @@
package com.android.wm.shell.bubbles;
import android.content.Intent;
-import android.graphics.Rect;
import android.content.pm.ShortcutInfo;
+import android.graphics.Rect;
+import android.os.UserHandle;
import com.android.wm.shell.bubbles.IBubblesListener;
import com.android.wm.shell.shared.bubbles.BubbleBarLocation;
@@ -52,7 +53,7 @@
oneway void showShortcutBubble(in ShortcutInfo info) = 12;
- oneway void showAppBubble(in Intent intent) = 13;
+ oneway void showAppBubble(in Intent intent, in UserHandle user) = 13;
oneway void showExpandedView() = 14;
}
\ No newline at end of file
diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/bubbles/BubbleDataTest.java b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/bubbles/BubbleDataTest.java
index ce640b5..ffcc344 100644
--- a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/bubbles/BubbleDataTest.java
+++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/bubbles/BubbleDataTest.java
@@ -445,6 +445,15 @@
assertThat(update.updatedBubble.showFlyout()).isFalse();
}
+ @Test
+ public void getOrCreateBubble_withIntent_usesCorrectUser() {
+ Intent intent = new Intent();
+ intent.setPackage(mContext.getPackageName());
+ Bubble b = mBubbleData.getOrCreateBubble(intent, UserHandle.of(/* userId= */ 10));
+
+ assertThat(b.getUser().getIdentifier()).isEqualTo(10);
+ }
+
//
// Overflow
//
@@ -1441,12 +1450,6 @@
assertWithMessage("selectedBubble").that(update.selectedBubble).isEqualTo(bubble);
}
- private void assertSelectionCleared() {
- BubbleData.Update update = mUpdateCaptor.getValue();
- assertWithMessage("selectionChanged").that(update.selectionChanged).isTrue();
- assertWithMessage("selectedBubble").that(update.selectedBubble).isNull();
- }
-
private void assertExpandedChangedTo(boolean expected) {
BubbleData.Update update = mUpdateCaptor.getValue();
assertWithMessage("expandedChanged").that(update.expandedChanged).isTrue();
diff --git a/media/java/android/media/MediaCodecInfo.java b/media/java/android/media/MediaCodecInfo.java
index 302969f..9bb31d0 100644
--- a/media/java/android/media/MediaCodecInfo.java
+++ b/media/java/android/media/MediaCodecInfo.java
@@ -908,13 +908,13 @@
/** @hide */
public String[] validFeatures() {
Feature[] features = getValidFeatures();
- String[] res = new String[features.length];
- for (int i = 0; i < res.length; i++) {
+ ArrayList<String> res = new ArrayList();
+ for (int i = 0; i < features.length; i++) {
if (!features[i].mInternal) {
- res[i] = features[i].mName;
+ res.add(features[i].mName);
}
}
- return res;
+ return res.toArray(new String[0]);
}
private Feature[] getValidFeatures() {
diff --git a/media/java/android/media/tv/TvInputService.java b/media/java/android/media/tv/TvInputService.java
index abfc244..f352a41 100644
--- a/media/java/android/media/tv/TvInputService.java
+++ b/media/java/android/media/tv/TvInputService.java
@@ -161,11 +161,6 @@
new RemoteCallbackList<>();
private TvInputManager mTvInputManager;
- /**
- * @hide
- */
- protected TvInputServiceExtensionManager mTvInputServiceExtensionManager =
- new TvInputServiceExtensionManager();
@Override
public final IBinder onBind(Intent intent) {
@@ -230,12 +225,20 @@
@Override
public IBinder getExtensionInterface(String name) {
- if (tifExtensionStandardization() && name != null) {
- if (TvInputServiceExtensionManager.checkIsStandardizedInterfaces(name)) {
- return mTvInputServiceExtensionManager.getExtensionIBinder(name);
+ IBinder binder = TvInputService.this.getExtensionInterface(name);
+ if (tifExtensionStandardization()) {
+ if (name != null
+ && TvInputServiceExtensionManager.checkIsStandardizedInterfaces(name)) {
+ if (TvInputServiceExtensionManager.checkIsStandardizedIBinder(name,
+ binder)) {
+ return binder;
+ } else {
+ // binder with standardized name is not standardized
+ return null;
+ }
}
}
- return TvInputService.this.getExtensionInterface(name);
+ return binder;
}
@Override
diff --git a/media/java/android/media/tv/TvInputServiceExtensionManager.java b/media/java/android/media/tv/TvInputServiceExtensionManager.java
index d33ac92..02d2616 100644
--- a/media/java/android/media/tv/TvInputServiceExtensionManager.java
+++ b/media/java/android/media/tv/TvInputServiceExtensionManager.java
@@ -16,13 +16,9 @@
package android.media.tv;
-import android.annotation.FlaggedApi;
-import android.annotation.IntDef;
import android.annotation.NonNull;
import android.annotation.Nullable;
-import android.annotation.RequiresPermission;
import android.annotation.StringDef;
-import android.media.tv.flags.Flags;
import android.os.IBinder;
import android.os.RemoteException;
import android.util.Log;
@@ -30,21 +26,17 @@
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.util.ArrayList;
-import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
-import java.util.Map;
import java.util.Set;
/**
* This class provides a list of available standardized TvInputService extension interface names
- * and a container storing IBinder objects that implement these interfaces created by SoC/OEMs.
- * It also provides an API for SoC/OEMs to register implemented IBinder objects.
+ * and checks if IBinder objects created by SoC/OEMs implement these interfaces.
*
* @hide
*/
-@FlaggedApi(Flags.FLAG_TIF_EXTENSION_STANDARDIZATION)
public final class TvInputServiceExtensionManager {
private static final String TAG = "TvInputServiceExtensionManager";
private static final String SCAN_PACKAGE = "android.media.tv.extension.scan.";
@@ -63,33 +55,6 @@
private static final String ANALOG_PACKAGE = "android.media.tv.extension.analog.";
private static final String TUNE_PACKAGE = "android.media.tv.extension.tune.";
- @IntDef(prefix = {"REGISTER_"}, value = {
- REGISTER_SUCCESS,
- REGISTER_FAIL_NAME_NOT_STANDARDIZED,
- REGISTER_FAIL_IMPLEMENTATION_NOT_STANDARDIZED,
- REGISTER_FAIL_REMOTE_EXCEPTION
- })
- @Retention(RetentionPolicy.SOURCE)
- public @interface RegisterResult {}
-
- /**
- * Registering binder returns success when it abides standardized interface structure
- */
- public static final int REGISTER_SUCCESS = 0;
- /**
- * Registering binder returns failure when the extension name is not in the standardization
- * list
- */
- public static final int REGISTER_FAIL_NAME_NOT_STANDARDIZED = 1;
- /**
- * Registering binder returns failure when the IBinder does not implement standardized interface
- */
- public static final int REGISTER_FAIL_IMPLEMENTATION_NOT_STANDARDIZED = 2;
- /**
- * Registering binder returns failure when remote server is not available
- */
- public static final int REGISTER_FAIL_REMOTE_EXCEPTION = 3;
-
@StringDef({
ISCAN_INTERFACE,
ISCAN_SESSION,
@@ -673,12 +638,6 @@
IMUX_TUNE
));
- // Store the mapping between interface names and IBinder
- private Map<String, IBinder> mExtensionInterfaceIBinderMapping = new HashMap<>();
-
- TvInputServiceExtensionManager() {
- }
-
/**
* Function to return available extension interface names
*/
@@ -694,43 +653,18 @@
}
/**
- * Registers IBinder objects that implement standardized AIDL interfaces.
- * <p>This function should be used by SoCs/OEMs
- *
- * @param extensionName Extension Interface Name
- * @param binder IBinder object to be registered
- * @return {@link #REGISTER_SUCCESS} on success of registering IBinder object
- * {@link #REGISTER_FAIL_NAME_NOT_STANDARDIZED} on failure due to registering extension
- * with non-standardized name
- * {@link #REGISTER_FAIL_IMPLEMENTATION_NOT_STANDARDIZED} on failure due to IBinder not
- * implementing standardized AIDL interface
- * {@link #REGISTER_FAIL_REMOTE_EXCEPTION} on failure due to remote exception
+ * Function check if the IBinder object implements standardized interface
*/
- @RequiresPermission(android.Manifest.permission.TV_INPUT_HARDWARE)
- @RegisterResult
- public int registerExtensionIBinder(@StandardizedExtensionName @NonNull String extensionName,
- @NonNull IBinder binder) {
- if (!checkIsStandardizedInterfaces(extensionName)) {
- return REGISTER_FAIL_NAME_NOT_STANDARDIZED;
- }
- try {
- if (binder.getInterfaceDescriptor().equals(extensionName)) {
- mExtensionInterfaceIBinderMapping.put(extensionName, binder);
- return REGISTER_SUCCESS;
- } else {
- return REGISTER_FAIL_IMPLEMENTATION_NOT_STANDARDIZED;
+ public static boolean checkIsStandardizedIBinder(@NonNull String extensionName,
+ @Nullable IBinder binder) {
+ if (binder != null) {
+ try {
+ return binder.getInterfaceDescriptor().equals(extensionName);
+ } catch (RemoteException e) {
+ Log.e(TAG, "Fetching IBinder object failure due to " + e);
}
- } catch (RemoteException e) {
- Log.e(TAG, "Fetching IBinder object failure due to " + e);
- return REGISTER_FAIL_REMOTE_EXCEPTION;
}
- }
-
- /**
- * Function to get corresponding IBinder object
- */
- @Nullable IBinder getExtensionIBinder(@NonNull String extensionName) {
- return mExtensionInterfaceIBinderMapping.get(extensionName);
+ return false;
}
}
diff --git a/packages/SettingsProvider/src/android/provider/settings/backup/SecureSettings.java b/packages/SettingsProvider/src/android/provider/settings/backup/SecureSettings.java
index d367748..640829e 100644
--- a/packages/SettingsProvider/src/android/provider/settings/backup/SecureSettings.java
+++ b/packages/SettingsProvider/src/android/provider/settings/backup/SecureSettings.java
@@ -204,7 +204,6 @@
Settings.Secure.AWARE_TAP_PAUSE_TOUCH_COUNT,
Settings.Secure.PEOPLE_STRIP,
Settings.Secure.MEDIA_CONTROLS_RESUME,
- Settings.Secure.MEDIA_CONTROLS_RECOMMENDATION,
Settings.Secure.MEDIA_CONTROLS_LOCK_SCREEN,
Settings.Secure.ACCESSIBILITY_MAGNIFICATION_MODE,
Settings.Secure.ACCESSIBILITY_BUTTON_TARGETS,
diff --git a/packages/SettingsProvider/src/android/provider/settings/validators/SecureSettingsValidators.java b/packages/SettingsProvider/src/android/provider/settings/validators/SecureSettingsValidators.java
index 242bdce..9fd0cc8 100644
--- a/packages/SettingsProvider/src/android/provider/settings/validators/SecureSettingsValidators.java
+++ b/packages/SettingsProvider/src/android/provider/settings/validators/SecureSettingsValidators.java
@@ -312,7 +312,6 @@
VALIDATORS.put(Secure.TAP_GESTURE, BOOLEAN_VALIDATOR);
VALIDATORS.put(Secure.PEOPLE_STRIP, BOOLEAN_VALIDATOR);
VALIDATORS.put(Secure.MEDIA_CONTROLS_RESUME, BOOLEAN_VALIDATOR);
- VALIDATORS.put(Secure.MEDIA_CONTROLS_RECOMMENDATION, BOOLEAN_VALIDATOR);
VALIDATORS.put(Secure.MEDIA_CONTROLS_LOCK_SCREEN, BOOLEAN_VALIDATOR);
VALIDATORS.put(Secure.ACCESSIBILITY_MAGNIFICATION_MODE,
new InclusiveIntegerRangeValidator(
diff --git a/packages/SystemUI/aconfig/systemui.aconfig b/packages/SystemUI/aconfig/systemui.aconfig
index 1a7ae72..f753316 100644
--- a/packages/SystemUI/aconfig/systemui.aconfig
+++ b/packages/SystemUI/aconfig/systemui.aconfig
@@ -1940,3 +1940,10 @@
description: "Force promoted notifications to always be expanded"
bug: "380901479"
}
+
+flag {
+ name: "aod_ui_rich_ongoing"
+ namespace: "systemui"
+ description: "Show a rich ongoing notification on the always-on display (depends on ui_rich_ongoing)"
+ bug: "369151941"
+}
\ No newline at end of file
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/communal/CommunalDreamStartableTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/communal/CommunalDreamStartableTest.kt
index e531e65..00d5afe 100644
--- a/packages/SystemUI/multivalentTests/src/com/android/systemui/communal/CommunalDreamStartableTest.kt
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/communal/CommunalDreamStartableTest.kt
@@ -16,14 +16,17 @@
package com.android.systemui.communal
+import android.platform.test.annotations.DisableFlags
import android.platform.test.annotations.EnableFlags
+import android.platform.test.flag.junit.FlagsParameterization
import android.service.dream.dreamManager
-import androidx.test.ext.junit.runners.AndroidJUnit4
import androidx.test.filters.SmallTest
import com.android.systemui.Flags
+import com.android.systemui.Flags.FLAG_GLANCEABLE_HUB_V2
import com.android.systemui.SysuiTestCase
import com.android.systemui.communal.domain.interactor.communalSceneInteractor
import com.android.systemui.communal.domain.interactor.communalSettingsInteractor
+import com.android.systemui.communal.domain.interactor.setCommunalV2Enabled
import com.android.systemui.flags.Flags.COMMUNAL_SERVICE_ENABLED
import com.android.systemui.flags.fakeFeatureFlagsClassic
import com.android.systemui.keyguard.data.repository.fakeKeyguardRepository
@@ -48,12 +51,14 @@
import org.junit.runner.RunWith
import org.mockito.Mockito.never
import org.mockito.Mockito.verify
+import platform.test.runner.parameterized.ParameterizedAndroidJunit4
+import platform.test.runner.parameterized.Parameters
@OptIn(ExperimentalCoroutinesApi::class)
@SmallTest
@EnableFlags(Flags.FLAG_COMMUNAL_HUB)
-@RunWith(AndroidJUnit4::class)
-class CommunalDreamStartableTest : SysuiTestCase() {
+@RunWith(ParameterizedAndroidJunit4::class)
+class CommunalDreamStartableTest(flags: FlagsParameterization) : SysuiTestCase() {
private val kosmos = testKosmos()
private val testScope = kosmos.testScope
@@ -63,26 +68,50 @@
private val keyguardRepository by lazy { kosmos.fakeKeyguardRepository }
private val powerRepository by lazy { kosmos.fakePowerRepository }
+ init {
+ mSetFlagsRule.setFlagsParameterization(flags)
+ }
+
@Before
fun setUp() {
kosmos.fakeFeatureFlagsClassic.set(COMMUNAL_SERVICE_ENABLED, true)
underTest =
CommunalDreamStartable(
- powerInteractor = kosmos.powerInteractor,
- communalSettingsInteractor = kosmos.communalSettingsInteractor,
- keyguardInteractor = kosmos.keyguardInteractor,
- keyguardTransitionInteractor = kosmos.keyguardTransitionInteractor,
- dreamManager = dreamManager,
- communalSceneInteractor = kosmos.communalSceneInteractor,
- bgScope = kosmos.applicationCoroutineScope,
- )
- .apply { start() }
+ powerInteractor = kosmos.powerInteractor,
+ communalSettingsInteractor = kosmos.communalSettingsInteractor,
+ keyguardInteractor = kosmos.keyguardInteractor,
+ keyguardTransitionInteractor = kosmos.keyguardTransitionInteractor,
+ dreamManager = dreamManager,
+ communalSceneInteractor = kosmos.communalSceneInteractor,
+ bgScope = kosmos.applicationCoroutineScope,
+ )
}
+ @EnableFlags(FLAG_GLANCEABLE_HUB_V2)
+ @Test
+ fun dreamNotStartedWhenTransitioningToHub() =
+ testScope.runTest {
+ // Enable v2 flag and recreate + rerun start method.
+ kosmos.setCommunalV2Enabled(true)
+ underTest.start()
+
+ keyguardRepository.setKeyguardShowing(true)
+ keyguardRepository.setDreaming(false)
+ powerRepository.setScreenPowerState(ScreenPowerState.SCREEN_ON)
+ whenever(dreamManager.canStartDreaming(/* isScreenOn= */ true)).thenReturn(true)
+ runCurrent()
+
+ transition(from = KeyguardState.DREAMING, to = KeyguardState.GLANCEABLE_HUB)
+
+ verify(dreamManager, never()).startDream()
+ }
+
+ @DisableFlags(FLAG_GLANCEABLE_HUB_V2)
@Test
fun startDreamWhenTransitioningToHub() =
testScope.runTest {
+ underTest.start()
keyguardRepository.setKeyguardShowing(true)
keyguardRepository.setDreaming(false)
powerRepository.setScreenPowerState(ScreenPowerState.SCREEN_ON)
@@ -100,6 +129,7 @@
@EnableFlags(Flags.FLAG_RESTART_DREAM_ON_UNOCCLUDE)
fun restartDreamingWhenTransitioningFromDreamingToOccludedToDreaming() =
testScope.runTest {
+ underTest.start()
keyguardRepository.setDreaming(false)
powerRepository.setScreenPowerState(ScreenPowerState.SCREEN_ON)
whenever(dreamManager.canStartDreaming(/* isScreenOn= */ true)).thenReturn(true)
@@ -122,9 +152,11 @@
verify(dreamManager).startDream()
}
+ @DisableFlags(FLAG_GLANCEABLE_HUB_V2)
@Test
fun shouldNotStartDreamWhenIneligibleToDream() =
testScope.runTest {
+ underTest.start()
keyguardRepository.setDreaming(false)
powerRepository.setScreenPowerState(ScreenPowerState.SCREEN_ON)
// Not eligible to dream
@@ -134,9 +166,11 @@
verify(dreamManager, never()).startDream()
}
+ @DisableFlags(FLAG_GLANCEABLE_HUB_V2)
@Test
fun shouldNotStartDreamIfAlreadyDreaming() =
testScope.runTest {
+ underTest.start()
keyguardRepository.setDreaming(true)
powerRepository.setScreenPowerState(ScreenPowerState.SCREEN_ON)
whenever(dreamManager.canStartDreaming(/* isScreenOn= */ true)).thenReturn(true)
@@ -145,9 +179,11 @@
verify(dreamManager, never()).startDream()
}
+ @DisableFlags(FLAG_GLANCEABLE_HUB_V2)
@Test
fun shouldNotStartDreamForInvalidTransition() =
testScope.runTest {
+ underTest.start()
keyguardRepository.setDreaming(true)
powerRepository.setScreenPowerState(ScreenPowerState.SCREEN_ON)
whenever(dreamManager.canStartDreaming(/* isScreenOn= */ true)).thenReturn(true)
@@ -160,9 +196,11 @@
}
}
+ @DisableFlags(FLAG_GLANCEABLE_HUB_V2)
@Test
fun shouldNotStartDreamWhenLaunchingWidget() =
testScope.runTest {
+ underTest.start()
keyguardRepository.setKeyguardShowing(true)
keyguardRepository.setDreaming(false)
powerRepository.setScreenPowerState(ScreenPowerState.SCREEN_ON)
@@ -175,9 +213,11 @@
verify(dreamManager, never()).startDream()
}
+ @DisableFlags(FLAG_GLANCEABLE_HUB_V2)
@Test
fun shouldNotStartDreamWhenOccluded() =
testScope.runTest {
+ underTest.start()
keyguardRepository.setKeyguardShowing(true)
keyguardRepository.setDreaming(false)
powerRepository.setScreenPowerState(ScreenPowerState.SCREEN_ON)
@@ -194,8 +234,16 @@
kosmos.fakeKeyguardTransitionRepository.sendTransitionSteps(
from = from,
to = to,
- testScope = this
+ testScope = this,
)
runCurrent()
}
+
+ companion object {
+ @JvmStatic
+ @Parameters(name = "{0}")
+ fun getParams(): List<FlagsParameterization> {
+ return FlagsParameterization.allCombinationsOf(FLAG_GLANCEABLE_HUB_V2)
+ }
+ }
}
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/dreams/DreamOverlayServiceTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/dreams/DreamOverlayServiceTest.kt
index 5921e94..0df584f 100644
--- a/packages/SystemUI/multivalentTests/src/com/android/systemui/dreams/DreamOverlayServiceTest.kt
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/dreams/DreamOverlayServiceTest.kt
@@ -58,6 +58,7 @@
import com.android.systemui.communal.domain.interactor.communalSettingsInteractor
import com.android.systemui.communal.domain.interactor.setCommunalAvailable
import com.android.systemui.communal.domain.interactor.setCommunalV2ConfigEnabled
+import com.android.systemui.communal.domain.interactor.setCommunalV2Enabled
import com.android.systemui.communal.shared.log.CommunalUiEvent
import com.android.systemui.communal.shared.model.CommunalScenes
import com.android.systemui.complication.ComplicationHostViewController
@@ -747,7 +748,7 @@
@Test
@EnableFlags(Flags.FLAG_DREAM_WAKE_REDIRECT, FLAG_COMMUNAL_HUB)
- @DisableFlags(FLAG_SCENE_CONTAINER)
+ @DisableFlags(FLAG_SCENE_CONTAINER, FLAG_GLANCEABLE_HUB_V2)
@kotlin.Throws(RemoteException::class)
fun testTransitionToGlanceableHub() =
testScope.runTest {
@@ -774,6 +775,7 @@
@Test
@EnableFlags(Flags.FLAG_DREAM_WAKE_REDIRECT, FLAG_SCENE_CONTAINER, FLAG_COMMUNAL_HUB)
+ @DisableFlags(FLAG_GLANCEABLE_HUB_V2)
@kotlin.Throws(RemoteException::class)
fun testTransitionToGlanceableHub_sceneContainer() =
testScope.runTest {
@@ -802,7 +804,29 @@
}
@Test
+ @EnableFlags(Flags.FLAG_DREAM_WAKE_REDIRECT, FLAG_COMMUNAL_HUB, FLAG_GLANCEABLE_HUB_V2)
+ @Throws(RemoteException::class)
+ fun testRedirect_v2Enabled_notTriggered() =
+ testScope.runTest {
+ kosmos.setCommunalV2Enabled(true)
+ // Inform the overlay service of dream starting. Do not show dream complications.
+ client.startDream(
+ mWindowParams,
+ mDreamOverlayCallback,
+ DREAM_COMPONENT,
+ false /*isPreview*/,
+ false, /*shouldShowComplication*/
+ )
+ // Set communal available, verify that onRedirectWake is never called.
+ kosmos.setCommunalAvailable(true)
+ mMainExecutor.runAllReady()
+ runCurrent()
+ verify(mDreamOverlayCallback, never()).onRedirectWake(any())
+ }
+
+ @Test
@EnableFlags(Flags.FLAG_DREAM_WAKE_REDIRECT, FLAG_COMMUNAL_HUB)
+ @DisableFlags(FLAG_GLANCEABLE_HUB_V2)
@Throws(RemoteException::class)
fun testRedirectExit() =
testScope.runTest {
@@ -1347,7 +1371,11 @@
@JvmStatic
@Parameters(name = "{0}")
fun getParams(): List<FlagsParameterization> {
- return FlagsParameterization.allCombinationsOf(FLAG_COMMUNAL_HUB).andSceneContainer()
+ return FlagsParameterization.allCombinationsOf(
+ FLAG_COMMUNAL_HUB,
+ FLAG_GLANCEABLE_HUB_V2,
+ )
+ .andSceneContainer()
}
}
}
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/domain/interactor/KeyguardQuickAffordanceInteractorTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/domain/interactor/KeyguardQuickAffordanceInteractorTest.kt
index fe9da0d..88c8b1f 100644
--- a/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/domain/interactor/KeyguardQuickAffordanceInteractorTest.kt
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/domain/interactor/KeyguardQuickAffordanceInteractorTest.kt
@@ -19,6 +19,7 @@
import android.app.admin.DevicePolicyManager
import android.os.UserHandle
+import android.view.accessibility.AccessibilityManager
import androidx.test.ext.junit.runners.AndroidJUnit4
import androidx.test.filters.SmallTest
import com.android.internal.widget.LockPatternUtils
@@ -96,6 +97,7 @@
@Mock private lateinit var shadeInteractor: ShadeInteractor
@Mock private lateinit var logger: KeyguardQuickAffordancesLogger
@Mock private lateinit var metricsLogger: KeyguardQuickAffordancesMetricsLogger
+ @Mock private lateinit var accessibilityManager: AccessibilityManager
private lateinit var underTest: KeyguardQuickAffordanceInteractor
@@ -199,11 +201,13 @@
backgroundDispatcher = kosmos.testDispatcher,
appContext = context,
communalSettingsInteractor = kosmos.communalSettingsInteractor,
+ accessibilityManager = accessibilityManager,
sceneInteractor = { kosmos.sceneInteractor },
)
kosmos.keyguardQuickAffordanceInteractor = underTest
whenever(shadeInteractor.anyExpansion).thenReturn(MutableStateFlow(0f))
+ whenever(accessibilityManager.isEnabled()).thenReturn(false)
}
@Test
@@ -672,6 +676,22 @@
}
@Test
+ fun useLongPress_withA11yEnabled_isFalse() =
+ testScope.runTest {
+ whenever(accessibilityManager.isEnabled()).thenReturn(true)
+ val useLongPress by collectLastValue(underTest.useLongPress())
+ assertThat(useLongPress).isFalse()
+ }
+
+ @Test
+ fun useLongPress_withA11yDisabled_isFalse() =
+ testScope.runTest {
+ whenever(accessibilityManager.isEnabled()).thenReturn(false)
+ val useLongPress by collectLastValue(underTest.useLongPress())
+ assertThat(useLongPress).isTrue()
+ }
+
+ @Test
fun useLongPress_whenDocked_isFalse() =
testScope.runTest {
dockManager.setIsDocked(true)
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/chips/call/ui/viewmodel/CallChipViewModelTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/chips/call/ui/viewmodel/CallChipViewModelTest.kt
index b0af8b1..75262a4 100644
--- a/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/chips/call/ui/viewmodel/CallChipViewModelTest.kt
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/chips/call/ui/viewmodel/CallChipViewModelTest.kt
@@ -23,6 +23,7 @@
import androidx.test.ext.junit.runners.AndroidJUnit4
import androidx.test.filters.SmallTest
import com.android.systemui.SysuiTestCase
+import com.android.systemui.animation.Expandable
import com.android.systemui.common.shared.model.Icon
import com.android.systemui.coroutines.collectLastValue
import com.android.systemui.kosmos.Kosmos
@@ -35,7 +36,14 @@
import com.android.systemui.statusbar.chips.ui.model.OngoingActivityChipModel
import com.android.systemui.statusbar.chips.ui.view.ChipBackgroundContainer
import com.android.systemui.statusbar.core.StatusBarConnectedDisplays
+import com.android.systemui.statusbar.core.StatusBarRootModernization
+import com.android.systemui.statusbar.notification.data.model.activeNotificationModel
+import com.android.systemui.statusbar.notification.data.repository.ActiveNotificationListRepository
+import com.android.systemui.statusbar.notification.data.repository.ActiveNotificationsStore
+import com.android.systemui.statusbar.notification.data.repository.activeNotificationListRepository
import com.android.systemui.statusbar.notification.promoted.shared.model.PromotedNotificationContentModel
+import com.android.systemui.statusbar.notification.shared.CallType
+import com.android.systemui.statusbar.phone.ongoingcall.StatusBarChipsModernization
import com.android.systemui.statusbar.phone.ongoingcall.data.repository.ongoingCallRepository
import com.android.systemui.statusbar.phone.ongoingcall.shared.model.OngoingCallModel
import com.android.systemui.statusbar.phone.ongoingcall.shared.model.inCallModel
@@ -44,6 +52,7 @@
import kotlin.test.Test
import kotlinx.coroutines.test.runTest
import org.junit.runner.RunWith
+import org.mockito.kotlin.any
import org.mockito.kotlin.mock
import org.mockito.kotlin.verify
import org.mockito.kotlin.whenever
@@ -52,6 +61,7 @@
@RunWith(AndroidJUnit4::class)
class CallChipViewModelTest : SysuiTestCase() {
private val kosmos = Kosmos()
+ private val notificationListRepository = kosmos.activeNotificationListRepository
private val testScope = kosmos.testScope
private val repo = kosmos.ongoingCallRepository
@@ -65,6 +75,8 @@
)
.thenReturn(chipBackgroundView)
}
+ private val mockExpandable: Expandable =
+ mock<Expandable>().apply { whenever(dialogTransitionController(any())).thenReturn(mock()) }
private val underTest by lazy { kosmos.callChipViewModel }
@@ -337,6 +349,7 @@
}
@Test
+ @DisableFlags(StatusBarChipsModernization.FLAG_NAME)
fun chip_inCall_nullIntent_nullClickListener() =
testScope.runTest {
val latest by collectLastValue(underTest.chip)
@@ -347,6 +360,7 @@
}
@Test
+ @DisableFlags(StatusBarChipsModernization.FLAG_NAME)
fun chip_inCall_positiveStartTime_validIntent_clickListenerLaunchesIntent() =
testScope.runTest {
val latest by collectLastValue(underTest.chip)
@@ -364,6 +378,7 @@
}
@Test
+ @DisableFlags(StatusBarChipsModernization.FLAG_NAME)
fun chip_inCall_zeroStartTime_validIntent_clickListenerLaunchesIntent() =
testScope.runTest {
val latest by collectLastValue(underTest.chip)
@@ -381,6 +396,72 @@
verify(kosmos.activityStarter).postStartActivityDismissingKeyguard(pendingIntent, null)
}
+ @Test
+ @EnableFlags(StatusBarRootModernization.FLAG_NAME, StatusBarChipsModernization.FLAG_NAME)
+ fun chip_inCall_nullIntent_noneClickBehavior() =
+ testScope.runTest {
+ val latest by collectLastValue(underTest.chip)
+
+ postOngoingCallNotification(
+ repository = notificationListRepository,
+ startTimeMs = 1000L,
+ intent = null,
+ )
+
+ assertThat((latest as OngoingActivityChipModel.Shown).clickBehavior)
+ .isInstanceOf(OngoingActivityChipModel.ClickBehavior.None::class.java)
+ }
+
+ @Test
+ @EnableFlags(StatusBarRootModernization.FLAG_NAME, StatusBarChipsModernization.FLAG_NAME)
+ fun chip_inCall_positiveStartTime_validIntent_clickBehaviorLaunchesIntent() =
+ testScope.runTest {
+ val latest by collectLastValue(underTest.chip)
+
+ val pendingIntent = mock<PendingIntent>()
+ postOngoingCallNotification(
+ repository = notificationListRepository,
+ startTimeMs = 1000L,
+ intent = pendingIntent,
+ )
+
+ val clickBehavior = (latest as OngoingActivityChipModel.Shown).clickBehavior
+ assertThat(clickBehavior)
+ .isInstanceOf(OngoingActivityChipModel.ClickBehavior.ExpandAction::class.java)
+ (clickBehavior as OngoingActivityChipModel.ClickBehavior.ExpandAction).onClick(
+ mockExpandable
+ )
+
+ // Ensure that the SysUI didn't modify the notification's intent by verifying it
+ // directly matches the `PendingIntent` set -- see b/212467440.
+ verify(kosmos.activityStarter).postStartActivityDismissingKeyguard(pendingIntent, null)
+ }
+
+ @Test
+ @EnableFlags(StatusBarRootModernization.FLAG_NAME, StatusBarChipsModernization.FLAG_NAME)
+ fun chip_inCall_zeroStartTime_validIntent_clickBehaviorLaunchesIntent() =
+ testScope.runTest {
+ val latest by collectLastValue(underTest.chip)
+
+ val pendingIntent = mock<PendingIntent>()
+ postOngoingCallNotification(
+ repository = notificationListRepository,
+ startTimeMs = 0L,
+ intent = pendingIntent,
+ )
+
+ val clickBehavior = (latest as OngoingActivityChipModel.Shown).clickBehavior
+ assertThat(clickBehavior)
+ .isInstanceOf(OngoingActivityChipModel.ClickBehavior.ExpandAction::class.java)
+ (clickBehavior as OngoingActivityChipModel.ClickBehavior.ExpandAction).onClick(
+ mockExpandable
+ )
+
+ // Ensure that the SysUI didn't modify the notification's intent by verifying it
+ // directly matches the `PendingIntent` set -- see b/212467440.
+ verify(kosmos.activityStarter).postStartActivityDismissingKeyguard(pendingIntent, null)
+ }
+
companion object {
fun createStatusBarIconViewOrNull(): StatusBarIconView? =
if (StatusBarConnectedDisplays.isEnabled) {
@@ -389,6 +470,27 @@
mock<StatusBarIconView>()
}
+ fun postOngoingCallNotification(
+ repository: ActiveNotificationListRepository,
+ startTimeMs: Long,
+ intent: PendingIntent?,
+ ) {
+ repository.activeNotifications.value =
+ ActiveNotificationsStore.Builder()
+ .apply {
+ addIndividualNotif(
+ activeNotificationModel(
+ key = "notif1",
+ whenTime = startTimeMs,
+ callType = CallType.Ongoing,
+ statusBarChipIcon = null,
+ contentIntent = intent,
+ )
+ )
+ }
+ .build()
+ }
+
private val PROMOTED_CONTENT_WITH_COLOR =
PromotedNotificationContentModel.Builder("notif")
.apply {
diff --git a/packages/SystemUI/src/com/android/systemui/common/ui/view/ViewExt.kt b/packages/SystemUI/src/com/android/systemui/common/ui/view/ViewExt.kt
index f7ea25c..b248043 100644
--- a/packages/SystemUI/src/com/android/systemui/common/ui/view/ViewExt.kt
+++ b/packages/SystemUI/src/com/android/systemui/common/ui/view/ViewExt.kt
@@ -68,3 +68,11 @@
setOnTouchListener(listener)
return DisposableHandle { setOnTouchListener(null) }
}
+
+/** A null listener should also set the longClickable property to false */
+fun View.updateLongClickListener(listener: View.OnLongClickListener?) {
+ setOnLongClickListener(listener)
+ if (listener == null) {
+ setLongClickable(false)
+ }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/communal/CommunalDreamStartable.kt b/packages/SystemUI/src/com/android/systemui/communal/CommunalDreamStartable.kt
index 1bd541e..6dc7c97 100644
--- a/packages/SystemUI/src/com/android/systemui/communal/CommunalDreamStartable.kt
+++ b/packages/SystemUI/src/com/android/systemui/communal/CommunalDreamStartable.kt
@@ -91,13 +91,19 @@
.launchIn(bgScope)
}
- // Restart the dream underneath the hub in order to support the ability to swipe
- // away the hub to enter the dream.
- startDream
- .sampleFilter(powerInteractor.isAwake) { isAwake ->
- !glanceableHubAllowKeyguardWhenDreaming() && dreamManager.canStartDreaming(isAwake)
- }
- .onEach { dreamManager.startDream() }
- .launchIn(bgScope)
+ // With hub v2, we no longer need to keep the dream running underneath the hub as there is
+ // no more swipe between the hub and dream. We can just start the dream on-demand when the
+ // user presses the dream coin.
+ if (!communalSettingsInteractor.isV2FlagEnabled()) {
+ // Restart the dream underneath the hub in order to support the ability to swipe away
+ // the hub to enter the dream.
+ startDream
+ .sampleFilter(powerInteractor.isAwake) { isAwake ->
+ !glanceableHubAllowKeyguardWhenDreaming() &&
+ dreamManager.canStartDreaming(isAwake)
+ }
+ .onEach { dreamManager.startDream() }
+ .launchIn(bgScope)
+ }
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/dreams/DreamOverlayService.java b/packages/SystemUI/src/com/android/systemui/dreams/DreamOverlayService.java
index 0b2b368..a56a63c 100644
--- a/packages/SystemUI/src/com/android/systemui/dreams/DreamOverlayService.java
+++ b/packages/SystemUI/src/com/android/systemui/dreams/DreamOverlayService.java
@@ -562,6 +562,13 @@
return;
}
+ if (mCommunalSettingsInteractor.isV2FlagEnabled()) {
+ // Dream wake redirect is not needed in V2 as we do not need to keep the dream awake
+ // underneath the hub anymore as there is no more swipe between the dream and hub. SysUI
+ // will automatically transition to the hub when the dream wakes.
+ return;
+ }
+
redirectWake(mCommunalAvailable && !glanceableHubAllowKeyguardWhenDreaming());
}
diff --git a/packages/SystemUI/src/com/android/systemui/flags/FlagDependencies.kt b/packages/SystemUI/src/com/android/systemui/flags/FlagDependencies.kt
index 3911c19..e588077 100644
--- a/packages/SystemUI/src/com/android/systemui/flags/FlagDependencies.kt
+++ b/packages/SystemUI/src/com/android/systemui/flags/FlagDependencies.kt
@@ -31,6 +31,7 @@
import com.android.systemui.statusbar.notification.emptyshade.shared.ModesEmptyShadeFix
import com.android.systemui.statusbar.notification.interruption.VisualInterruptionRefactor
import com.android.systemui.statusbar.notification.promoted.PromotedNotificationUi
+import com.android.systemui.statusbar.notification.promoted.PromotedNotificationUiAod
import com.android.systemui.statusbar.notification.promoted.PromotedNotificationUiForceExpanded
import com.android.systemui.statusbar.notification.shared.NotificationAvalancheSuppression
import com.android.systemui.statusbar.notification.shared.NotificationMinimalism
@@ -55,6 +56,9 @@
ModesEmptyShadeFix.token dependsOn modesUi
PromotedNotificationUiForceExpanded.token dependsOn PromotedNotificationUi.token
+
+ PromotedNotificationUiAod.token dependsOn PromotedNotificationUi.token
+
// SceneContainer dependencies
SceneContainerFlag.getFlagDependencies().forEach { (alpha, beta) -> alpha dependsOn beta }
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/KeyguardQuickAffordanceInteractor.kt b/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/KeyguardQuickAffordanceInteractor.kt
index 7d8badd..b866fca 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/KeyguardQuickAffordanceInteractor.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/KeyguardQuickAffordanceInteractor.kt
@@ -22,6 +22,7 @@
import android.content.Context
import android.content.Intent
import android.util.Log
+import android.view.accessibility.AccessibilityManager
import com.android.app.tracing.coroutines.withContextTraced as withContext
import com.android.compose.animation.scene.ObservableTransitionState
import com.android.internal.widget.LockPatternUtils
@@ -92,6 +93,7 @@
private val dockManager: DockManager,
private val biometricSettingsRepository: BiometricSettingsRepository,
private val communalSettingsInteractor: CommunalSettingsInteractor,
+ private val accessibilityManager: AccessibilityManager,
@Background private val backgroundDispatcher: CoroutineDispatcher,
@ShadeDisplayAware private val appContext: Context,
private val sceneInteractor: Lazy<SceneInteractor>,
@@ -115,7 +117,10 @@
*
* If `false`, the UI goes back to using single taps.
*/
- fun useLongPress(): Flow<Boolean> = dockManager.retrieveIsDocked().map { !it }
+ fun useLongPress(): Flow<Boolean> =
+ dockManager.retrieveIsDocked().map { isDocked ->
+ !isDocked && !accessibilityManager.isEnabled()
+ }
/** Returns an observable for the quick affordance at the given position. */
suspend fun quickAffordance(
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/ui/binder/KeyguardQuickAffordanceViewBinder.kt b/packages/SystemUI/src/com/android/systemui/keyguard/ui/binder/KeyguardQuickAffordanceViewBinder.kt
index 8a2e3dd..f396cf9 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/ui/binder/KeyguardQuickAffordanceViewBinder.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/ui/binder/KeyguardQuickAffordanceViewBinder.kt
@@ -39,6 +39,7 @@
import com.android.systemui.animation.view.LaunchableImageView
import com.android.systemui.common.shared.model.Icon
import com.android.systemui.common.ui.binder.IconViewBinder
+import com.android.systemui.common.ui.view.updateLongClickListener
import com.android.systemui.dagger.SysUISingleton
import com.android.systemui.keyguard.ui.viewmodel.KeyguardQuickAffordanceHapticViewModel
import com.android.systemui.keyguard.ui.viewmodel.KeyguardQuickAffordanceViewModel
@@ -275,6 +276,7 @@
)
} else {
view.setOnClickListener(OnClickListener(viewModel, checkNotNull(falsingManager)))
+ view.updateLongClickListener(null)
}
} else {
view.onLongClickListener = null
diff --git a/packages/SystemUI/src/com/android/systemui/media/controls/domain/pipeline/LegacyMediaDataManagerImpl.kt b/packages/SystemUI/src/com/android/systemui/media/controls/domain/pipeline/LegacyMediaDataManagerImpl.kt
index 2191f37..f1f299a 100644
--- a/packages/SystemUI/src/com/android/systemui/media/controls/domain/pipeline/LegacyMediaDataManagerImpl.kt
+++ b/packages/SystemUI/src/com/android/systemui/media/controls/domain/pipeline/LegacyMediaDataManagerImpl.kt
@@ -45,16 +45,15 @@
import android.media.session.MediaSession
import android.media.session.PlaybackState
import android.net.Uri
-import android.os.Parcelable
import android.os.Process
import android.os.UserHandle
-import android.provider.Settings
import android.service.notification.StatusBarNotification
import android.support.v4.media.MediaMetadataCompat
import android.text.TextUtils
import android.util.Log
import android.util.Pair as APair
import androidx.media.utils.MediaConstants
+import com.android.app.tracing.coroutines.launchTraced as launch
import com.android.app.tracing.traceSection
import com.android.internal.annotations.Keep
import com.android.internal.logging.InstanceId
@@ -86,11 +85,9 @@
import com.android.systemui.media.controls.util.MediaFlags
import com.android.systemui.media.controls.util.MediaUiEventLogger
import com.android.systemui.media.controls.util.SmallHash
-import com.android.systemui.plugins.BcSmartspaceDataPlugin
import com.android.systemui.res.R
import com.android.systemui.statusbar.NotificationMediaManager.isPlayingState
import com.android.systemui.statusbar.notification.row.HybridGroupManager
-import com.android.systemui.tuner.TunerService
import com.android.systemui.util.Assert
import com.android.systemui.util.Utils
import com.android.systemui.util.concurrency.DelayableExecutor
@@ -103,7 +100,6 @@
import javax.inject.Inject
import kotlinx.coroutines.CoroutineDispatcher
import kotlinx.coroutines.CoroutineScope
-import com.android.app.tracing.coroutines.launchTraced as launch
import kotlinx.coroutines.withContext
// URI fields to try loading album art from
@@ -152,22 +148,6 @@
expiryTimeMs = 0,
)
-const val MEDIA_TITLE_ERROR_MESSAGE = "Invalid media data: title is null or blank."
-
-/**
- * Allow recommendations from smartspace to show in media controls. Requires
- * [Utils.useQsMediaPlayer] to be enabled. On by default, but can be disabled by setting to 0
- */
-private fun allowMediaRecommendations(context: Context): Boolean {
- val flag =
- Settings.Secure.getInt(
- context.contentResolver,
- Settings.Secure.MEDIA_CONTROLS_RECOMMENDATION,
- 1,
- )
- return Utils.useQsMediaPlayer(context) && flag > 0
-}
-
/** A class that facilitates management and loading of Media Data, ready for binding. */
@SysUISingleton
class LegacyMediaDataManagerImpl(
@@ -191,14 +171,13 @@
private var useMediaResumption: Boolean,
private val useQsMediaPlayer: Boolean,
private val systemClock: SystemClock,
- private val tunerService: TunerService,
private val mediaFlags: MediaFlags,
private val logger: MediaUiEventLogger,
private val smartspaceManager: SmartspaceManager?,
private val keyguardUpdateMonitor: KeyguardUpdateMonitor,
private val mediaDataLoader: dagger.Lazy<MediaDataLoader>,
private val mediaLogger: MediaLogger,
-) : Dumpable, BcSmartspaceDataPlugin.SmartspaceTargetListener, MediaDataManager {
+) : Dumpable, MediaDataManager {
companion object {
// UI surface label for subscribing Smartspace updates.
@@ -238,7 +217,6 @@
// There should ONLY be at most one Smartspace media recommendation.
var smartspaceMediaData: SmartspaceMediaData = EMPTY_SMARTSPACE_MEDIA_DATA
@Keep private var smartspaceSession: SmartspaceSession? = null
- private var allowMediaRecommendations = allowMediaRecommendations(context)
private val artworkWidth =
context.resources.getDimensionPixelSize(
@@ -276,7 +254,6 @@
mediaDataFilter: LegacyMediaDataFilterImpl,
smartspaceMediaDataProvider: SmartspaceMediaDataProvider,
clock: SystemClock,
- tunerService: TunerService,
mediaFlags: MediaFlags,
logger: MediaUiEventLogger,
smartspaceManager: SmartspaceManager?,
@@ -306,7 +283,6 @@
Utils.useMediaResumption(context),
Utils.useQsMediaPlayer(context),
clock,
- tunerService,
mediaFlags,
logger,
smartspaceManager,
@@ -372,7 +348,7 @@
context.registerReceiver(appChangeReceiver, uninstallFilter)
// Register for Smartspace data updates.
- smartspaceMediaDataProvider.registerListener(this)
+ // TODO(b/382680767): remove
smartspaceSession =
smartspaceManager?.createSmartspaceSession(
SmartspaceConfig.Builder(context, SMARTSPACE_UI_SURFACE_LABEL).build()
@@ -391,24 +367,9 @@
)
}
smartspaceSession?.let { it.requestSmartspaceUpdate() }
- tunerService.addTunable(
- object : TunerService.Tunable {
- override fun onTuningChanged(key: String?, newValue: String?) {
- allowMediaRecommendations = allowMediaRecommendations(context)
- if (!allowMediaRecommendations) {
- dismissSmartspaceRecommendation(
- key = smartspaceMediaData.targetId,
- delay = 0L,
- )
- }
- }
- },
- Settings.Secure.MEDIA_CONTROLS_RECOMMENDATION,
- )
}
override fun destroy() {
- smartspaceMediaDataProvider.unregisterListener(this)
smartspaceSession?.close()
smartspaceSession = null
context.unregisterReceiver(appChangeReceiver)
@@ -1328,61 +1289,6 @@
}
}
- override fun onSmartspaceTargetsUpdated(targets: List<Parcelable>) {
- if (!allowMediaRecommendations) {
- if (DEBUG) Log.d(TAG, "Smartspace recommendation is disabled in Settings.")
- return
- }
-
- val mediaTargets = targets.filterIsInstance<SmartspaceTarget>()
- when (mediaTargets.size) {
- 0 -> {
- if (!smartspaceMediaData.isActive) {
- return
- }
- if (DEBUG) {
- Log.d(TAG, "Set Smartspace media to be inactive for the data update")
- }
- if (mediaFlags.isPersistentSsCardEnabled()) {
- // Smartspace uses this signal to hide the card (e.g. when it expires or user
- // disconnects headphones), so treat as setting inactive when flag is on
- smartspaceMediaData = smartspaceMediaData.copy(isActive = false)
- notifySmartspaceMediaDataLoaded(
- smartspaceMediaData.targetId,
- smartspaceMediaData,
- )
- } else {
- smartspaceMediaData =
- EMPTY_SMARTSPACE_MEDIA_DATA.copy(
- targetId = smartspaceMediaData.targetId,
- instanceId = smartspaceMediaData.instanceId,
- )
- notifySmartspaceMediaDataRemoved(
- smartspaceMediaData.targetId,
- immediately = false,
- )
- }
- }
- 1 -> {
- val newMediaTarget = mediaTargets.get(0)
- if (smartspaceMediaData.targetId == newMediaTarget.smartspaceTargetId) {
- // The same Smartspace updates can be received. Skip the duplicate updates.
- return
- }
- if (DEBUG) Log.d(TAG, "Forwarding Smartspace media update.")
- smartspaceMediaData = toSmartspaceMediaData(newMediaTarget)
- notifySmartspaceMediaDataLoaded(smartspaceMediaData.targetId, smartspaceMediaData)
- }
- else -> {
- // There should NOT be more than 1 Smartspace media update. When it happens, it
- // indicates a bad state or an error. Reset the status accordingly.
- Log.wtf(TAG, "More than 1 Smartspace Media Update. Resetting the status...")
- notifySmartspaceMediaDataRemoved(smartspaceMediaData.targetId, immediately = false)
- smartspaceMediaData = EMPTY_SMARTSPACE_MEDIA_DATA
- }
- }
- }
-
override fun onNotificationRemoved(key: String) {
Assert.isMainThread()
val removed = mediaEntries.remove(key) ?: return
@@ -1641,7 +1547,6 @@
println("externalListeners: ${mediaDataFilter.listeners}")
println("mediaEntries: $mediaEntries")
println("useMediaResumption: $useMediaResumption")
- println("allowMediaRecommendations: $allowMediaRecommendations")
}
mediaDeviceManager.dump(pw)
}
diff --git a/packages/SystemUI/src/com/android/systemui/media/controls/domain/pipeline/MediaDataProcessor.kt b/packages/SystemUI/src/com/android/systemui/media/controls/domain/pipeline/MediaDataProcessor.kt
index 3821f3d..a524db4 100644
--- a/packages/SystemUI/src/com/android/systemui/media/controls/domain/pipeline/MediaDataProcessor.kt
+++ b/packages/SystemUI/src/com/android/systemui/media/controls/domain/pipeline/MediaDataProcessor.kt
@@ -45,16 +45,15 @@
import android.media.session.MediaSession
import android.media.session.PlaybackState
import android.net.Uri
-import android.os.Parcelable
import android.os.Process
import android.os.UserHandle
-import android.provider.Settings
import android.service.notification.StatusBarNotification
import android.support.v4.media.MediaMetadataCompat
import android.text.TextUtils
import android.util.Log
import android.util.Pair as APair
import androidx.media.utils.MediaConstants
+import com.android.app.tracing.coroutines.launchTraced as launch
import com.android.app.tracing.traceSection
import com.android.internal.annotations.Keep
import com.android.internal.logging.InstanceId
@@ -87,8 +86,6 @@
import com.android.systemui.media.controls.util.MediaFlags
import com.android.systemui.media.controls.util.MediaUiEventLogger
import com.android.systemui.media.controls.util.SmallHash
-import com.android.systemui.plugins.ActivityStarter
-import com.android.systemui.plugins.BcSmartspaceDataPlugin
import com.android.systemui.res.R
import com.android.systemui.scene.shared.flag.SceneContainerFlag
import com.android.systemui.statusbar.NotificationMediaManager.isPlayingState
@@ -97,8 +94,6 @@
import com.android.systemui.util.Utils
import com.android.systemui.util.concurrency.DelayableExecutor
import com.android.systemui.util.concurrency.ThreadFactory
-import com.android.systemui.util.settings.SecureSettings
-import com.android.systemui.util.settings.SettingsProxyExt.observerFlow
import com.android.systemui.util.time.SystemClock
import java.io.IOException
import java.io.PrintWriter
@@ -106,12 +101,6 @@
import javax.inject.Inject
import kotlinx.coroutines.CoroutineDispatcher
import kotlinx.coroutines.CoroutineScope
-import kotlinx.coroutines.flow.collectLatest
-import kotlinx.coroutines.flow.distinctUntilChanged
-import kotlinx.coroutines.flow.flowOn
-import kotlinx.coroutines.flow.map
-import kotlinx.coroutines.flow.onStart
-import com.android.app.tracing.coroutines.launchTraced as launch
import kotlinx.coroutines.withContext
// URI fields to try loading album art from
@@ -139,12 +128,10 @@
private val mediaControllerFactory: MediaControllerFactory,
private val broadcastDispatcher: BroadcastDispatcher,
private val dumpManager: DumpManager,
- private val activityStarter: ActivityStarter,
private val smartspaceMediaDataProvider: SmartspaceMediaDataProvider,
private var useMediaResumption: Boolean,
private val useQsMediaPlayer: Boolean,
private val systemClock: SystemClock,
- private val secureSettings: SecureSettings,
private val mediaFlags: MediaFlags,
private val logger: MediaUiEventLogger,
private val smartspaceManager: SmartspaceManager?,
@@ -152,7 +139,7 @@
private val mediaDataRepository: MediaDataRepository,
private val mediaDataLoader: dagger.Lazy<MediaDataLoader>,
private val mediaLogger: MediaLogger,
-) : CoreStartable, BcSmartspaceDataPlugin.SmartspaceTargetListener {
+) : CoreStartable {
companion object {
/**
@@ -191,7 +178,6 @@
// There should ONLY be at most one Smartspace media recommendation.
@Keep private var smartspaceSession: SmartspaceSession? = null
- private var allowMediaRecommendations = false
private val artworkWidth =
context.resources.getDimensionPixelSize(
@@ -221,10 +207,8 @@
mediaControllerFactory: MediaControllerFactory,
dumpManager: DumpManager,
broadcastDispatcher: BroadcastDispatcher,
- activityStarter: ActivityStarter,
smartspaceMediaDataProvider: SmartspaceMediaDataProvider,
clock: SystemClock,
- secureSettings: SecureSettings,
mediaFlags: MediaFlags,
logger: MediaUiEventLogger,
smartspaceManager: SmartspaceManager?,
@@ -245,12 +229,10 @@
mediaControllerFactory,
broadcastDispatcher,
dumpManager,
- activityStarter,
smartspaceMediaDataProvider,
Utils.useMediaResumption(context),
Utils.useQsMediaPlayer(context),
clock,
- secureSettings,
mediaFlags,
logger,
smartspaceManager,
@@ -296,7 +278,7 @@
context.registerReceiver(appChangeReceiver, uninstallFilter)
// Register for Smartspace data updates.
- smartspaceMediaDataProvider.registerListener(this)
+ // TODO(b/382680767): remove
smartspaceSession =
smartspaceManager?.createSmartspaceSession(
SmartspaceConfig.Builder(context, SMARTSPACE_UI_SURFACE_LABEL).build()
@@ -314,13 +296,9 @@
}
}
smartspaceSession?.requestSmartspaceUpdate()
-
- // Track media controls recommendation setting.
- applicationScope.launch { trackMediaControlsRecommendationSetting() }
}
fun destroy() {
- smartspaceMediaDataProvider.unregisterListener(this)
smartspaceSession?.close()
smartspaceSession = null
context.unregisterReceiver(appChangeReceiver)
@@ -357,43 +335,6 @@
}
}
- /**
- * Allow recommendations from smartspace to show in media controls. Requires
- * [Utils.useQsMediaPlayer] to be enabled. On by default, but can be disabled by setting to 0
- */
- private suspend fun allowMediaRecommendations(): Boolean {
- return withContext(backgroundDispatcher) {
- val flag =
- secureSettings.getBoolForUser(
- Settings.Secure.MEDIA_CONTROLS_RECOMMENDATION,
- true,
- UserHandle.USER_CURRENT,
- )
-
- useQsMediaPlayer && flag
- }
- }
-
- private suspend fun trackMediaControlsRecommendationSetting() {
- secureSettings
- .observerFlow(UserHandle.USER_ALL, Settings.Secure.MEDIA_CONTROLS_RECOMMENDATION)
- // perform a query at the beginning.
- .onStart { emit(Unit) }
- .map { allowMediaRecommendations() }
- .distinctUntilChanged()
- .flowOn(backgroundDispatcher)
- // only track the most recent emission
- .collectLatest {
- allowMediaRecommendations = it
- if (!allowMediaRecommendations) {
- dismissSmartspaceRecommendation(
- key = mediaDataRepository.smartspaceMediaData.value.targetId,
- delay = 0L,
- )
- }
- }
- }
-
private fun removeAllForPackage(packageName: String) {
Assert.isMainThread()
val toRemove =
@@ -1277,62 +1218,6 @@
}
}
- override fun onSmartspaceTargetsUpdated(targets: List<Parcelable>) {
- if (!allowMediaRecommendations) {
- if (DEBUG) Log.d(TAG, "Smartspace recommendation is disabled in Settings.")
- return
- }
-
- val mediaTargets = targets.filterIsInstance<SmartspaceTarget>()
- val smartspaceMediaData = mediaDataRepository.smartspaceMediaData.value
- when (mediaTargets.size) {
- 0 -> {
- if (!smartspaceMediaData.isActive) {
- return
- }
- if (DEBUG) {
- Log.d(TAG, "Set Smartspace media to be inactive for the data update")
- }
- if (mediaFlags.isPersistentSsCardEnabled()) {
- // Smartspace uses this signal to hide the card (e.g. when it expires or user
- // disconnects headphones), so treat as setting inactive when flag is on
- val recommendation = smartspaceMediaData.copy(isActive = false)
- mediaDataRepository.setRecommendation(recommendation)
- notifySmartspaceMediaDataLoaded(recommendation.targetId, recommendation)
- } else {
- notifySmartspaceMediaDataRemoved(
- smartspaceMediaData.targetId,
- immediately = false,
- )
- mediaDataRepository.setRecommendation(
- SmartspaceMediaData(
- targetId = smartspaceMediaData.targetId,
- instanceId = smartspaceMediaData.instanceId,
- )
- )
- }
- }
- 1 -> {
- val newMediaTarget = mediaTargets.get(0)
- if (smartspaceMediaData.targetId == newMediaTarget.smartspaceTargetId) {
- // The same Smartspace updates can be received. Skip the duplicate updates.
- return
- }
- if (DEBUG) Log.d(TAG, "Forwarding Smartspace media update.")
- val recommendation = toSmartspaceMediaData(newMediaTarget)
- mediaDataRepository.setRecommendation(recommendation)
- notifySmartspaceMediaDataLoaded(recommendation.targetId, recommendation)
- }
- else -> {
- // There should NOT be more than 1 Smartspace media update. When it happens, it
- // indicates a bad state or an error. Reset the status accordingly.
- Log.wtf(TAG, "More than 1 Smartspace Media Update. Resetting the status...")
- notifySmartspaceMediaDataRemoved(smartspaceMediaData.targetId, immediately = false)
- mediaDataRepository.setRecommendation(SmartspaceMediaData())
- }
- }
- }
-
fun onNotificationRemoved(key: String) {
Assert.isMainThread()
val removed = mediaDataRepository.removeMediaEntry(key) ?: return
@@ -1621,7 +1506,6 @@
pw.apply {
println("internalListeners: $internalListeners")
println("useMediaResumption: $useMediaResumption")
- println("allowMediaRecommendations: $allowMediaRecommendations")
}
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/media/controls/ui/controller/MediaViewController.kt b/packages/SystemUI/src/com/android/systemui/media/controls/ui/controller/MediaViewController.kt
index 86e9294..975f8f4 100644
--- a/packages/SystemUI/src/com/android/systemui/media/controls/ui/controller/MediaViewController.kt
+++ b/packages/SystemUI/src/com/android/systemui/media/controls/ui/controller/MediaViewController.kt
@@ -1042,6 +1042,18 @@
return null
}
+ if (state.expansion == 1.0f) {
+ val height =
+ if (state.expandedMatchesParentHeight) {
+ heightInSceneContainerPx
+ } else {
+ context.resources.getDimensionPixelSize(
+ R.dimen.qs_media_session_height_expanded
+ )
+ }
+ setBackgroundHeights(height)
+ }
+
// Similar to obtainViewState: Let's create a new measurement
val result =
transitionLayout?.calculateViewState(
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/chips/call/ui/viewmodel/CallChipViewModel.kt b/packages/SystemUI/src/com/android/systemui/statusbar/chips/call/ui/viewmodel/CallChipViewModel.kt
index 108d737..99e8472 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/chips/call/ui/viewmodel/CallChipViewModel.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/chips/call/ui/viewmodel/CallChipViewModel.kt
@@ -37,6 +37,7 @@
import com.android.systemui.statusbar.chips.ui.view.ChipBackgroundContainer
import com.android.systemui.statusbar.chips.ui.viewmodel.OngoingActivityChipViewModel
import com.android.systemui.statusbar.core.StatusBarConnectedDisplays
+import com.android.systemui.statusbar.phone.ongoingcall.StatusBarChipsModernization
import com.android.systemui.statusbar.phone.ongoingcall.shared.model.OngoingCallModel
import com.android.systemui.util.time.SystemClock
import javax.inject.Inject
@@ -93,9 +94,7 @@
icon = icon,
colors = colors,
onClickListenerLegacy = getOnClickListener(state),
- // TODO(b/372657935): Add click support for the call chip when
- // StatusBarChipModernization is enabled.
- clickBehavior = OngoingActivityChipModel.ClickBehavior.None,
+ clickBehavior = getClickBehavior(state),
)
} else {
val startTimeInElapsedRealtime =
@@ -106,9 +105,7 @@
colors = colors,
startTimeMs = startTimeInElapsedRealtime,
onClickListenerLegacy = getOnClickListener(state),
- // TODO(b/372657935): Add click support for the call chip when
- // StatusBarChipModernization is enabled.
- clickBehavior = OngoingActivityChipModel.ClickBehavior.None,
+ clickBehavior = getClickBehavior(state),
)
}
}
@@ -122,6 +119,7 @@
}
return View.OnClickListener { view ->
+ StatusBarChipsModernization.assertInLegacyMode()
logger.log(TAG, LogLevel.INFO, {}, { "Chip clicked" })
val backgroundView =
view.requireViewById<ChipBackgroundContainer>(R.id.ongoing_activity_chip_background)
@@ -136,6 +134,27 @@
}
}
+ private fun getClickBehavior(
+ state: OngoingCallModel.InCall
+ ): OngoingActivityChipModel.ClickBehavior =
+ if (state.intent == null) {
+ OngoingActivityChipModel.ClickBehavior.None
+ } else {
+ OngoingActivityChipModel.ClickBehavior.ExpandAction(
+ onClick = { expandable ->
+ StatusBarChipsModernization.assertInNewMode()
+ val animationController =
+ expandable.activityTransitionController(
+ InteractionJankMonitor.CUJ_STATUS_BAR_APP_LAUNCH_FROM_CALL_CHIP
+ )
+ activityStarter.postStartActivityDismissingKeyguard(
+ state.intent,
+ animationController,
+ )
+ }
+ )
+ }
+
companion object {
private val phoneIcon =
Icon.Resource(
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/promoted/PromotedNotificationUiAod.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/promoted/PromotedNotificationUiAod.kt
new file mode 100644
index 0000000..fa1f32c
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/promoted/PromotedNotificationUiAod.kt
@@ -0,0 +1,60 @@
+/*
+ * Copyright (C) 2025 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.statusbar.notification.promoted
+
+import com.android.systemui.Flags
+import com.android.systemui.flags.FlagToken
+import com.android.systemui.flags.RefactorFlagUtils
+
+/** Helper for reading or using the promoted ongoing notifications AOD flag state. */
+object PromotedNotificationUiAod {
+ /** The aconfig flag name */
+ const val FLAG_NAME = Flags.FLAG_AOD_UI_RICH_ONGOING
+
+ /** A token used for dependency declaration */
+ val token: FlagToken
+ get() = FlagToken(FLAG_NAME, isEnabled)
+
+ /** Is the refactor enabled */
+ @JvmStatic
+ inline val isEnabled
+ get() = Flags.aodUiRichOngoing()
+
+ /**
+ * Called to ensure code is only run when the flag is enabled. This protects users from the
+ * unintended behaviors caused by accidentally running new logic, while also crashing on an eng
+ * build to ensure that the refactor author catches issues in testing.
+ */
+ @JvmStatic
+ inline fun isUnexpectedlyInLegacyMode() =
+ RefactorFlagUtils.isUnexpectedlyInLegacyMode(isEnabled, FLAG_NAME)
+
+ /**
+ * Called to ensure code is only run when the flag is disabled. This will throw an exception if
+ * the flag is not enabled to ensure that the refactor author catches issues in testing.
+ * Caution!! Using this check incorrectly will cause crashes in nextfood builds!
+ */
+ @JvmStatic
+ inline fun assertInNewMode() = RefactorFlagUtils.assertInNewMode(isEnabled, FLAG_NAME)
+
+ /**
+ * Called to ensure code is only run when the flag is disabled. This will throw an exception if
+ * the flag is enabled to ensure that the refactor author catches issues in testing.
+ */
+ @JvmStatic
+ inline fun assertInLegacyMode() = RefactorFlagUtils.assertInLegacyMode(isEnabled, FLAG_NAME)
+}
diff --git a/packages/SystemUI/src/com/android/systemui/tuner/TunerServiceImpl.java b/packages/SystemUI/src/com/android/systemui/tuner/TunerServiceImpl.java
index 05ee35b..8f5fccd 100644
--- a/packages/SystemUI/src/com/android/systemui/tuner/TunerServiceImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/tuner/TunerServiceImpl.java
@@ -75,8 +75,7 @@
private static final String[] RESET_EXCEPTION_LIST = new String[] {
QSHost.TILES_SETTING,
Settings.Secure.DOZE_ALWAYS_ON,
- Settings.Secure.MEDIA_CONTROLS_RESUME,
- Settings.Secure.MEDIA_CONTROLS_RECOMMENDATION
+ Settings.Secure.MEDIA_CONTROLS_RESUME
};
private final Observer mObserver = new Observer();
diff --git a/packages/SystemUI/tests/src/com/android/systemui/keyguard/CustomizationProviderTest.kt b/packages/SystemUI/tests/src/com/android/systemui/keyguard/CustomizationProviderTest.kt
index 82bf5e2..a3c3d2c 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/keyguard/CustomizationProviderTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/keyguard/CustomizationProviderTest.kt
@@ -205,6 +205,7 @@
biometricSettingsRepository = biometricSettingsRepository,
backgroundDispatcher = testDispatcher,
appContext = mContext,
+ accessibilityManager = mock(),
communalSettingsInteractor = kosmos.communalSettingsInteractor,
sceneInteractor = { kosmos.sceneInteractor },
)
diff --git a/packages/SystemUI/tests/src/com/android/systemui/keyguard/domain/interactor/KeyguardQuickAffordanceInteractorParameterizedTest.kt b/packages/SystemUI/tests/src/com/android/systemui/keyguard/domain/interactor/KeyguardQuickAffordanceInteractorParameterizedTest.kt
index 111d819..21519b0 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/keyguard/domain/interactor/KeyguardQuickAffordanceInteractorParameterizedTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/keyguard/domain/interactor/KeyguardQuickAffordanceInteractorParameterizedTest.kt
@@ -322,6 +322,7 @@
biometricSettingsRepository = biometricSettingsRepository,
backgroundDispatcher = testDispatcher,
appContext = mContext,
+ accessibilityManager = mock(),
communalSettingsInteractor = kosmos.communalSettingsInteractor,
sceneInteractor = { kosmos.sceneInteractor },
)
diff --git a/packages/SystemUI/tests/src/com/android/systemui/keyguard/domain/interactor/KeyguardQuickAffordanceInteractorSceneContainerTest.kt b/packages/SystemUI/tests/src/com/android/systemui/keyguard/domain/interactor/KeyguardQuickAffordanceInteractorSceneContainerTest.kt
index 8c00047..caf08ef 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/keyguard/domain/interactor/KeyguardQuickAffordanceInteractorSceneContainerTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/keyguard/domain/interactor/KeyguardQuickAffordanceInteractorSceneContainerTest.kt
@@ -325,6 +325,7 @@
biometricSettingsRepository = biometricSettingsRepository,
backgroundDispatcher = testDispatcher,
appContext = mContext,
+ accessibilityManager = mock(),
communalSettingsInteractor = kosmos.communalSettingsInteractor,
sceneInteractor = { kosmos.sceneInteractor },
)
diff --git a/packages/SystemUI/tests/src/com/android/systemui/keyguard/ui/viewmodel/KeyguardQuickAffordancesCombinedViewModelTest.kt b/packages/SystemUI/tests/src/com/android/systemui/keyguard/ui/viewmodel/KeyguardQuickAffordancesCombinedViewModelTest.kt
index 0b2b867..b5a2271 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/keyguard/ui/viewmodel/KeyguardQuickAffordancesCombinedViewModelTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/keyguard/ui/viewmodel/KeyguardQuickAffordancesCombinedViewModelTest.kt
@@ -294,6 +294,7 @@
biometricSettingsRepository = biometricSettingsRepository,
backgroundDispatcher = kosmos.testDispatcher,
appContext = mContext,
+ accessibilityManager = mock(),
communalSettingsInteractor = kosmos.communalSettingsInteractor,
sceneInteractor = { kosmos.sceneInteractor },
),
diff --git a/packages/SystemUI/tests/src/com/android/systemui/media/controls/domain/pipeline/LegacyMediaDataManagerImplTest.kt b/packages/SystemUI/tests/src/com/android/systemui/media/controls/domain/pipeline/LegacyMediaDataManagerImplTest.kt
index 3ddd4b5..2815b9769 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/media/controls/domain/pipeline/LegacyMediaDataManagerImplTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/media/controls/domain/pipeline/LegacyMediaDataManagerImplTest.kt
@@ -41,13 +41,11 @@
import android.platform.test.annotations.DisableFlags
import android.platform.test.annotations.EnableFlags
import android.platform.test.flag.junit.FlagsParameterization
-import android.provider.Settings
import android.service.notification.StatusBarNotification
import android.testing.TestableLooper.RunWithLooper
import androidx.media.utils.MediaConstants
import androidx.test.filters.SmallTest
import com.android.dx.mockito.inline.extended.ExtendedMockito
-import com.android.internal.logging.InstanceId
import com.android.keyguard.KeyguardUpdateMonitor
import com.android.systemui.Flags
import com.android.systemui.InstanceIdSequenceFake
@@ -65,10 +63,7 @@
import com.android.systemui.media.controls.domain.resume.ResumeMediaBrowser
import com.android.systemui.media.controls.shared.mediaLogger
import com.android.systemui.media.controls.shared.mockMediaLogger
-import com.android.systemui.media.controls.shared.model.EXTRA_KEY_TRIGGER_SOURCE
-import com.android.systemui.media.controls.shared.model.EXTRA_VALUE_TRIGGER_PERIODIC
import com.android.systemui.media.controls.shared.model.MediaData
-import com.android.systemui.media.controls.shared.model.SmartspaceMediaData
import com.android.systemui.media.controls.shared.model.SmartspaceMediaDataProvider
import com.android.systemui.media.controls.util.MediaUiEventLogger
import com.android.systemui.media.controls.util.fakeMediaControllerFactory
@@ -76,7 +71,6 @@
import com.android.systemui.res.R
import com.android.systemui.statusbar.SbnBuilder
import com.android.systemui.testKosmos
-import com.android.systemui.tuner.TunerService
import com.android.systemui.util.concurrency.FakeExecutor
import com.android.systemui.util.time.FakeSystemClock
import com.google.common.truth.Truth.assertThat
@@ -95,12 +89,10 @@
import org.mockito.ArgumentMatchers.anyInt
import org.mockito.Captor
import org.mockito.Mock
-import org.mockito.Mockito
import org.mockito.Mockito.mock
import org.mockito.Mockito.never
import org.mockito.Mockito.reset
import org.mockito.Mockito.verify
-import org.mockito.Mockito.verifyNoMoreInteractions
import org.mockito.Mockito.`when` as whenever
import org.mockito.MockitoSession
import org.mockito.junit.MockitoJUnit
@@ -126,10 +118,6 @@
private const val USER_ID = 0
private val DISMISS_INTENT = Intent().apply { action = "dismiss" }
-private fun <T> anyObject(): T {
- return Mockito.anyObject<T>()
-}
-
@OptIn(ExperimentalCoroutinesApi::class)
@SmallTest
@RunWithLooper(setAsMainLooper = true)
@@ -168,8 +156,6 @@
lateinit var remoteCastNotification: StatusBarNotification
@Captor lateinit var mediaDataCaptor: ArgumentCaptor<MediaData>
private val clock = FakeSystemClock()
- @Mock private lateinit var tunerService: TunerService
- @Captor lateinit var tunableCaptor: ArgumentCaptor<TunerService.Tunable>
@Captor lateinit var stateCallbackCaptor: ArgumentCaptor<(String, PlaybackState) -> Unit>
@Captor lateinit var sessionCallbackCaptor: ArgumentCaptor<(String) -> Unit>
@Captor lateinit var smartSpaceConfigBuilderCaptor: ArgumentCaptor<SmartspaceConfig>
@@ -197,13 +183,6 @@
private val mediaControllerFactory = kosmos.fakeMediaControllerFactory
private val instanceIdSequence = InstanceIdSequenceFake(1 shl 20)
- private val originalSmartspaceSetting =
- Settings.Secure.getInt(
- context.contentResolver,
- Settings.Secure.MEDIA_CONTROLS_RECOMMENDATION,
- 1,
- )
-
private lateinit var staticMockSession: MockitoSession
@Before
@@ -219,11 +198,6 @@
backgroundExecutor = FakeExecutor(clock)
uiExecutor = FakeExecutor(clock)
smartspaceMediaDataProvider = SmartspaceMediaDataProvider()
- Settings.Secure.putInt(
- context.contentResolver,
- Settings.Secure.MEDIA_CONTROLS_RECOMMENDATION,
- 1,
- )
mediaDataManager =
LegacyMediaDataManagerImpl(
context = context,
@@ -246,7 +220,6 @@
useMediaResumption = true,
useQsMediaPlayer = true,
systemClock = clock,
- tunerService = tunerService,
mediaFlags = kosmos.mediaFlags,
logger = logger,
smartspaceManager = smartspaceManager,
@@ -254,8 +227,6 @@
mediaDataLoader = { kosmos.mediaDataLoader },
mediaLogger = kosmos.mediaLogger,
)
- verify(tunerService)
- .addTunable(capture(tunableCaptor), eq(Settings.Secure.MEDIA_CONTROLS_RECOMMENDATION))
verify(mediaTimeoutListener).stateCallback = capture(stateCallbackCaptor)
verify(mediaTimeoutListener).sessionCallback = capture(sessionCallbackCaptor)
session = MediaSession(context, "MediaDataManagerTestSession")
@@ -332,11 +303,6 @@
staticMockSession.finishMocking()
session.release()
mediaDataManager.destroy()
- Settings.Secure.putInt(
- context.contentResolver,
- Settings.Secure.MEDIA_CONTROLS_RECOMMENDATION,
- originalSmartspaceSetting,
- )
}
@Test
@@ -1236,272 +1202,6 @@
}
@Test
- fun testOnSmartspaceMediaDataLoaded_hasNewValidMediaTarget_callsListener() {
- smartspaceMediaDataProvider.onTargetsAvailable(listOf(mediaSmartspaceTarget))
- verify(logger).getNewInstanceId()
- val instanceId = instanceIdSequence.lastInstanceId
-
- verify(listener)
- .onSmartspaceMediaDataLoaded(
- eq(KEY_MEDIA_SMARTSPACE),
- eq(
- SmartspaceMediaData(
- targetId = KEY_MEDIA_SMARTSPACE,
- isActive = true,
- packageName = PACKAGE_NAME,
- cardAction = mediaSmartspaceBaseAction,
- recommendations = validRecommendationList,
- dismissIntent = DISMISS_INTENT,
- headphoneConnectionTimeMillis = SMARTSPACE_CREATION_TIME,
- instanceId = InstanceId.fakeInstanceId(instanceId),
- expiryTimeMs = SMARTSPACE_EXPIRY_TIME,
- )
- ),
- eq(false),
- )
- }
-
- @Test
- fun testOnSmartspaceMediaDataLoaded_hasNewInvalidMediaTarget_callsListener() {
- whenever(mediaSmartspaceTarget.iconGrid).thenReturn(listOf())
- smartspaceMediaDataProvider.onTargetsAvailable(listOf(mediaSmartspaceTarget))
- verify(logger).getNewInstanceId()
- val instanceId = instanceIdSequence.lastInstanceId
-
- verify(listener)
- .onSmartspaceMediaDataLoaded(
- eq(KEY_MEDIA_SMARTSPACE),
- eq(
- EMPTY_SMARTSPACE_MEDIA_DATA.copy(
- targetId = KEY_MEDIA_SMARTSPACE,
- isActive = true,
- dismissIntent = DISMISS_INTENT,
- headphoneConnectionTimeMillis = SMARTSPACE_CREATION_TIME,
- instanceId = InstanceId.fakeInstanceId(instanceId),
- expiryTimeMs = SMARTSPACE_EXPIRY_TIME,
- )
- ),
- eq(false),
- )
- }
-
- @Test
- fun testOnSmartspaceMediaDataLoaded_hasNullIntent_callsListener() {
- val recommendationExtras =
- Bundle().apply {
- putString("package_name", PACKAGE_NAME)
- putParcelable("dismiss_intent", null)
- }
- whenever(mediaSmartspaceBaseAction.extras).thenReturn(recommendationExtras)
- whenever(mediaSmartspaceTarget.baseAction).thenReturn(mediaSmartspaceBaseAction)
- whenever(mediaSmartspaceTarget.iconGrid).thenReturn(listOf())
-
- smartspaceMediaDataProvider.onTargetsAvailable(listOf(mediaSmartspaceTarget))
- verify(logger).getNewInstanceId()
- val instanceId = instanceIdSequence.lastInstanceId
-
- verify(listener)
- .onSmartspaceMediaDataLoaded(
- eq(KEY_MEDIA_SMARTSPACE),
- eq(
- EMPTY_SMARTSPACE_MEDIA_DATA.copy(
- targetId = KEY_MEDIA_SMARTSPACE,
- isActive = true,
- dismissIntent = null,
- headphoneConnectionTimeMillis = SMARTSPACE_CREATION_TIME,
- instanceId = InstanceId.fakeInstanceId(instanceId),
- expiryTimeMs = SMARTSPACE_EXPIRY_TIME,
- )
- ),
- eq(false),
- )
- }
-
- @Test
- fun testOnSmartspaceMediaDataLoaded_hasNoneMediaTarget_notCallsListener() {
- smartspaceMediaDataProvider.onTargetsAvailable(listOf())
- verify(logger, never()).getNewInstanceId()
- verify(listener, never())
- .onSmartspaceMediaDataLoaded(anyObject(), anyObject(), anyBoolean())
- }
-
- @Test
- fun testOnSmartspaceMediaDataLoaded_hasNoneMediaTarget_callsRemoveListener() {
- smartspaceMediaDataProvider.onTargetsAvailable(listOf(mediaSmartspaceTarget))
- verify(logger).getNewInstanceId()
-
- smartspaceMediaDataProvider.onTargetsAvailable(listOf())
- uiExecutor.advanceClockToLast()
- uiExecutor.runAllReady()
-
- verify(listener).onSmartspaceMediaDataRemoved(eq(KEY_MEDIA_SMARTSPACE), eq(false))
- verifyNoMoreInteractions(logger)
- }
-
- @Test
- fun testOnSmartspaceMediaDataLoaded_persistentEnabled_headphoneTrigger_isActive() {
- fakeFeatureFlags.set(MEDIA_RETAIN_RECOMMENDATIONS, true)
- smartspaceMediaDataProvider.onTargetsAvailable(listOf(mediaSmartspaceTarget))
- val instanceId = instanceIdSequence.lastInstanceId
-
- verify(listener)
- .onSmartspaceMediaDataLoaded(
- eq(KEY_MEDIA_SMARTSPACE),
- eq(
- SmartspaceMediaData(
- targetId = KEY_MEDIA_SMARTSPACE,
- isActive = true,
- packageName = PACKAGE_NAME,
- cardAction = mediaSmartspaceBaseAction,
- recommendations = validRecommendationList,
- dismissIntent = DISMISS_INTENT,
- headphoneConnectionTimeMillis = SMARTSPACE_CREATION_TIME,
- instanceId = InstanceId.fakeInstanceId(instanceId),
- expiryTimeMs = SMARTSPACE_EXPIRY_TIME,
- )
- ),
- eq(false),
- )
- }
-
- @Test
- fun testOnSmartspaceMediaDataLoaded_persistentEnabled_periodicTrigger_notActive() {
- fakeFeatureFlags.set(MEDIA_RETAIN_RECOMMENDATIONS, true)
- val extras =
- Bundle().apply {
- putString("package_name", PACKAGE_NAME)
- putParcelable("dismiss_intent", DISMISS_INTENT)
- putString(EXTRA_KEY_TRIGGER_SOURCE, EXTRA_VALUE_TRIGGER_PERIODIC)
- }
- whenever(mediaSmartspaceBaseAction.extras).thenReturn(extras)
-
- smartspaceMediaDataProvider.onTargetsAvailable(listOf(mediaSmartspaceTarget))
- val instanceId = instanceIdSequence.lastInstanceId
-
- verify(listener)
- .onSmartspaceMediaDataLoaded(
- eq(KEY_MEDIA_SMARTSPACE),
- eq(
- SmartspaceMediaData(
- targetId = KEY_MEDIA_SMARTSPACE,
- isActive = false,
- packageName = PACKAGE_NAME,
- cardAction = mediaSmartspaceBaseAction,
- recommendations = validRecommendationList,
- dismissIntent = DISMISS_INTENT,
- headphoneConnectionTimeMillis = SMARTSPACE_CREATION_TIME,
- instanceId = InstanceId.fakeInstanceId(instanceId),
- expiryTimeMs = SMARTSPACE_EXPIRY_TIME,
- )
- ),
- eq(false),
- )
- }
-
- @Test
- fun testOnSmartspaceMediaDataLoaded_persistentEnabled_noTargets_inactive() {
- fakeFeatureFlags.set(MEDIA_RETAIN_RECOMMENDATIONS, true)
-
- smartspaceMediaDataProvider.onTargetsAvailable(listOf(mediaSmartspaceTarget))
- val instanceId = instanceIdSequence.lastInstanceId
-
- smartspaceMediaDataProvider.onTargetsAvailable(listOf())
- uiExecutor.advanceClockToLast()
- uiExecutor.runAllReady()
-
- verify(listener)
- .onSmartspaceMediaDataLoaded(
- eq(KEY_MEDIA_SMARTSPACE),
- eq(
- SmartspaceMediaData(
- targetId = KEY_MEDIA_SMARTSPACE,
- isActive = false,
- packageName = PACKAGE_NAME,
- cardAction = mediaSmartspaceBaseAction,
- recommendations = validRecommendationList,
- dismissIntent = DISMISS_INTENT,
- headphoneConnectionTimeMillis = SMARTSPACE_CREATION_TIME,
- instanceId = InstanceId.fakeInstanceId(instanceId),
- expiryTimeMs = SMARTSPACE_EXPIRY_TIME,
- )
- ),
- eq(false),
- )
- verify(listener, never()).onSmartspaceMediaDataRemoved(eq(KEY_MEDIA_SMARTSPACE), eq(false))
- }
-
- @Test
- fun testSetRecommendationInactive_notifiesListeners() {
- fakeFeatureFlags.set(MEDIA_RETAIN_RECOMMENDATIONS, true)
-
- smartspaceMediaDataProvider.onTargetsAvailable(listOf(mediaSmartspaceTarget))
- val instanceId = instanceIdSequence.lastInstanceId
-
- mediaDataManager.setRecommendationInactive(KEY_MEDIA_SMARTSPACE)
- uiExecutor.advanceClockToLast()
- uiExecutor.runAllReady()
-
- verify(listener)
- .onSmartspaceMediaDataLoaded(
- eq(KEY_MEDIA_SMARTSPACE),
- eq(
- SmartspaceMediaData(
- targetId = KEY_MEDIA_SMARTSPACE,
- isActive = false,
- packageName = PACKAGE_NAME,
- cardAction = mediaSmartspaceBaseAction,
- recommendations = validRecommendationList,
- dismissIntent = DISMISS_INTENT,
- headphoneConnectionTimeMillis = SMARTSPACE_CREATION_TIME,
- instanceId = InstanceId.fakeInstanceId(instanceId),
- expiryTimeMs = SMARTSPACE_EXPIRY_TIME,
- )
- ),
- eq(false),
- )
- }
-
- @Test
- fun testOnSmartspaceMediaDataLoaded_settingDisabled_doesNothing() {
- // WHEN media recommendation setting is off
- Settings.Secure.putInt(
- context.contentResolver,
- Settings.Secure.MEDIA_CONTROLS_RECOMMENDATION,
- 0,
- )
- tunableCaptor.value.onTuningChanged(Settings.Secure.MEDIA_CONTROLS_RECOMMENDATION, "0")
-
- smartspaceMediaDataProvider.onTargetsAvailable(listOf(mediaSmartspaceTarget))
-
- // THEN smartspace signal is ignored
- verify(listener, never())
- .onSmartspaceMediaDataLoaded(anyObject(), anyObject(), anyBoolean())
- }
-
- @Test
- fun testMediaRecommendationDisabled_removesSmartspaceData() {
- // GIVEN a media recommendation card is present
- smartspaceMediaDataProvider.onTargetsAvailable(listOf(mediaSmartspaceTarget))
- verify(listener)
- .onSmartspaceMediaDataLoaded(eq(KEY_MEDIA_SMARTSPACE), anyObject(), anyBoolean())
-
- // WHEN the media recommendation setting is turned off
- Settings.Secure.putInt(
- context.contentResolver,
- Settings.Secure.MEDIA_CONTROLS_RECOMMENDATION,
- 0,
- )
- tunableCaptor.value.onTuningChanged(Settings.Secure.MEDIA_CONTROLS_RECOMMENDATION, "0")
-
- // THEN listeners are notified
- uiExecutor.advanceClockToLast()
- foregroundExecutor.advanceClockToLast()
- uiExecutor.runAllReady()
- foregroundExecutor.runAllReady()
- verify(listener).onSmartspaceMediaDataRemoved(eq(KEY_MEDIA_SMARTSPACE), eq(true))
- }
-
- @Test
fun testOnMediaDataChanged_updatesLastActiveTime() {
val currentTime = clock.elapsedRealtime()
addNotificationAndLoad()
diff --git a/packages/SystemUI/tests/src/com/android/systemui/media/controls/domain/pipeline/MediaDataProcessorTest.kt b/packages/SystemUI/tests/src/com/android/systemui/media/controls/domain/pipeline/MediaDataProcessorTest.kt
index e5483c0..b9ebce8 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/media/controls/domain/pipeline/MediaDataProcessorTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/media/controls/domain/pipeline/MediaDataProcessorTest.kt
@@ -42,13 +42,11 @@
import android.platform.test.annotations.DisableFlags
import android.platform.test.annotations.EnableFlags
import android.platform.test.flag.junit.FlagsParameterization
-import android.provider.Settings
import android.service.notification.StatusBarNotification
import android.testing.TestableLooper.RunWithLooper
import androidx.media.utils.MediaConstants
import androidx.test.filters.SmallTest
import com.android.dx.mockito.inline.extended.ExtendedMockito
-import com.android.internal.logging.InstanceId
import com.android.keyguard.KeyguardUpdateMonitor
import com.android.systemui.Flags
import com.android.systemui.InstanceIdSequenceFake
@@ -71,21 +69,16 @@
import com.android.systemui.media.controls.domain.resume.ResumeMediaBrowser
import com.android.systemui.media.controls.shared.mediaLogger
import com.android.systemui.media.controls.shared.mockMediaLogger
-import com.android.systemui.media.controls.shared.model.EXTRA_KEY_TRIGGER_SOURCE
-import com.android.systemui.media.controls.shared.model.EXTRA_VALUE_TRIGGER_PERIODIC
import com.android.systemui.media.controls.shared.model.MediaData
-import com.android.systemui.media.controls.shared.model.SmartspaceMediaData
import com.android.systemui.media.controls.shared.model.SmartspaceMediaDataProvider
import com.android.systemui.media.controls.util.MediaUiEventLogger
import com.android.systemui.media.controls.util.fakeMediaControllerFactory
import com.android.systemui.media.controls.util.mediaFlags
-import com.android.systemui.plugins.activityStarter
import com.android.systemui.res.R
import com.android.systemui.statusbar.SbnBuilder
import com.android.systemui.statusbar.notificationLockscreenUserManager
import com.android.systemui.testKosmos
import com.android.systemui.util.concurrency.FakeExecutor
-import com.android.systemui.util.settings.fakeSettings
import com.android.systemui.util.time.FakeSystemClock
import com.google.common.truth.Truth.assertThat
import kotlinx.coroutines.ExperimentalCoroutinesApi
@@ -102,11 +95,9 @@
import org.mockito.ArgumentMatchers.anyInt
import org.mockito.Captor
import org.mockito.Mock
-import org.mockito.Mockito
import org.mockito.Mockito.never
import org.mockito.Mockito.reset
import org.mockito.Mockito.verify
-import org.mockito.Mockito.verifyNoMoreInteractions
import org.mockito.MockitoSession
import org.mockito.junit.MockitoJUnit
import org.mockito.kotlin.any
@@ -133,10 +124,6 @@
private const val USER_ID = 0
private val DISMISS_INTENT = Intent().apply { action = "dismiss" }
-private fun <T> anyObject(): T {
- return Mockito.anyObject<T>()
-}
-
@OptIn(ExperimentalCoroutinesApi::class)
@SmallTest
@RunWithLooper(setAsMainLooper = true)
@@ -146,7 +133,6 @@
private val kosmos = testKosmos().apply { mediaLogger = mockMediaLogger }
private val testDispatcher = kosmos.testDispatcher
private val testScope = kosmos.testScope
- private val settings = kosmos.fakeSettings
@JvmField @Rule val mockito = MockitoJUnit.rule()
@Mock lateinit var controller: MediaController
@@ -201,7 +187,6 @@
}
private val fakeFeatureFlags = kosmos.fakeFeatureFlagsClassic
- private val activityStarter = kosmos.activityStarter
private val mediaControllerFactory = kosmos.fakeMediaControllerFactory
private val notificationLockscreenUserManager = kosmos.notificationLockscreenUserManager
private val mediaFilterRepository = kosmos.mediaFilterRepository
@@ -209,13 +194,6 @@
private val instanceIdSequence = InstanceIdSequenceFake(1 shl 20)
- private val originalSmartspaceSetting =
- Settings.Secure.getInt(
- context.contentResolver,
- Settings.Secure.MEDIA_CONTROLS_RECOMMENDATION,
- 1,
- )
-
private lateinit var staticMockSession: MockitoSession
@Before
@@ -231,11 +209,6 @@
backgroundExecutor = FakeExecutor(clock)
uiExecutor = FakeExecutor(clock)
smartspaceMediaDataProvider = SmartspaceMediaDataProvider()
- Settings.Secure.putInt(
- context.contentResolver,
- Settings.Secure.MEDIA_CONTROLS_RECOMMENDATION,
- 1,
- )
mediaDataProcessor =
MediaDataProcessor(
context = context,
@@ -248,12 +221,10 @@
mediaControllerFactory = mediaControllerFactory,
broadcastDispatcher = broadcastDispatcher,
dumpManager = dumpManager,
- activityStarter = activityStarter,
smartspaceMediaDataProvider = smartspaceMediaDataProvider,
useMediaResumption = true,
useQsMediaPlayer = true,
systemClock = clock,
- secureSettings = settings,
mediaFlags = kosmos.mediaFlags,
logger = logger,
smartspaceManager = smartspaceManager,
@@ -355,11 +326,6 @@
staticMockSession.finishMocking()
session.release()
mediaDataProcessor.destroy()
- Settings.Secure.putInt(
- context.contentResolver,
- Settings.Secure.MEDIA_CONTROLS_RECOMMENDATION,
- originalSmartspaceSetting,
- )
}
@Test
@@ -1255,264 +1221,6 @@
}
@Test
- fun testOnSmartspaceMediaDataLoaded_hasNewValidMediaTarget_callsListener() {
- smartspaceMediaDataProvider.onTargetsAvailable(listOf(mediaSmartspaceTarget))
- verify(logger).getNewInstanceId()
- val instanceId = instanceIdSequence.lastInstanceId
-
- verify(listener)
- .onSmartspaceMediaDataLoaded(
- eq(KEY_MEDIA_SMARTSPACE),
- eq(
- SmartspaceMediaData(
- targetId = KEY_MEDIA_SMARTSPACE,
- isActive = true,
- packageName = PACKAGE_NAME,
- cardAction = mediaSmartspaceBaseAction,
- recommendations = validRecommendationList,
- dismissIntent = DISMISS_INTENT,
- headphoneConnectionTimeMillis = SMARTSPACE_CREATION_TIME,
- instanceId = InstanceId.fakeInstanceId(instanceId),
- expiryTimeMs = SMARTSPACE_EXPIRY_TIME,
- )
- ),
- eq(false),
- )
- }
-
- @Test
- fun testOnSmartspaceMediaDataLoaded_hasNewInvalidMediaTarget_callsListener() {
- whenever(mediaSmartspaceTarget.iconGrid).thenReturn(listOf())
- smartspaceMediaDataProvider.onTargetsAvailable(listOf(mediaSmartspaceTarget))
- verify(logger).getNewInstanceId()
- val instanceId = instanceIdSequence.lastInstanceId
-
- verify(listener)
- .onSmartspaceMediaDataLoaded(
- eq(KEY_MEDIA_SMARTSPACE),
- eq(
- SmartspaceMediaData(
- targetId = KEY_MEDIA_SMARTSPACE,
- isActive = true,
- dismissIntent = DISMISS_INTENT,
- headphoneConnectionTimeMillis = SMARTSPACE_CREATION_TIME,
- instanceId = InstanceId.fakeInstanceId(instanceId),
- expiryTimeMs = SMARTSPACE_EXPIRY_TIME,
- )
- ),
- eq(false),
- )
- }
-
- @Test
- fun testOnSmartspaceMediaDataLoaded_hasNullIntent_callsListener() {
- val recommendationExtras =
- Bundle().apply {
- putString("package_name", PACKAGE_NAME)
- putParcelable("dismiss_intent", null)
- }
- whenever(mediaSmartspaceBaseAction.extras).thenReturn(recommendationExtras)
- whenever(mediaSmartspaceTarget.baseAction).thenReturn(mediaSmartspaceBaseAction)
- whenever(mediaSmartspaceTarget.iconGrid).thenReturn(listOf())
-
- smartspaceMediaDataProvider.onTargetsAvailable(listOf(mediaSmartspaceTarget))
- verify(logger).getNewInstanceId()
- val instanceId = instanceIdSequence.lastInstanceId
-
- verify(listener)
- .onSmartspaceMediaDataLoaded(
- eq(KEY_MEDIA_SMARTSPACE),
- eq(
- SmartspaceMediaData(
- targetId = KEY_MEDIA_SMARTSPACE,
- isActive = true,
- dismissIntent = null,
- headphoneConnectionTimeMillis = SMARTSPACE_CREATION_TIME,
- instanceId = InstanceId.fakeInstanceId(instanceId),
- expiryTimeMs = SMARTSPACE_EXPIRY_TIME,
- )
- ),
- eq(false),
- )
- }
-
- @Test
- fun testOnSmartspaceMediaDataLoaded_hasNoneMediaTarget_notCallsListener() {
- smartspaceMediaDataProvider.onTargetsAvailable(listOf())
- verify(logger, never()).getNewInstanceId()
- verify(listener, never())
- .onSmartspaceMediaDataLoaded(anyObject(), anyObject(), anyBoolean())
- }
-
- @Test
- fun testOnSmartspaceMediaDataLoaded_hasNoneMediaTarget_callsRemoveListener() {
- smartspaceMediaDataProvider.onTargetsAvailable(listOf(mediaSmartspaceTarget))
- verify(logger).getNewInstanceId()
-
- smartspaceMediaDataProvider.onTargetsAvailable(listOf())
- uiExecutor.advanceClockToLast()
- uiExecutor.runAllReady()
-
- verify(listener).onSmartspaceMediaDataRemoved(eq(KEY_MEDIA_SMARTSPACE), eq(false))
- verifyNoMoreInteractions(logger)
- }
-
- @Test
- fun testOnSmartspaceMediaDataLoaded_persistentEnabled_headphoneTrigger_isActive() {
- fakeFeatureFlags.set(MEDIA_RETAIN_RECOMMENDATIONS, true)
- smartspaceMediaDataProvider.onTargetsAvailable(listOf(mediaSmartspaceTarget))
- val instanceId = instanceIdSequence.lastInstanceId
-
- verify(listener)
- .onSmartspaceMediaDataLoaded(
- eq(KEY_MEDIA_SMARTSPACE),
- eq(
- SmartspaceMediaData(
- targetId = KEY_MEDIA_SMARTSPACE,
- isActive = true,
- packageName = PACKAGE_NAME,
- cardAction = mediaSmartspaceBaseAction,
- recommendations = validRecommendationList,
- dismissIntent = DISMISS_INTENT,
- headphoneConnectionTimeMillis = SMARTSPACE_CREATION_TIME,
- instanceId = InstanceId.fakeInstanceId(instanceId),
- expiryTimeMs = SMARTSPACE_EXPIRY_TIME,
- )
- ),
- eq(false),
- )
- }
-
- @Test
- fun testOnSmartspaceMediaDataLoaded_persistentEnabled_periodicTrigger_notActive() {
- fakeFeatureFlags.set(MEDIA_RETAIN_RECOMMENDATIONS, true)
- val extras =
- Bundle().apply {
- putString("package_name", PACKAGE_NAME)
- putParcelable("dismiss_intent", DISMISS_INTENT)
- putString(EXTRA_KEY_TRIGGER_SOURCE, EXTRA_VALUE_TRIGGER_PERIODIC)
- }
- whenever(mediaSmartspaceBaseAction.extras).thenReturn(extras)
-
- smartspaceMediaDataProvider.onTargetsAvailable(listOf(mediaSmartspaceTarget))
- val instanceId = instanceIdSequence.lastInstanceId
-
- verify(listener)
- .onSmartspaceMediaDataLoaded(
- eq(KEY_MEDIA_SMARTSPACE),
- eq(
- SmartspaceMediaData(
- targetId = KEY_MEDIA_SMARTSPACE,
- isActive = false,
- packageName = PACKAGE_NAME,
- cardAction = mediaSmartspaceBaseAction,
- recommendations = validRecommendationList,
- dismissIntent = DISMISS_INTENT,
- headphoneConnectionTimeMillis = SMARTSPACE_CREATION_TIME,
- instanceId = InstanceId.fakeInstanceId(instanceId),
- expiryTimeMs = SMARTSPACE_EXPIRY_TIME,
- )
- ),
- eq(false),
- )
- }
-
- @Test
- fun testOnSmartspaceMediaDataLoaded_persistentEnabled_noTargets_inactive() {
- fakeFeatureFlags.set(MEDIA_RETAIN_RECOMMENDATIONS, true)
-
- smartspaceMediaDataProvider.onTargetsAvailable(listOf(mediaSmartspaceTarget))
- val instanceId = instanceIdSequence.lastInstanceId
-
- smartspaceMediaDataProvider.onTargetsAvailable(listOf())
- uiExecutor.advanceClockToLast()
- uiExecutor.runAllReady()
-
- verify(listener)
- .onSmartspaceMediaDataLoaded(
- eq(KEY_MEDIA_SMARTSPACE),
- eq(
- SmartspaceMediaData(
- targetId = KEY_MEDIA_SMARTSPACE,
- isActive = false,
- packageName = PACKAGE_NAME,
- cardAction = mediaSmartspaceBaseAction,
- recommendations = validRecommendationList,
- dismissIntent = DISMISS_INTENT,
- headphoneConnectionTimeMillis = SMARTSPACE_CREATION_TIME,
- instanceId = InstanceId.fakeInstanceId(instanceId),
- expiryTimeMs = SMARTSPACE_EXPIRY_TIME,
- )
- ),
- eq(false),
- )
- verify(listener, never()).onSmartspaceMediaDataRemoved(eq(KEY_MEDIA_SMARTSPACE), eq(false))
- }
-
- @Test
- fun testSetRecommendationInactive_notifiesListeners() {
- fakeFeatureFlags.set(MEDIA_RETAIN_RECOMMENDATIONS, true)
-
- smartspaceMediaDataProvider.onTargetsAvailable(listOf(mediaSmartspaceTarget))
- val instanceId = instanceIdSequence.lastInstanceId
-
- mediaDataProcessor.setRecommendationInactive(KEY_MEDIA_SMARTSPACE)
- uiExecutor.advanceClockToLast()
- uiExecutor.runAllReady()
-
- verify(listener)
- .onSmartspaceMediaDataLoaded(
- eq(KEY_MEDIA_SMARTSPACE),
- eq(
- SmartspaceMediaData(
- targetId = KEY_MEDIA_SMARTSPACE,
- isActive = false,
- packageName = PACKAGE_NAME,
- cardAction = mediaSmartspaceBaseAction,
- recommendations = validRecommendationList,
- dismissIntent = DISMISS_INTENT,
- headphoneConnectionTimeMillis = SMARTSPACE_CREATION_TIME,
- instanceId = InstanceId.fakeInstanceId(instanceId),
- expiryTimeMs = SMARTSPACE_EXPIRY_TIME,
- )
- ),
- eq(false),
- )
- }
-
- @Test
- fun testOnSmartspaceMediaDataLoaded_settingDisabled_doesNothing() {
- // WHEN media recommendation setting is off
- settings.putInt(Settings.Secure.MEDIA_CONTROLS_RECOMMENDATION, 0)
- testScope.runCurrent()
-
- smartspaceMediaDataProvider.onTargetsAvailable(listOf(mediaSmartspaceTarget))
-
- // THEN smartspace signal is ignored
- verify(listener, never())
- .onSmartspaceMediaDataLoaded(anyObject(), anyObject(), anyBoolean())
- }
-
- @Test
- fun testMediaRecommendationDisabled_removesSmartspaceData() {
- // GIVEN a media recommendation card is present
- smartspaceMediaDataProvider.onTargetsAvailable(listOf(mediaSmartspaceTarget))
- verify(listener)
- .onSmartspaceMediaDataLoaded(eq(KEY_MEDIA_SMARTSPACE), anyObject(), anyBoolean())
-
- // WHEN the media recommendation setting is turned off
- settings.putInt(Settings.Secure.MEDIA_CONTROLS_RECOMMENDATION, 0)
- testScope.runCurrent()
-
- // THEN listeners are notified
- uiExecutor.advanceClockToLast()
- foregroundExecutor.advanceClockToLast()
- uiExecutor.runAllReady()
- foregroundExecutor.runAllReady()
- verify(listener).onSmartspaceMediaDataRemoved(eq(KEY_MEDIA_SMARTSPACE), eq(true))
- }
-
- @Test
fun testOnMediaDataChanged_updatesLastActiveTime() {
val currentTime = clock.elapsedRealtime()
addNotificationAndLoad()
diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/domain/interactor/KeyguardQuickAffordanceInteractorKosmos.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/domain/interactor/KeyguardQuickAffordanceInteractorKosmos.kt
index 3b1199a..ba64ed7 100644
--- a/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/domain/interactor/KeyguardQuickAffordanceInteractorKosmos.kt
+++ b/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/domain/interactor/KeyguardQuickAffordanceInteractorKosmos.kt
@@ -18,6 +18,7 @@
import android.app.admin.devicePolicyManager
import android.content.applicationContext
+import android.view.accessibility.AccessibilityManager
import com.android.internal.widget.lockPatternUtils
import com.android.keyguard.logging.KeyguardQuickAffordancesLogger
import com.android.systemui.animation.dialogTransitionAnimator
@@ -54,6 +55,7 @@
dockManager = dockManager,
biometricSettingsRepository = biometricSettingsRepository,
communalSettingsInteractor = communalSettingsInteractor,
+ accessibilityManager = mock<AccessibilityManager>(),
backgroundDispatcher = testDispatcher,
appContext = applicationContext,
sceneInteractor = { sceneInteractor },
diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/media/controls/domain/pipeline/MediaDataProcessorKosmos.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/media/controls/domain/pipeline/MediaDataProcessorKosmos.kt
index 174e653..fcaad6b 100644
--- a/packages/SystemUI/tests/utils/src/com/android/systemui/media/controls/domain/pipeline/MediaDataProcessorKosmos.kt
+++ b/packages/SystemUI/tests/utils/src/com/android/systemui/media/controls/domain/pipeline/MediaDataProcessorKosmos.kt
@@ -31,9 +31,7 @@
import com.android.systemui.media.controls.util.fakeMediaControllerFactory
import com.android.systemui.media.controls.util.mediaFlags
import com.android.systemui.media.controls.util.mediaUiEventLogger
-import com.android.systemui.plugins.activityStarter
import com.android.systemui.util.Utils
-import com.android.systemui.util.settings.fakeSettings
import com.android.systemui.util.time.systemClock
val Kosmos.mediaDataProcessor by
@@ -49,12 +47,10 @@
mediaControllerFactory = fakeMediaControllerFactory,
broadcastDispatcher = broadcastDispatcher,
dumpManager = dumpManager,
- activityStarter = activityStarter,
smartspaceMediaDataProvider = SmartspaceMediaDataProvider(),
useMediaResumption = Utils.useMediaResumption(applicationContext),
useQsMediaPlayer = Utils.useQsMediaPlayer(applicationContext),
systemClock = systemClock,
- secureSettings = fakeSettings,
mediaFlags = mediaFlags,
logger = mediaUiEventLogger,
smartspaceManager = SmartspaceManager(applicationContext),
diff --git a/services/companion/java/com/android/server/companion/CompanionDeviceShellCommand.java b/services/companion/java/com/android/server/companion/CompanionDeviceShellCommand.java
index 2804945..3508f2f 100644
--- a/services/companion/java/com/android/server/companion/CompanionDeviceShellCommand.java
+++ b/services/companion/java/com/android/server/companion/CompanionDeviceShellCommand.java
@@ -106,7 +106,7 @@
boolean selfManaged = getNextBooleanArg();
final MacAddress macAddress = MacAddress.fromString(address);
mAssociationRequestsProcessor.createAssociation(userId, packageName, macAddress,
- deviceProfile, deviceProfile, /* associatedDevice */ null, false,
+ deviceProfile, deviceProfile, /* associatedDevice */ null, selfManaged,
/* callback */ null, /* resultReceiver */ null, /* deviceIcon */ null);
}
break;
diff --git a/services/companion/java/com/android/server/companion/virtual/VirtualDeviceManagerService.java b/services/companion/java/com/android/server/companion/virtual/VirtualDeviceManagerService.java
index 0b335d3..4dd8b14 100644
--- a/services/companion/java/com/android/server/companion/virtual/VirtualDeviceManagerService.java
+++ b/services/companion/java/com/android/server/companion/virtual/VirtualDeviceManagerService.java
@@ -820,13 +820,12 @@
@Override
public void onAuthenticationPrompt(int uid) {
- synchronized (mVirtualDeviceManagerLock) {
- for (int i = 0; i < mVirtualDevices.size(); i++) {
- VirtualDeviceImpl device = mVirtualDevices.valueAt(i);
- device.showToastWhereUidIsRunning(uid,
- R.string.app_streaming_blocked_message_for_fingerprint_dialog,
- Toast.LENGTH_LONG, Looper.getMainLooper());
- }
+ ArrayList<VirtualDeviceImpl> virtualDevicesSnapshot = getVirtualDevicesSnapshot();
+ for (int i = 0; i < virtualDevicesSnapshot.size(); i++) {
+ VirtualDeviceImpl device = virtualDevicesSnapshot.get(i);
+ device.showToastWhereUidIsRunning(uid,
+ R.string.app_streaming_blocked_message_for_fingerprint_dialog,
+ Toast.LENGTH_LONG, Looper.getMainLooper());
}
}
diff --git a/services/core/java/com/android/server/am/SettingsToPropertiesMapper.java b/services/core/java/com/android/server/am/SettingsToPropertiesMapper.java
index d3a5254..a54a663 100644
--- a/services/core/java/com/android/server/am/SettingsToPropertiesMapper.java
+++ b/services/core/java/com/android/server/am/SettingsToPropertiesMapper.java
@@ -16,12 +16,23 @@
package com.android.server.am;
+import static com.android.aconfig_new_storage.Flags.enableAconfigStorageDaemon;
+import static com.android.aconfig_new_storage.Flags.enableAconfigdFromMainline;
+import static com.android.aconfig_new_storage.Flags.supportClearLocalOverridesImmediately;
+import static com.android.aconfig_new_storage.Flags.supportImmediateLocalOverrides;
+
+import static java.util.concurrent.Executors.newSingleThreadScheduledExecutor;
+
+import android.aconfigd.Aconfigd.StorageRequestMessage;
+import android.aconfigd.Aconfigd.StorageRequestMessages;
+import android.aconfigd.Aconfigd.StorageReturnMessage;
+import android.aconfigd.Aconfigd.StorageReturnMessages;
import android.annotation.NonNull;
import android.content.ContentResolver;
import android.database.ContentObserver;
-import android.net.Uri;
-import android.net.LocalSocketAddress;
import android.net.LocalSocket;
+import android.net.LocalSocketAddress;
+import android.net.Uri;
import android.os.AsyncTask;
import android.os.Build;
import android.os.SystemProperties;
@@ -35,28 +46,13 @@
import com.android.internal.annotations.VisibleForTesting;
import com.android.providers.settings.Flags;
-import android.aconfigd.Aconfigd.StorageRequestMessage;
-import android.aconfigd.Aconfigd.StorageRequestMessages;
-import android.aconfigd.Aconfigd.StorageReturnMessage;
-import android.aconfigd.Aconfigd.StorageReturnMessages;
-import static com.android.aconfig_new_storage.Flags.enableAconfigStorageDaemon;
-import static com.android.aconfig_new_storage.Flags.supportImmediateLocalOverrides;
-import static com.android.aconfig_new_storage.Flags.supportClearLocalOverridesImmediately;
-import static com.android.aconfig_new_storage.Flags.enableAconfigdFromMainline;
-
+import java.io.BufferedReader;
import java.io.DataInputStream;
import java.io.DataOutputStream;
-import java.io.BufferedReader;
import java.io.File;
import java.io.FileReader;
import java.io.IOException;
import java.util.HashSet;
-import java.util.HashMap;
-import java.util.Map;
-import java.util.List;
-import java.util.ArrayList;
-import java.util.Set;
-import static java.util.concurrent.Executors.newSingleThreadScheduledExecutor;
/**
* Maps system settings to system properties.
@@ -271,6 +267,7 @@
"wear_sysui",
"wear_system_managed_surfaces",
"wear_watchfaces",
+ "web_apps_on_chromeos_and_android",
"window_surfaces",
"windowing_frontend",
"xr",
diff --git a/services/core/java/com/android/server/appop/DiscreteOpsDbHelper.java b/services/core/java/com/android/server/appop/DiscreteOpsDbHelper.java
index 695032e..86f5d9b 100644
--- a/services/core/java/com/android/server/appop/DiscreteOpsDbHelper.java
+++ b/services/core/java/com/android/server/appop/DiscreteOpsDbHelper.java
@@ -27,9 +27,13 @@
import android.database.sqlite.SQLiteOpenHelper;
import android.database.sqlite.SQLiteRawStatement;
import android.os.Environment;
+import android.os.SystemClock;
+import android.permission.flags.Flags;
import android.util.IntArray;
import android.util.Slog;
+import com.android.internal.util.FrameworkStatsLog;
+
import java.io.File;
import java.util.ArrayList;
import java.util.List;
@@ -76,6 +80,10 @@
if (opEvents.isEmpty()) {
return;
}
+ long startTime = 0;
+ if (Flags.sqliteDiscreteOpEventLoggingEnabled()) {
+ startTime = SystemClock.elapsedRealtime();
+ }
SQLiteDatabase db = getWritableDatabase();
// TODO (b/383157289) what if database is busy and can't start a transaction? will read
@@ -117,6 +125,11 @@
+ " file size (bytes) : " + getDatabaseFile().length(), exception);
}
}
+ if (Flags.sqliteDiscreteOpEventLoggingEnabled()) {
+ long timeTaken = SystemClock.elapsedRealtime() - startTime;
+ FrameworkStatsLog.write(FrameworkStatsLog.SQLITE_DISCRETE_OP_EVENT_REPORTED,
+ -1, timeTaken, getDatabaseFile().length());
+ }
}
private void bindTextOrNull(SQLiteRawStatement statement, int index, @Nullable String text) {
@@ -181,7 +194,10 @@
uidFilter, packageNameFilter,
attributionTagFilter, opCodesFilter, opFlagsFilter);
String sql = buildSql(conditions, orderByColumn, limit);
-
+ long startTime = 0;
+ if (Flags.sqliteDiscreteOpEventLoggingEnabled()) {
+ startTime = SystemClock.elapsedRealtime();
+ }
SQLiteDatabase db = getReadableDatabase();
List<DiscreteOpsSqlRegistry.DiscreteOp> results = new ArrayList<>();
db.beginTransactionReadOnly();
@@ -225,6 +241,11 @@
} finally {
db.endTransaction();
}
+ if (Flags.sqliteDiscreteOpEventLoggingEnabled()) {
+ long timeTaken = SystemClock.elapsedRealtime() - startTime;
+ FrameworkStatsLog.write(FrameworkStatsLog.SQLITE_DISCRETE_OP_EVENT_REPORTED,
+ timeTaken, -1, getDatabaseFile().length());
+ }
return results;
}
diff --git a/services/core/java/com/android/server/display/DisplayManagerService.java b/services/core/java/com/android/server/display/DisplayManagerService.java
index 3350109..3598b9b 100644
--- a/services/core/java/com/android/server/display/DisplayManagerService.java
+++ b/services/core/java/com/android/server/display/DisplayManagerService.java
@@ -29,6 +29,7 @@
import static android.Manifest.permission.RESTRICT_DISPLAY_MODES;
import static android.app.ActivityManager.RunningAppProcessInfo.IMPORTANCE_CACHED;
import static android.app.ActivityManager.RunningAppProcessInfo.IMPORTANCE_GONE;
+import static android.app.ActivityManager.RunningAppProcessInfo.IMPORTANCE_VISIBLE;
import static android.hardware.display.DisplayManagerGlobal.InternalEventFlag;
import static android.hardware.display.DisplayManager.VIRTUAL_DISPLAY_FLAG_ALWAYS_UNLOCKED;
import static android.hardware.display.DisplayManager.VIRTUAL_DISPLAY_FLAG_AUTO_MIRROR;
@@ -380,6 +381,8 @@
private final SparseArray<DisplayPowerController> mDisplayPowerControllers =
new SparseArray<>();
+ private int mMaxImportanceForRRCallbacks = IMPORTANCE_VISIBLE;
+
/** {@link DisplayBlanker} used by all {@link DisplayPowerController}s. */
private final DisplayBlanker mDisplayBlanker = new DisplayBlanker() {
// Synchronized to avoid race conditions when updating multiple display states.
@@ -3636,6 +3639,7 @@
pw.println(" mWifiDisplayScanRequestCount=" + mWifiDisplayScanRequestCount);
pw.println(" mStableDisplaySize=" + mStableDisplaySize);
pw.println(" mMinimumBrightnessCurve=" + mMinimumBrightnessCurve);
+ pw.println(" mMaxImportanceForRRCallbacks=" + mMaxImportanceForRRCallbacks);
if (mUserPreferredMode != null) {
pw.println(" mUserPreferredMode=" + mUserPreferredMode);
@@ -3764,6 +3768,10 @@
}
}
+ void overrideMaxImportanceForRRCallbacks(int importance) {
+ mMaxImportanceForRRCallbacks = importance;
+ }
+
boolean requestDisplayPower(int displayId, int requestedState) {
synchronized (mSyncRoot) {
final var display = mLogicalDisplayMapper.getDisplayLocked(displayId);
@@ -4147,6 +4155,18 @@
mPackageName = packageNames == null ? null : packageNames[0];
}
+ public boolean shouldReceiveRefreshRateWithChangeUpdate(int event) {
+ if (mFlags.isRefreshRateEventForForegroundAppsEnabled()
+ && event == DisplayManagerGlobal.EVENT_DISPLAY_REFRESH_RATE_CHANGED) {
+ int procState = mActivityManagerInternal.getUidProcessState(mUid);
+ int importance = ActivityManager.RunningAppProcessInfo
+ .procStateToImportance(procState);
+ return importance <= mMaxImportanceForRRCallbacks || mUid <= Process.SYSTEM_UID;
+ }
+
+ return true;
+ }
+
public void updateEventFlagsMask(@InternalEventFlag long internalEventFlag) {
mInternalEventFlagsMask.set(internalEventFlag);
}
@@ -4254,6 +4274,11 @@
}
}
+ if (!shouldReceiveRefreshRateWithChangeUpdate(event)) {
+ // The client is not visible to the user and is not a system service, so do nothing.
+ return true;
+ }
+
try {
transmitDisplayEvent(displayId, event);
return true;
@@ -4405,6 +4430,11 @@
+ displayEvent.displayId + "/"
+ displayEvent.event + " to " + mUid + "/" + mPid);
}
+
+ if (!shouldReceiveRefreshRateWithChangeUpdate(displayEvent.event)) {
+ continue;
+ }
+
transmitDisplayEvent(displayEvent.displayId, displayEvent.event);
}
return true;
diff --git a/services/core/java/com/android/server/display/DisplayManagerShellCommand.java b/services/core/java/com/android/server/display/DisplayManagerShellCommand.java
index f6b2591..e23756f 100644
--- a/services/core/java/com/android/server/display/DisplayManagerShellCommand.java
+++ b/services/core/java/com/android/server/display/DisplayManagerShellCommand.java
@@ -112,6 +112,8 @@
return requestDisplayPower(Display.STATE_UNKNOWN);
case "power-off":
return requestDisplayPower(Display.STATE_OFF);
+ case "override-max-importance-rr-callbacks":
+ return overrideMaxImportanceForRRCallbacks();
default:
return handleDefaultCommands(cmd);
}
@@ -631,4 +633,21 @@
mService.requestDisplayPower(displayId, state);
return 0;
}
+
+ private int overrideMaxImportanceForRRCallbacks() {
+ final String importanceString = getNextArg();
+ if (importanceString == null) {
+ getErrPrintWriter().println("Error: no importance specified");
+ return 1;
+ }
+ final int importance;
+ try {
+ importance = Integer.parseInt(importanceString);
+ } catch (NumberFormatException e) {
+ getErrPrintWriter().println("Error: invalid importance: '" + importanceString + "'");
+ return 1;
+ }
+ mService.overrideMaxImportanceForRRCallbacks(importance);
+ return 0;
+ }
}
diff --git a/services/core/java/com/android/server/display/feature/DisplayManagerFlags.java b/services/core/java/com/android/server/display/feature/DisplayManagerFlags.java
index 72306ae..d435144 100644
--- a/services/core/java/com/android/server/display/feature/DisplayManagerFlags.java
+++ b/services/core/java/com/android/server/display/feature/DisplayManagerFlags.java
@@ -268,6 +268,11 @@
Flags::framerateOverrideTriggersRrCallbacks
);
+ private final FlagState mRefreshRateEventForForegroundApps = new FlagState(
+ Flags.FLAG_REFRESH_RATE_EVENT_FOR_FOREGROUND_APPS,
+ Flags::refreshRateEventForForegroundApps
+ );
+
/**
* @return {@code true} if 'port' is allowed in display layout configuration file.
*/
@@ -579,6 +584,14 @@
/**
+ * @return {@code true} if the flag for sending refresh rate events only for the apps in
+ * foreground is enabled
+ */
+ public boolean isRefreshRateEventForForegroundAppsEnabled() {
+ return mRefreshRateEventForForegroundApps.isEnabled();
+ }
+
+ /**
* dumps all flagstates
* @param pw printWriter
*/
@@ -634,7 +647,7 @@
pw.println(" " + mEnableDisplayContentModeManagementFlagState);
pw.println(" " + mBaseDensityForExternalDisplays);
pw.println(" " + mFramerateOverrideTriggersRrCallbacks);
-
+ pw.println(" " + mRefreshRateEventForForegroundApps);
}
private static class FlagState {
diff --git a/services/core/java/com/android/server/display/feature/display_flags.aconfig b/services/core/java/com/android/server/display/feature/display_flags.aconfig
index 1cd0505..63cd2d7 100644
--- a/services/core/java/com/android/server/display/feature/display_flags.aconfig
+++ b/services/core/java/com/android/server/display/feature/display_flags.aconfig
@@ -486,6 +486,17 @@
description: "Feature flag to trigger the RR callbacks when framerate overridding happens."
bug: "390113266"
is_fixed_read_only: true
+ metadata {
+ purpose: PURPOSE_BUGFIX
+ }
+}
+
+flag {
+ name: "refresh_rate_event_for_foreground_apps"
+ namespace: "display_manager"
+ description: "Send Refresh Rate events only for the apps in foreground."
+ bug: "390107600"
+ is_fixed_read_only: true
metadata {
purpose: PURPOSE_BUGFIX
}
diff --git a/services/core/java/com/android/server/pm/InstallPackageHelper.java b/services/core/java/com/android/server/pm/InstallPackageHelper.java
index b043d13..8eb5b6f 100644
--- a/services/core/java/com/android/server/pm/InstallPackageHelper.java
+++ b/services/core/java/com/android/server/pm/InstallPackageHelper.java
@@ -863,6 +863,9 @@
// restore if appropriate, then pass responsibility back to the
// Package Manager to run the post-install observer callbacks
// and broadcasts.
+ // Note: MUST close freezer before backup/restore, otherwise test
+ // of CtsBackupHostTestCases will fail.
+ request.closeFreezer();
doRestore = performBackupManagerRestore(userId, token, request);
}
diff --git a/services/core/java/com/android/server/power/OWNERS b/services/core/java/com/android/server/power/OWNERS
index c1fad33..a1531a8 100644
--- a/services/core/java/com/android/server/power/OWNERS
+++ b/services/core/java/com/android/server/power/OWNERS
@@ -2,6 +2,8 @@
santoscordon@google.com
petsjonkin@google.com
brup@google.com
+flc@google.com
+wilczynskip@google.com
per-file ThermalManagerService.java=file:/THERMAL_OWNERS
per-file LowPowerStandbyController.java=qingxun@google.com
diff --git a/services/devicepolicy/java/com/android/server/devicepolicy/ActiveAdmin.java b/services/devicepolicy/java/com/android/server/devicepolicy/ActiveAdmin.java
index 76d16e1..a81a0b3 100644
--- a/services/devicepolicy/java/com/android/server/devicepolicy/ActiveAdmin.java
+++ b/services/devicepolicy/java/com/android/server/devicepolicy/ActiveAdmin.java
@@ -73,9 +73,6 @@
class ActiveAdmin {
- private final int userId;
- public final boolean isPermissionBased;
-
private static final String TAG_DISABLE_KEYGUARD_FEATURES = "disable-keyguard-features";
private static final String TAG_TEST_ONLY_ADMIN = "test-only-admin";
private static final String TAG_DISABLE_CAMERA = "disable-camera";
@@ -364,23 +361,8 @@
private static final int PROVISIONING_CONTEXT_LENGTH_LIMIT = 1000;
ActiveAdmin(DeviceAdminInfo info, boolean isParent) {
- this.userId = -1;
this.info = info;
this.isParent = isParent;
- this.isPermissionBased = false;
- }
-
- ActiveAdmin(int userId, boolean permissionBased) {
- if (Flags.activeAdminCleanup()) {
- throw new UnsupportedOperationException("permission based admin no longer supported");
- }
- if (permissionBased == false) {
- throw new IllegalArgumentException("Can only pass true for permissionBased admin");
- }
- this.userId = userId;
- this.isPermissionBased = permissionBased;
- this.isParent = false;
- this.info = null;
}
ActiveAdmin getParentActiveAdmin() {
@@ -397,16 +379,10 @@
}
int getUid() {
- if (isPermissionBased) {
- return -1;
- }
return info.getActivityInfo().applicationInfo.uid;
}
public UserHandle getUserHandle() {
- if (isPermissionBased) {
- return UserHandle.of(userId);
- }
return UserHandle.of(UserHandle.getUserId(info.getActivityInfo().applicationInfo.uid));
}
diff --git a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyData.java b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyData.java
index c937e10..89c8b56 100644
--- a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyData.java
+++ b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyData.java
@@ -21,7 +21,6 @@
import android.annotation.UserIdInt;
import android.app.admin.DeviceAdminInfo;
import android.app.admin.DevicePolicyManager;
-import android.app.admin.flags.Flags;
import android.content.ComponentName;
import android.os.FileUtils;
import android.os.PersistableBundle;
@@ -125,24 +124,6 @@
final ArrayList<ActiveAdmin> mAdminList = new ArrayList<>();
final ArrayList<ComponentName> mRemovingAdmins = new ArrayList<>();
- /**
- * @deprecated Do not use. Policies set by permission holders must go into DevicePolicyEngine.
- */
- @Deprecated
- ActiveAdmin mPermissionBasedAdmin;
-
- // Create or get the permission-based admin. The permission-based admin will not have a
- // DeviceAdminInfo or ComponentName.
- ActiveAdmin createOrGetPermissionBasedAdmin(int userId) {
- if (Flags.activeAdminCleanup()) {
- throw new UnsupportedOperationException("permission based admin no longer supported");
- }
- if (mPermissionBasedAdmin == null) {
- mPermissionBasedAdmin = new ActiveAdmin(userId, /* permissionBased= */ true);
- }
- return mPermissionBasedAdmin;
- }
-
// TODO(b/35385311): Keep track of metadata in TrustedCertificateStore instead.
final ArraySet<String> mAcceptedCaCertificates = new ArraySet<>();
@@ -282,12 +263,6 @@
}
}
- if (!Flags.activeAdminCleanup() && policyData.mPermissionBasedAdmin != null) {
- out.startTag(null, "permission-based-admin");
- policyData.mPermissionBasedAdmin.writeToXml(out);
- out.endTag(null, "permission-based-admin");
- }
-
if (policyData.mPasswordOwner >= 0) {
out.startTag(null, "password-owner");
out.attributeInt(null, "value", policyData.mPasswordOwner);
@@ -495,7 +470,6 @@
policy.mLockTaskPackages.clear();
policy.mAdminList.clear();
policy.mAdminMap.clear();
- policy.mPermissionBasedAdmin = null;
policy.mAffiliationIds.clear();
policy.mOwnerInstalledCaCerts.clear();
policy.mUserControlDisabledPackages = null;
@@ -523,11 +497,6 @@
} catch (RuntimeException e) {
Slogf.w(TAG, e, "Failed loading admin %s", name);
}
- } else if (!Flags.activeAdminCleanup() && "permission-based-admin".equals(tag)) {
-
- ActiveAdmin ap = new ActiveAdmin(policy.mUserId, /* permissionBased= */ true);
- ap.readFromXml(parser, /* overwritePolicies= */ false);
- policy.mPermissionBasedAdmin = ap;
} else if ("delegation".equals(tag)) {
// Parse delegation info.
final String delegatePackage = parser.getAttributeValue(null,
diff --git a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
index e960abd..4c2c858 100644
--- a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
+++ b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
@@ -3448,8 +3448,8 @@
EnforcingAdmin enforcingAdmin =
EnforcingAdmin.createEnterpriseEnforcingAdmin(
admin.info.getComponent(),
- admin.getUserHandle().getIdentifier(),
- admin);
+ admin.getUserHandle().getIdentifier()
+ );
mDevicePolicyEngine.setGlobalPolicy(
PolicyDefinition.SECURITY_LOGGING,
enforcingAdmin,
@@ -3692,8 +3692,8 @@
int userId = admin.getUserHandle().getIdentifier();
EnforcingAdmin enforcingAdmin = EnforcingAdmin.createEnterpriseEnforcingAdmin(
admin.info.getComponent(),
- userId,
- admin);
+ userId
+ );
Integer passwordComplexity = mDevicePolicyEngine.getLocalPolicySetByAdmin(
PolicyDefinition.PASSWORD_COMPLEXITY,
@@ -3985,8 +3985,7 @@
final int N = admins.size();
for (int i = 0; i < N; i++) {
ActiveAdmin admin = admins.get(i);
- if (((!Flags.activeAdminCleanup() && admin.isPermissionBased)
- || admin.info.usesPolicy(DeviceAdminInfo.USES_POLICY_EXPIRE_PASSWORD))
+ if ((admin.info.usesPolicy(DeviceAdminInfo.USES_POLICY_EXPIRE_PASSWORD))
&& admin.passwordExpirationTimeout > 0L
&& now >= admin.passwordExpirationDate - EXPIRATION_GRACE_PERIOD_MS
&& admin.passwordExpirationDate > 0L) {
@@ -4167,10 +4166,10 @@
EnforcingAdmin oldAdmin =
EnforcingAdmin.createEnterpriseEnforcingAdmin(
- outgoingReceiver, userHandle, adminToTransfer);
+ outgoingReceiver, userHandle);
EnforcingAdmin newAdmin =
EnforcingAdmin.createEnterpriseEnforcingAdmin(
- incomingReceiver, userHandle, adminToTransfer);
+ incomingReceiver, userHandle);
mDevicePolicyEngine.transferPolicies(oldAdmin, newAdmin);
@@ -4470,7 +4469,7 @@
}
mDevicePolicyEngine.removePoliciesForAdmin(
EnforcingAdmin.createEnterpriseEnforcingAdmin(
- adminReceiver, userHandle, admin));
+ adminReceiver, userHandle));
}
private boolean canSetPasswordQualityOnParent(String packageName, final CallerIdentity caller) {
@@ -4525,10 +4524,8 @@
who, DeviceAdminInfo.USES_POLICY_LIMIT_PASSWORD, parent);
if (Flags.unmanagedModeMigration()) {
- enforcingAdmin = EnforcingAdmin.createEnterpriseEnforcingAdmin(who,
- userId,
- getActiveAdminForCallerLocked(who,
- DeviceAdminInfo.USES_POLICY_LIMIT_PASSWORD));
+ getActiveAdminForCallerLocked(who, DeviceAdminInfo.USES_POLICY_LIMIT_PASSWORD);
+ enforcingAdmin = EnforcingAdmin.createEnterpriseEnforcingAdmin(who, userId);
}
// If setPasswordQuality is called on the parent, ensure that
// the primary admin does not have password complexity state (this is an
@@ -5584,17 +5581,13 @@
Preconditions.checkArgument(!calledOnParent || isProfileOwner(caller));
final ActiveAdmin activeAdmin;
- if (Flags.activeAdminCleanup()) {
- if (admin.hasAuthority(EnforcingAdmin.DPC_AUTHORITY)) {
- synchronized (getLockObject()) {
- activeAdmin = getActiveAdminUncheckedLocked(
- admin.getComponentName(), admin.getUserId());
- }
- } else {
- activeAdmin = null;
+ if (admin.hasAuthority(EnforcingAdmin.DPC_AUTHORITY)) {
+ synchronized (getLockObject()) {
+ activeAdmin = getActiveAdminUncheckedLocked(
+ admin.getComponentName(), admin.getUserId());
}
} else {
- activeAdmin = admin.getActiveAdmin();
+ activeAdmin = null;
}
// We require the caller to explicitly clear any password quality requirements set
@@ -6331,12 +6324,7 @@
caller.getPackageName(),
getAffectedUser(parent)
);
- if (Flags.activeAdminCleanup()) {
- adminComponent = enforcingAdmin.getComponentName();
- } else {
- ActiveAdmin admin = enforcingAdmin.getActiveAdmin();
- adminComponent = admin == null ? null : admin.info.getComponent();
- }
+ adminComponent = enforcingAdmin.getComponentName();
} else {
ActiveAdmin admin = getActiveAdminOrCheckPermissionForCallerLocked(
null,
@@ -7824,19 +7812,9 @@
calledByProfileOwnerOnOrgOwnedDevice, calledOnParentInstance);
}
- int userId;
- ActiveAdmin admin = null;
- if (Flags.activeAdminCleanup()) {
- userId = enforcingAdmin.getUserId();
- Slogf.i(LOG_TAG, "wipeDataWithReason(%s): admin=%s, user=%d", wipeReasonForUser,
- enforcingAdmin, userId);
- } else {
- admin = enforcingAdmin.getActiveAdmin();
- userId = admin != null ? admin.getUserHandle().getIdentifier()
- : caller.getUserId();
- Slogf.i(LOG_TAG, "wipeDataWithReason(%s): admin=%s, user=%d", wipeReasonForUser, admin,
- userId);
- }
+ int userId = enforcingAdmin.getUserId();
+ Slogf.i(LOG_TAG, "wipeDataWithReason(%s): admin=%s, user=%d", wipeReasonForUser,
+ enforcingAdmin, userId);
if (calledByProfileOwnerOnOrgOwnedDevice) {
// When wipeData is called on the parent instance, it implies wiping the entire device.
@@ -7858,38 +7836,14 @@
final String adminName;
final ComponentName adminComp;
- if (Flags.activeAdminCleanup()) {
- adminComp = enforcingAdmin.getComponentName();
- adminName = adminComp != null
- ? adminComp.flattenToShortString()
- : enforcingAdmin.getPackageName();
- event.setAdmin(enforcingAdmin.getPackageName());
- // Not including any HSUM handling here because the "else" branch in the "flag off"
- // case below is unreachable under normal circumstances and for permission-based
- // callers admin won't be null.
- } else {
- if (admin != null) {
- if (admin.isPermissionBased) {
- adminComp = null;
- adminName = caller.getPackageName();
- event.setAdmin(adminName);
- } else {
- adminComp = admin.info.getComponent();
- adminName = adminComp.flattenToShortString();
- event.setAdmin(adminComp);
- }
- } else {
- adminComp = null;
- adminName = mInjector.getPackageManager().getPackagesForUid(caller.getUid())[0];
- Slogf.i(LOG_TAG, "Logging wipeData() event admin as " + adminName);
- event.setAdmin(adminName);
- if (mInjector.userManagerIsHeadlessSystemUserMode()) {
- // On headless system user mode, the call is meant to factory reset the whole
- // device, otherwise the caller could simply remove the current user.
- userId = UserHandle.USER_SYSTEM;
- }
- }
- }
+ adminComp = enforcingAdmin.getComponentName();
+ adminName = adminComp != null
+ ? adminComp.flattenToShortString()
+ : enforcingAdmin.getPackageName();
+ event.setAdmin(enforcingAdmin.getPackageName());
+ // Not including any HSUM handling here because the "else" branch in the "flag off"
+ // case below is unreachable under normal circumstances and for permission-based
+ // callers admin won't be null.
event.write();
String internalReason = String.format(
@@ -8375,8 +8329,7 @@
List<ActiveAdmin> admins = getActiveAdminsForLockscreenPoliciesLocked(userHandle);
for (int i = 0; i < admins.size(); i++) {
ActiveAdmin admin = admins.get(i);
- if ((!Flags.activeAdminCleanup() && admin.isPermissionBased)
- || admin.info.usesPolicy(DeviceAdminInfo.USES_POLICY_EXPIRE_PASSWORD)) {
+ if (admin.info.usesPolicy(DeviceAdminInfo.USES_POLICY_EXPIRE_PASSWORD)) {
affectedUserIds.add(admin.getUserHandle().getIdentifier());
long timeout = admin.passwordExpirationTimeout;
admin.passwordExpirationDate =
@@ -8470,9 +8423,6 @@
*/
private int getUserIdToWipeForFailedPasswords(ActiveAdmin admin) {
final int userId = admin.getUserHandle().getIdentifier();
- if (!Flags.activeAdminCleanup() && admin.isPermissionBased) {
- return userId;
- }
final ComponentName component = admin.info.getComponent();
return isProfileOwnerOfOrganizationOwnedDevice(component, userId)
? getProfileParentId(userId) : userId;
@@ -10282,8 +10232,7 @@
setGlobalSettingDeviceOwnerType(DEVICE_OWNER_TYPE_DEFAULT);
mDevicePolicyEngine.removePoliciesForAdmin(
- EnforcingAdmin.createEnterpriseEnforcingAdmin(
- admin.info.getComponent(), userId, admin));
+ EnforcingAdmin.createEnterpriseEnforcingAdmin(admin.info.getComponent(), userId));
}
private void clearApplicationRestrictions(int userId) {
@@ -10433,8 +10382,7 @@
setNetworkLoggingActiveInternal(false);
mDevicePolicyEngine.removePoliciesForAdmin(
- EnforcingAdmin.createEnterpriseEnforcingAdmin(
- admin.info.getComponent(), userId, admin));
+ EnforcingAdmin.createEnterpriseEnforcingAdmin(admin.info.getComponent(), userId));
}
@Override
@@ -16449,8 +16397,7 @@
if (admin.mPasswordPolicy.quality < minPasswordQuality) {
return false;
}
- return (!Flags.activeAdminCleanup() && admin.isPermissionBased)
- || admin.info.usesPolicy(DeviceAdminInfo.USES_POLICY_LIMIT_PASSWORD);
+ return admin.info.usesPolicy(DeviceAdminInfo.USES_POLICY_LIMIT_PASSWORD);
}
@Override
@@ -20918,8 +20865,7 @@
if (profileOwner != null) {
EnforcingAdmin admin = EnforcingAdmin.createEnterpriseEnforcingAdmin(
profileOwner.info.getComponent(),
- profileUserId,
- profileOwner);
+ profileUserId);
mDevicePolicyEngine.setLocalPolicy(
PolicyDefinition.PERSONAL_APPS_SUSPENDED,
admin,
@@ -23517,27 +23463,6 @@
*
* @param callerPackageName The package name of the calling application.
* @param adminPolicy The admin policy that should grant holders permission.
- * @param permission The name of the permission being checked.
- * @param targetUserId The userId of the user which the caller needs permission to act on.
- * @throws SecurityException if the caller has not been granted the given permission,
- * the associated cross-user permission if the caller's user is different to the target user.
- */
- private void enforcePermission(String permission, int adminPolicy,
- String callerPackageName, int targetUserId) throws SecurityException {
- if (hasAdminPolicy(adminPolicy, callerPackageName)) {
- return;
- }
- enforcePermission(permission, callerPackageName, targetUserId);
- }
-
- /**
- * Checks if the calling process has been granted permission to apply a device policy on a
- * specific user.
- * The given permission will be checked along with its associated cross-user permission if it
- * exists and the target user is different to the calling user.
- *
- * @param callerPackageName The package name of the calling application.
- * @param adminPolicy The admin policy that should grant holders permission.
* @param permissions The names of the permissions being checked.
* @param targetUserId The userId of the user which the caller needs permission to act on.
* @throws SecurityException if the caller has not been granted the given permission,
@@ -23670,24 +23595,21 @@
ComponentName component;
synchronized (getLockObject()) {
if (who != null) {
- admin = getActiveAdminUncheckedLocked(who, userId);
component = who;
} else {
admin = getDeviceOrProfileOwnerAdminLocked(userId);
component = admin.info.getComponent();
}
}
- return EnforcingAdmin.createEnterpriseEnforcingAdmin(component, userId, admin);
+ return EnforcingAdmin.createEnterpriseEnforcingAdmin(component, userId);
}
- // Check for non-DPC active admins.
+ // Check for DA active admins.
admin = getActiveAdminForCaller(who, caller);
if (admin != null) {
- return EnforcingAdmin.createDeviceAdminEnforcingAdmin(admin.info.getComponent(), userId,
- admin);
+ return EnforcingAdmin.createDeviceAdminEnforcingAdmin(
+ admin.info.getComponent(), userId);
}
- admin = Flags.activeAdminCleanup()
- ? null : getUserData(userId).createOrGetPermissionBasedAdmin(userId);
- return EnforcingAdmin.createEnforcingAdmin(caller.getPackageName(), userId, admin);
+ return EnforcingAdmin.createEnforcingAdmin(caller.getPackageName(), userId);
}
private EnforcingAdmin getEnforcingAdminForPackage(@Nullable ComponentName who,
@@ -23699,19 +23621,17 @@
admin = getActiveAdminUncheckedLocked(who, userId);
}
if (admin != null) {
- return EnforcingAdmin.createEnterpriseEnforcingAdmin(who, userId, admin);
+ return EnforcingAdmin.createEnterpriseEnforcingAdmin(who, userId);
}
} else {
- // Check for non-DPC active admins.
+ // Check for DA active admins.
admin = getActiveAdminUncheckedLocked(who, userId);
if (admin != null) {
- return EnforcingAdmin.createDeviceAdminEnforcingAdmin(who, userId, admin);
+ return EnforcingAdmin.createDeviceAdminEnforcingAdmin(who, userId);
}
}
}
- admin = Flags.activeAdminCleanup()
- ? null : getUserData(userId).createOrGetPermissionBasedAdmin(userId);
- return EnforcingAdmin.createEnforcingAdmin(packageName, userId, admin);
+ return EnforcingAdmin.createEnforcingAdmin(packageName, userId);
}
private int getAffectedUser(boolean calledOnParent) {
@@ -24427,9 +24347,7 @@
&& admin.getParentActiveAdmin().disableScreenCapture))) {
EnforcingAdmin enforcingAdmin = EnforcingAdmin.createEnterpriseEnforcingAdmin(
- admin.info.getComponent(),
- admin.getUserHandle().getIdentifier(),
- admin);
+ admin.info.getComponent(), admin.getUserHandle().getIdentifier());
mDevicePolicyEngine.setGlobalPolicy(
PolicyDefinition.SCREEN_CAPTURE_DISABLED,
enforcingAdmin,
@@ -24442,8 +24360,7 @@
if (profileOwner != null && profileOwner.disableScreenCapture) {
EnforcingAdmin enforcingAdmin = EnforcingAdmin.createEnterpriseEnforcingAdmin(
profileOwner.info.getComponent(),
- profileOwner.getUserHandle().getIdentifier(),
- profileOwner);
+ profileOwner.getUserHandle().getIdentifier());
mDevicePolicyEngine.setLocalPolicy(
PolicyDefinition.SCREEN_CAPTURE_DISABLED,
enforcingAdmin,
@@ -24485,10 +24402,7 @@
private void setLockTaskPolicyInPolicyEngine(
ActiveAdmin admin, int userId, List<String> packages, int features) {
EnforcingAdmin enforcingAdmin =
- EnforcingAdmin.createEnterpriseEnforcingAdmin(
- admin.info.getComponent(),
- userId,
- admin);
+ EnforcingAdmin.createEnterpriseEnforcingAdmin(admin.info.getComponent(), userId);
mDevicePolicyEngine.setLocalPolicy(
PolicyDefinition.LOCK_TASK,
enforcingAdmin,
@@ -24503,9 +24417,7 @@
ActiveAdmin admin = getProfileOwnerOrDeviceOwnerLocked(userInfo.id);
if (admin != null) {
EnforcingAdmin enforcingAdmin = EnforcingAdmin.createEnterpriseEnforcingAdmin(
- admin.info.getComponent(),
- admin.getUserHandle().getIdentifier(),
- admin);
+ admin.info.getComponent(), admin.getUserHandle().getIdentifier());
if (admin.permittedInputMethods != null) {
mDevicePolicyEngine.setLocalPolicy(
PolicyDefinition.PERMITTED_INPUT_METHODS,
@@ -24536,9 +24448,7 @@
ActiveAdmin admin = getProfileOwnerOrDeviceOwnerLocked(userInfo.id);
if (admin != null) {
EnforcingAdmin enforcingAdmin = EnforcingAdmin.createEnterpriseEnforcingAdmin(
- admin.info.getComponent(),
- admin.getUserHandle().getIdentifier(),
- admin);
+ admin.info.getComponent(), admin.getUserHandle().getIdentifier());
for (String accountType : admin.accountTypesWithManagementDisabled) {
mDevicePolicyEngine.setLocalPolicy(
PolicyDefinition.ACCOUNT_MANAGEMENT_DISABLED(accountType),
@@ -24569,9 +24479,7 @@
ActiveAdmin admin = getProfileOwnerOrDeviceOwnerLocked(userInfo.id);
if (admin != null && admin.protectedPackages != null) {
EnforcingAdmin enforcingAdmin = EnforcingAdmin.createEnterpriseEnforcingAdmin(
- admin.info.getComponent(),
- admin.getUserHandle().getIdentifier(),
- admin);
+ admin.info.getComponent(), admin.getUserHandle().getIdentifier());
if (isDeviceOwner(admin)) {
mDevicePolicyEngine.setGlobalPolicy(
PolicyDefinition.USER_CONTROLLED_DISABLED_PACKAGES,
@@ -24599,10 +24507,8 @@
if (admin == null) continue;
ComponentName adminComponent = admin.info.getComponent();
int userId = userInfo.id;
- EnforcingAdmin enforcingAdmin = EnforcingAdmin.createEnterpriseEnforcingAdmin(
- adminComponent,
- userId,
- admin);
+ EnforcingAdmin enforcingAdmin =
+ EnforcingAdmin.createEnterpriseEnforcingAdmin(adminComponent, userId);
int ownerType;
if (isDeviceOwner(admin)) {
ownerType = OWNER_TYPE_DEVICE_OWNER;
@@ -24635,9 +24541,7 @@
ActiveAdmin admin = getProfileOwnerOrDeviceOwnerLocked(userInfo.id);
if (admin == null) continue;
EnforcingAdmin enforcingAdmin = EnforcingAdmin.createEnterpriseEnforcingAdmin(
- admin.info.getComponent(),
- userInfo.id,
- admin);
+ admin.info.getComponent(), userInfo.id);
runner.accept(admin, enforcingAdmin);
}
diff --git a/services/devicepolicy/java/com/android/server/devicepolicy/EnforcingAdmin.java b/services/devicepolicy/java/com/android/server/devicepolicy/EnforcingAdmin.java
index 5a0b079..aca3315 100644
--- a/services/devicepolicy/java/com/android/server/devicepolicy/EnforcingAdmin.java
+++ b/services/devicepolicy/java/com/android/server/devicepolicy/EnforcingAdmin.java
@@ -23,7 +23,6 @@
import android.app.admin.DpcAuthority;
import android.app.admin.RoleAuthority;
import android.app.admin.UnknownAuthority;
-import android.app.admin.flags.Flags;
import android.content.ComponentName;
import android.os.UserHandle;
@@ -80,36 +79,24 @@
private final int mUserId;
private final boolean mIsRoleAuthority;
private final boolean mIsSystemAuthority;
- private final ActiveAdmin mActiveAdmin;
- static EnforcingAdmin createEnforcingAdmin(@NonNull String packageName, int userId,
- ActiveAdmin admin) {
+ static EnforcingAdmin createEnforcingAdmin(@NonNull String packageName, int userId) {
Objects.requireNonNull(packageName);
- return new EnforcingAdmin(packageName, userId, admin);
+ return new EnforcingAdmin(packageName, userId);
}
static EnforcingAdmin createEnterpriseEnforcingAdmin(
@NonNull ComponentName componentName, int userId) {
Objects.requireNonNull(componentName);
return new EnforcingAdmin(
- componentName.getPackageName(), componentName, Set.of(DPC_AUTHORITY), userId,
- /* activeAdmin=*/ null);
+ componentName.getPackageName(), componentName, Set.of(DPC_AUTHORITY), userId);
}
- static EnforcingAdmin createEnterpriseEnforcingAdmin(
- @NonNull ComponentName componentName, int userId, ActiveAdmin activeAdmin) {
- Objects.requireNonNull(componentName);
- return new EnforcingAdmin(
- componentName.getPackageName(), componentName, Set.of(DPC_AUTHORITY), userId,
- activeAdmin);
- }
-
- static EnforcingAdmin createDeviceAdminEnforcingAdmin(ComponentName componentName, int userId,
- ActiveAdmin activeAdmin) {
+ static EnforcingAdmin createDeviceAdminEnforcingAdmin(ComponentName componentName, int userId) {
Objects.requireNonNull(componentName);
return new EnforcingAdmin(
componentName.getPackageName(), componentName, Set.of(DEVICE_ADMIN_AUTHORITY),
- userId, activeAdmin);
+ userId);
}
static EnforcingAdmin createSystemEnforcingAdmin(@NonNull String systemEntity) {
@@ -124,24 +111,20 @@
if (DpcAuthority.DPC_AUTHORITY.equals(authority)) {
return new EnforcingAdmin(
admin.getPackageName(), admin.getComponentName(),
- Set.of(DPC_AUTHORITY), admin.getUserHandle().getIdentifier(),
- /* activeAdmin = */ null);
+ Set.of(DPC_AUTHORITY), admin.getUserHandle().getIdentifier());
} else if (DeviceAdminAuthority.DEVICE_ADMIN_AUTHORITY.equals(authority)) {
return new EnforcingAdmin(
admin.getPackageName(), admin.getComponentName(),
- Set.of(DEVICE_ADMIN_AUTHORITY), admin.getUserHandle().getIdentifier(),
- /* activeAdmin = */ null);
+ Set.of(DEVICE_ADMIN_AUTHORITY), admin.getUserHandle().getIdentifier());
} else if (authority instanceof RoleAuthority roleAuthority) {
return new EnforcingAdmin(
admin.getPackageName(), admin.getComponentName(),
Set.of(DEVICE_ADMIN_AUTHORITY), admin.getUserHandle().getIdentifier(),
- /* activeAdmin = */ null,
/* isRoleAuthority = */ true);
}
// TODO(b/324899199): Consider supporting android.app.admin.SystemAuthority.
return new EnforcingAdmin(admin.getPackageName(), admin.getComponentName(),
- Set.of(), admin.getUserHandle().getIdentifier(),
- /* activeAdmin = */ null);
+ Set.of(), admin.getUserHandle().getIdentifier());
}
static String getRoleAuthorityOf(String roleName) {
@@ -167,7 +150,7 @@
private EnforcingAdmin(
String packageName, @Nullable ComponentName componentName, Set<String> authorities,
- int userId, @Nullable ActiveAdmin activeAdmin) {
+ int userId) {
Objects.requireNonNull(packageName);
Objects.requireNonNull(authorities);
@@ -179,10 +162,9 @@
mComponentName = componentName;
mAuthorities = new HashSet<>(authorities);
mUserId = userId;
- mActiveAdmin = activeAdmin;
}
- private EnforcingAdmin(String packageName, int userId, ActiveAdmin activeAdmin) {
+ private EnforcingAdmin(String packageName, int userId) {
Objects.requireNonNull(packageName);
// Only role authorities use this constructor.
@@ -194,7 +176,6 @@
mComponentName = null;
// authorities will be loaded when needed
mAuthorities = null;
- mActiveAdmin = activeAdmin;
}
/** Constructor for System authorities. */
@@ -210,12 +191,11 @@
mUserId = UserHandle.USER_SYSTEM;
mComponentName = null;
mAuthorities = getSystemAuthority(systemEntity);
- mActiveAdmin = null;
}
private EnforcingAdmin(
String packageName, @Nullable ComponentName componentName, Set<String> authorities,
- int userId, @Nullable ActiveAdmin activeAdmin, boolean isRoleAuthority) {
+ int userId, boolean isRoleAuthority) {
Objects.requireNonNull(packageName);
Objects.requireNonNull(authorities);
@@ -226,7 +206,6 @@
mComponentName = componentName;
mAuthorities = new HashSet<>(authorities);
mUserId = userId;
- mActiveAdmin = activeAdmin;
}
private static Set<String> getRoleAuthoritiesOrDefault(String packageName, int userId) {
@@ -295,14 +274,6 @@
}
@Nullable
- public ActiveAdmin getActiveAdmin() {
- if (Flags.activeAdminCleanup()) {
- throw new UnsupportedOperationException("getActiveAdmin() no longer supported");
- }
- return mActiveAdmin;
- }
-
- @Nullable
ComponentName getComponentName() {
return mComponentName;
}
@@ -419,7 +390,7 @@
return null;
}
// TODO(b/281697976): load active admin
- return new EnforcingAdmin(packageName, userId, null);
+ return new EnforcingAdmin(packageName, userId);
} else if (isSystemAuthority) {
if (systemEntity == null) {
Slogf.wtf(TAG, "Error parsing EnforcingAdmin with SystemAuthority, "
@@ -439,7 +410,7 @@
? null : new ComponentName(packageName, className);
Set<String> authorities = Set.of(authoritiesStr.split(ATTR_AUTHORITIES_SEPARATOR));
// TODO(b/281697976): load active admin
- return new EnforcingAdmin(packageName, componentName, authorities, userId, null);
+ return new EnforcingAdmin(packageName, componentName, authorities, userId);
}
}
diff --git a/services/tests/displayservicetests/src/com/android/server/display/DisplayManagerServiceTest.java b/services/tests/displayservicetests/src/com/android/server/display/DisplayManagerServiceTest.java
index 8e4d8ed..e8b28ac 100644
--- a/services/tests/displayservicetests/src/com/android/server/display/DisplayManagerServiceTest.java
+++ b/services/tests/displayservicetests/src/com/android/server/display/DisplayManagerServiceTest.java
@@ -23,6 +23,7 @@
import static android.Manifest.permission.CONTROL_DISPLAY_BRIGHTNESS;
import static android.Manifest.permission.MANAGE_DISPLAYS;
import static android.Manifest.permission.MODIFY_USER_PREFERRED_DISPLAY_MODE;
+import static android.app.ActivityManager.PROCESS_STATE_TRANSIENT_BACKGROUND;
import static android.hardware.display.DisplayManager.SWITCHING_TYPE_NONE;
import static android.hardware.display.DisplayManager.VIRTUAL_DISPLAY_FLAG_ALWAYS_UNLOCKED;
import static android.hardware.display.DisplayManager.VIRTUAL_DISPLAY_FLAG_AUTO_MIRROR;
@@ -2344,6 +2345,29 @@
callback.clear();
}
+ @Test
+ public void test_doesNotNotifyRefreshRateChanged_whenAppInBackground() {
+ when(mMockFlags.isRefreshRateEventForForegroundAppsEnabled()).thenReturn(true);
+ DisplayManagerService displayManager =
+ new DisplayManagerService(mContext, mBasicInjector);
+ DisplayManagerService.BinderService displayManagerBinderService =
+ displayManager.new BinderService();
+ displayManager.windowManagerAndInputReady();
+ registerDefaultDisplays(displayManager);
+ displayManager.onBootPhase(SystemService.PHASE_WAIT_FOR_DEFAULT_DISPLAY);
+
+ FakeDisplayDevice displayDevice = createFakeDisplayDevice(displayManager, new float[]{60f});
+ FakeDisplayManagerCallback callback = registerDisplayListenerCallback(displayManager,
+ displayManagerBinderService, displayDevice);
+
+ when(mMockActivityManagerInternal.getUidProcessState(Process.myUid()))
+ .thenReturn(PROCESS_STATE_TRANSIENT_BACKGROUND);
+ updateRenderFrameRate(displayManager, displayDevice, 30f);
+ waitForIdleHandler(displayManager.getDisplayHandler());
+ assertEquals(0, callback.receivedEvents().size());
+ callback.clear();
+ }
+
/**
* Tests that the DisplayInfo is updated correctly with a render frame rate
*/
diff --git a/services/tests/mockingservicestests/src/com/android/server/power/ScreenUndimDetectorTest.java b/services/tests/mockingservicestests/src/com/android/server/power/ScreenUndimDetectorTest.java
index e8e1dac..8ce05e2 100644
--- a/services/tests/mockingservicestests/src/com/android/server/power/ScreenUndimDetectorTest.java
+++ b/services/tests/mockingservicestests/src/com/android/server/power/ScreenUndimDetectorTest.java
@@ -40,6 +40,7 @@
import org.junit.After;
import org.junit.Before;
+import org.junit.Ignore;
import org.junit.ClassRule;
import org.junit.Rule;
import org.junit.Test;
@@ -329,6 +330,7 @@
}
}
+ @Ignore("b/387389929")
@Test
public void recordScreenPolicy_otherTransitions_doesNotReset() {
DeviceConfig.setProperty(NAMESPACE_ATTENTION_MANAGER_SERVICE,
diff --git a/telecomm/java/android/telecom/Call.java b/telecomm/java/android/telecom/Call.java
index a52614d..531f516 100644
--- a/telecomm/java/android/telecom/Call.java
+++ b/telecomm/java/android/telecom/Call.java
@@ -52,6 +52,8 @@
* Represents an ongoing phone call that the in-call app should present to the user.
*/
public final class Call {
+ private static final String LOG_TAG = "TelecomCall";
+
/**
* The state of a {@code Call} when newly created.
*/
@@ -2912,6 +2914,11 @@
}
} catch (BadParcelableException e) {
return false;
+ } catch (ClassCastException e) {
+ Log.e(LOG_TAG, e, "areBundlesEqual: failure comparing bundle key %s", key);
+ // until we know what is causing this, we should rethrow -- this is still not
+ // expected.
+ throw e;
}
}
}