Merge "Add new signature permission for Population Density Provider" into main
diff --git a/core/api/system-current.txt b/core/api/system-current.txt
index bf209d7..50d2bfe 100644
--- a/core/api/system-current.txt
+++ b/core/api/system-current.txt
@@ -19151,8 +19151,10 @@
public static class WindowManager.LayoutParams extends android.view.ViewGroup.LayoutParams implements android.os.Parcelable {
method public final long getUserActivityTimeout();
+ method @FlaggedApi("com.android.hardware.input.override_power_key_behavior_in_focused_window") @RequiresPermission(android.Manifest.permission.OVERRIDE_SYSTEM_KEY_BEHAVIOR_IN_FOCUSED_WINDOW) public boolean isReceivePowerKeyDoublePressEnabled();
method public boolean isSystemApplicationOverlay();
method @FlaggedApi("android.companion.virtualdevice.flags.status_bar_and_insets") public void setInsetsParams(@NonNull java.util.List<android.view.WindowManager.InsetsParams>);
+ method @FlaggedApi("com.android.hardware.input.override_power_key_behavior_in_focused_window") @RequiresPermission(android.Manifest.permission.OVERRIDE_SYSTEM_KEY_BEHAVIOR_IN_FOCUSED_WINDOW) public void setReceivePowerKeyDoublePressEnabled(boolean);
method @RequiresPermission(android.Manifest.permission.SYSTEM_APPLICATION_OVERLAY) public void setSystemApplicationOverlay(boolean);
method public final void setUserActivityTimeout(long);
field @RequiresPermission(android.Manifest.permission.HIDE_NON_SYSTEM_OVERLAY_WINDOWS) public static final int SYSTEM_FLAG_HIDE_NON_SYSTEM_OVERLAY_WINDOWS = 524288; // 0x80000
diff --git a/core/java/android/app/appfunctions/ExecuteAppFunctionRequest.java b/core/java/android/app/appfunctions/ExecuteAppFunctionRequest.java
index a88198a..bdc6ce5 100644
--- a/core/java/android/app/appfunctions/ExecuteAppFunctionRequest.java
+++ b/core/java/android/app/appfunctions/ExecuteAppFunctionRequest.java
@@ -136,6 +136,16 @@
return mExtras;
}
+ /**
+ * Returns the size of the request in bytes.
+ *
+ * @hide
+ */
+ public int getRequestDataSize() {
+ return mTargetPackageName.getBytes().length + mFunctionIdentifier.getBytes().length
+ + mParameters.getDataSize() + mExtras.getSize();
+ }
+
@Override
public void writeToParcel(@NonNull Parcel dest, int flags) {
dest.writeString8(mTargetPackageName);
diff --git a/core/java/android/app/appfunctions/ExecuteAppFunctionResponse.java b/core/java/android/app/appfunctions/ExecuteAppFunctionResponse.java
index a4952f4..618cc1c 100644
--- a/core/java/android/app/appfunctions/ExecuteAppFunctionResponse.java
+++ b/core/java/android/app/appfunctions/ExecuteAppFunctionResponse.java
@@ -135,6 +135,15 @@
return mExtras;
}
+ /**
+ * Returns the size of the response in bytes.
+ *
+ * @hide
+ */
+ public int getResponseDataSize() {
+ return mResultDocumentWrapper.getDataSize() + mExtras.getSize();
+ }
+
@Override
public int describeContents() {
return 0;
diff --git a/core/java/android/app/appfunctions/GenericDocumentWrapper.java b/core/java/android/app/appfunctions/GenericDocumentWrapper.java
index 541ca74..02133b4 100644
--- a/core/java/android/app/appfunctions/GenericDocumentWrapper.java
+++ b/core/java/android/app/appfunctions/GenericDocumentWrapper.java
@@ -50,6 +50,10 @@
@Nullable
private Parcel mParcel;
+ @GuardedBy("mLock")
+ @Nullable
+ private Integer mDataSize;
+
private final Object mLock = new Object();
public static final Creator<GenericDocumentWrapper> CREATOR =
@@ -75,11 +79,13 @@
public GenericDocumentWrapper(@NonNull GenericDocument genericDocument) {
mGenericDocument = Objects.requireNonNull(genericDocument);
mParcel = null;
+ mDataSize = null;
}
public GenericDocumentWrapper(@NonNull Parcel parcel) {
mGenericDocument = null;
mParcel = Objects.requireNonNull(parcel);
+ mDataSize = mParcel.dataSize();
}
/** Returns the wrapped {@link android.app.appsearch.GenericDocument} */
@@ -109,6 +115,21 @@
}
}
+ /** Returns the size of the parcelled document. */
+
+ int getDataSize() {
+ synchronized (mLock) {
+ if (mDataSize != null) {
+ return mDataSize;
+ }
+ Parcel tempParcel = Parcel.obtain();
+ writeToParcel(tempParcel, 0);
+ mDataSize = tempParcel.dataSize();
+ tempParcel.recycle();
+ return mDataSize;
+ }
+ }
+
@Override
public int describeContents() {
return 0;
diff --git a/core/java/android/content/pm/flags.aconfig b/core/java/android/content/pm/flags.aconfig
index 8ba2dcc..dfeee2a 100644
--- a/core/java/android/content/pm/flags.aconfig
+++ b/core/java/android/content/pm/flags.aconfig
@@ -354,14 +354,6 @@
}
flag {
- name: "support_minor_versions_in_minsdkversion"
- namespace: "package_manager_service"
- description: "Block app installations that specify an incompatible minor SDK version"
- bug: "377302905"
- is_exported: true
-}
-
-flag {
name: "app_compat_option_16kb"
is_exported: true
namespace: "devoptions_settings"
diff --git a/core/java/android/view/WindowManager.java b/core/java/android/view/WindowManager.java
index 1e8cad6..101d5c9 100644
--- a/core/java/android/view/WindowManager.java
+++ b/core/java/android/view/WindowManager.java
@@ -80,6 +80,9 @@
import static android.view.WindowLayoutParamsProto.X;
import static android.view.WindowLayoutParamsProto.Y;
+import static com.android.hardware.input.Flags.FLAG_OVERRIDE_POWER_KEY_BEHAVIOR_IN_FOCUSED_WINDOW;
+import static com.android.hardware.input.Flags.overridePowerKeyBehaviorInFocusedWindow;
+
import android.Manifest.permission;
import android.annotation.CallbackExecutor;
import android.annotation.FlaggedApi;
@@ -4465,6 +4468,29 @@
public static final int INPUT_FEATURE_SENSITIVE_FOR_PRIVACY = 1 << 3;
/**
+ * Input feature used to indicate that the system should send power key events to this
+ * window when it's in the foreground. The window can override the double press power key
+ * gesture behavior.
+ *
+ * A double press gesture is defined as two
+ * {@link KeyEvent.Callback#onKeyDown(int, KeyEvent)} events within a time span defined by
+ * {@link ViewConfiguration#getMultiPressTimeout()}.
+ *
+ * Note: While the window may receive all power key {@link KeyEvent}s, it can only
+ * override the double press gesture behavior. The system will perform default behavior for
+ * single, long-press and other multi-press gestures, regardless of if the app handles the
+ * key or not.
+ *
+ * To override the default behavior for double press, the app must return true for the
+ * second {@link KeyEvent.Callback#onKeyDown(int, KeyEvent)}. If the app returns false, the
+ * system behavior will be performed for double press.
+ * @hide
+ */
+ @RequiresPermission(permission.OVERRIDE_SYSTEM_KEY_BEHAVIOR_IN_FOCUSED_WINDOW)
+ public static final int
+ INPUT_FEATURE_RECEIVE_POWER_KEY_DOUBLE_PRESS = 1 << 4;
+
+ /**
* An internal annotation for flags that can be specified to {@link #inputFeatures}.
*
* NOTE: These are not the same as {@link android.os.InputConfig} flags.
@@ -4477,6 +4503,7 @@
INPUT_FEATURE_DISABLE_USER_ACTIVITY,
INPUT_FEATURE_SPY,
INPUT_FEATURE_SENSITIVE_FOR_PRIVACY,
+ INPUT_FEATURE_RECEIVE_POWER_KEY_DOUBLE_PRESS
})
public @interface InputFeatureFlags {
}
@@ -4766,6 +4793,44 @@
}
/**
+ * Specifies if the system should send power key events to this window when it's in the
+ * foreground, with only the double tap gesture behavior being overrideable.
+ *
+ * @param enabled if true, the system should send power key events to this window when it's
+ * in the foreground, with only the power key double tap gesture being
+ * overrideable.
+ * @hide
+ */
+ @SystemApi
+ @RequiresPermission(permission.OVERRIDE_SYSTEM_KEY_BEHAVIOR_IN_FOCUSED_WINDOW)
+ @FlaggedApi(FLAG_OVERRIDE_POWER_KEY_BEHAVIOR_IN_FOCUSED_WINDOW)
+ public void setReceivePowerKeyDoublePressEnabled(boolean enabled) {
+ if (enabled) {
+ inputFeatures
+ |= INPUT_FEATURE_RECEIVE_POWER_KEY_DOUBLE_PRESS;
+ } else {
+ inputFeatures
+ &= ~INPUT_FEATURE_RECEIVE_POWER_KEY_DOUBLE_PRESS;
+ }
+ }
+
+ /**
+ * Returns whether or not the system should send power key events to this window when it's
+ * in the foreground, with only the double tap gesture being overrideable.
+ *
+ * @return if the system should send power key events to this window when it's in the
+ * foreground, with only the double tap gesture being overrideable.
+ * @hide
+ */
+ @SystemApi
+ @RequiresPermission(permission.OVERRIDE_SYSTEM_KEY_BEHAVIOR_IN_FOCUSED_WINDOW)
+ @FlaggedApi(FLAG_OVERRIDE_POWER_KEY_BEHAVIOR_IN_FOCUSED_WINDOW)
+ public boolean isReceivePowerKeyDoublePressEnabled() {
+ return (inputFeatures
+ & INPUT_FEATURE_RECEIVE_POWER_KEY_DOUBLE_PRESS) != 0;
+ }
+
+ /**
* Specifies that the window should be considered a trusted system overlay. Trusted system
* overlays are ignored when considering whether windows are obscured during input
* dispatch. Requires the {@link android.Manifest.permission#INTERNAL_SYSTEM_WINDOW}
@@ -6157,6 +6222,16 @@
inputFeatures &= ~INPUT_FEATURE_SPY;
features.add("INPUT_FEATURE_SPY");
}
+ if (overridePowerKeyBehaviorInFocusedWindow()) {
+ if ((inputFeatures
+ & INPUT_FEATURE_RECEIVE_POWER_KEY_DOUBLE_PRESS)
+ != 0) {
+ inputFeatures
+ &=
+ ~INPUT_FEATURE_RECEIVE_POWER_KEY_DOUBLE_PRESS;
+ features.add("INPUT_FEATURE_RECEIVE_POWER_KEY_DOUBLE_PRESS");
+ }
+ }
if (inputFeatures != 0) {
features.add(Integer.toHexString(inputFeatures));
}
diff --git a/core/java/com/android/internal/util/ArrayUtils.java b/core/java/com/android/internal/util/ArrayUtils.java
index 1e965c5d..9b8551b 100644
--- a/core/java/com/android/internal/util/ArrayUtils.java
+++ b/core/java/com/android/internal/util/ArrayUtils.java
@@ -85,6 +85,51 @@
}
/**
+ * This is like <code>new byte[length]</code>, but it allocates the array as non-movable. This
+ * prevents copies of the data from being left on the Java heap as a result of heap compaction.
+ * Use this when the array will contain sensitive data such as a password or cryptographic key
+ * that needs to be wiped from memory when no longer needed. The owner of the array is still
+ * responsible for the zeroization; {@link #zeroize(byte[])} should be used to do so.
+ *
+ * @param length the length of the array to allocate
+ * @return the new array
+ */
+ public static byte[] newNonMovableByteArray(int length) {
+ return (byte[]) VMRuntime.getRuntime().newNonMovableArray(byte.class, length);
+ }
+
+ /**
+ * Like {@link #newNonMovableByteArray(int)}, but allocates a char array.
+ *
+ * @param length the length of the array to allocate
+ * @return the new array
+ */
+ public static char[] newNonMovableCharArray(int length) {
+ return (char[]) VMRuntime.getRuntime().newNonMovableArray(char.class, length);
+ }
+
+ /**
+ * Zeroizes a byte array as securely as possible. Use this when the array contains sensitive
+ * data such as a password or cryptographic key.
+ * <p>
+ * This zeroizes the array in a way that is guaranteed to not be optimized out by the compiler.
+ * If supported by the architecture, it zeroizes the data not just in the L1 data cache but also
+ * in other levels of the memory hierarchy up to and including main memory (but not above that).
+ * <p>
+ * This works on any <code>byte[]</code>, but to ensure that copies of the array aren't left on
+ * the Java heap the array should have been allocated with {@link #newNonMovableByteArray(int)}.
+ * Use on other arrays might also introduce performance anomalies.
+ *
+ * @param array the array to zeroize
+ */
+ public static native void zeroize(byte[] array);
+
+ /**
+ * Like {@link #zeroize(byte[])}, but for char arrays.
+ */
+ public static native void zeroize(char[] array);
+
+ /**
* Checks if the beginnings of two byte arrays are equal.
*
* @param array1 the first byte array
diff --git a/core/jni/Android.bp b/core/jni/Android.bp
index e22d958..0ffe2f9 100644
--- a/core/jni/Android.bp
+++ b/core/jni/Android.bp
@@ -92,6 +92,7 @@
"android_view_VelocityTracker.cpp",
"android_view_VerifiedKeyEvent.cpp",
"android_view_VerifiedMotionEvent.cpp",
+ "com_android_internal_util_ArrayUtils.cpp",
"com_android_internal_util_VirtualRefBasePtr.cpp",
"core_jni_helpers.cpp",
":deviceproductinfoconstants_aidl",
diff --git a/core/jni/AndroidRuntime.cpp b/core/jni/AndroidRuntime.cpp
index ac187b0..78d69f0 100644
--- a/core/jni/AndroidRuntime.cpp
+++ b/core/jni/AndroidRuntime.cpp
@@ -220,6 +220,7 @@
extern int register_com_android_internal_os_ZygoteCommandBuffer(JNIEnv *env);
extern int register_com_android_internal_os_ZygoteInit(JNIEnv *env);
extern int register_com_android_internal_security_VerityUtils(JNIEnv* env);
+extern int register_com_android_internal_util_ArrayUtils(JNIEnv* env);
extern int register_com_android_internal_util_VirtualRefBasePtr(JNIEnv *env);
extern int register_android_window_WindowInfosListener(JNIEnv* env);
extern int register_android_window_ScreenCapture(JNIEnv* env);
@@ -1621,6 +1622,7 @@
REG_JNI(register_com_android_internal_os_ZygoteCommandBuffer),
REG_JNI(register_com_android_internal_os_ZygoteInit),
REG_JNI(register_com_android_internal_security_VerityUtils),
+ REG_JNI(register_com_android_internal_util_ArrayUtils),
REG_JNI(register_com_android_internal_util_VirtualRefBasePtr),
REG_JNI(register_android_hardware_Camera),
REG_JNI(register_android_hardware_camera2_CameraMetadata),
diff --git a/core/jni/com_android_internal_util_ArrayUtils.cpp b/core/jni/com_android_internal_util_ArrayUtils.cpp
new file mode 100644
index 0000000..c69e6c9
--- /dev/null
+++ b/core/jni/com_android_internal_util_ArrayUtils.cpp
@@ -0,0 +1,122 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#define LOG_TAG "ArrayUtils"
+
+#include <android-base/logging.h>
+#include <jni.h>
+#include <nativehelper/JNIHelp.h>
+#include <string.h>
+#include <unistd.h>
+#include <utils/Log.h>
+
+namespace android {
+
+static size_t GetCacheLineSize() {
+ long size = sysconf(_SC_LEVEL1_DCACHE_LINESIZE);
+ if (size <= 0) {
+ ALOGE("Unable to determine L1 data cache line size. Assuming 32 bytes");
+ return 32;
+ }
+ return size;
+}
+
+#ifdef __aarch64__
+static void CleanDataCache(const uint8_t* p, size_t size, size_t cache_line_size) {
+ // Execute 'dc cvac' at least once on each cache line in the memory region.
+ //
+ // 'dc cvac' stands for "Data Cache line Clean by Virtual Address to point-of-Coherency".
+ // It writes the cache line back to the "point-of-coherency", i.e. main memory.
+ //
+ // Since the memory region is not guaranteed to be cache-line-aligned, we use an "extra"
+ // instruction after the loop to make sure the last cache line gets covered.
+ for (size_t i = 0; i < size; i += cache_line_size) {
+ asm volatile("dc cvac, %0" ::"r"(p + i));
+ }
+ asm volatile("dc cvac, %0" ::"r"(p + size - 1));
+}
+#elif defined(__i386__) || defined(__x86_64__)
+static void CleanDataCache(const uint8_t* p, size_t size, size_t cache_line_size) {
+ for (size_t i = 0; i < size; i += cache_line_size) {
+ asm volatile("clflush (%0)" ::"r"(p + i));
+ }
+ asm volatile("clflush (%0)" ::"r"(p + size - 1));
+}
+#elif defined(__riscv)
+static void CleanDataCache(const uint8_t* p, size_t size, size_t cache_line_size) {
+ // This should eventually work, but it is not ready to be enabled yet:
+ // 1.) The Android emulator needs to add support for zicbom.
+ // 2.) Kernel needs to enable zicbom in usermode.
+ // 3.) Android clang needs to add zicbom to the target.
+#if 0
+ for (size_t i = 0; i < size; i += cache_line_size) {
+ asm volatile("cbo.clean (%0)" ::"r"(p + i));
+ }
+ asm volatile("cbo.clean (%0)" ::"r"(p + size - 1));
+#endif
+}
+#elif defined(__arm__)
+// arm32 has a cacheflush() syscall, but it is undocumented and only flushes the icache.
+// It is not the same as cacheflush(2) as documented in the Linux man-pages project.
+static void CleanDataCache(const uint8_t* p, size_t size, size_t cache_line_size) {}
+#else
+#error "Unknown architecture"
+#endif
+
+static void ZeroizePrimitiveArray(JNIEnv* env, jclass clazz, jarray array, size_t component_len) {
+ static const size_t cache_line_size = GetCacheLineSize();
+
+ size_t size = env->GetArrayLength(array) * component_len;
+ if (size == 0) {
+ return;
+ }
+
+ // ART guarantees that GetPrimitiveArrayCritical never copies.
+ jboolean isCopy;
+ void* elems = env->GetPrimitiveArrayCritical(array, &isCopy);
+ CHECK(!isCopy);
+
+#ifdef __BIONIC__
+ memset_explicit(elems, 0, size);
+#else
+ memset(elems, 0, size);
+#endif
+ // Clean the data cache so that the data gets zeroized in main memory right away. Without this,
+ // it might not be written to main memory until the cache line happens to be evicted.
+ CleanDataCache(static_cast<const uint8_t*>(elems), size, cache_line_size);
+
+ env->ReleasePrimitiveArrayCritical(array, elems, /* mode= */ 0);
+}
+
+static void ZeroizeByteArray(JNIEnv* env, jclass clazz, jbyteArray array) {
+ ZeroizePrimitiveArray(env, clazz, array, sizeof(jbyte));
+}
+
+static void ZeroizeCharArray(JNIEnv* env, jclass clazz, jcharArray array) {
+ ZeroizePrimitiveArray(env, clazz, array, sizeof(jchar));
+}
+
+static const JNINativeMethod sMethods[] = {
+ {"zeroize", "([B)V", (void*)ZeroizeByteArray},
+ {"zeroize", "([C)V", (void*)ZeroizeCharArray},
+};
+
+int register_com_android_internal_util_ArrayUtils(JNIEnv* env) {
+ return jniRegisterNativeMethods(env, "com/android/internal/util/ArrayUtils", sMethods,
+ NELEM(sMethods));
+}
+
+} // namespace android
diff --git a/core/res/res/values/config.xml b/core/res/res/values/config.xml
index f199159..a2b7de1 100644
--- a/core/res/res/values/config.xml
+++ b/core/res/res/values/config.xml
@@ -7267,4 +7267,8 @@
POLICY_DOZE can also dim the screen unless parameter useNormalBrightnessForDoze of
DreamService#setDozeScreenState requests an exception. -->
<bool name="config_allowNormalBrightnessForDozePolicy">false</bool>
+
+ <!-- List of protected packages that require biometric authentication for modification
+ (Disable, force-stop or uninstalling updates). -->
+ <string-array name="config_biometric_protected_package_names" translatable="false" />
</resources>
diff --git a/core/res/res/values/symbols.xml b/core/res/res/values/symbols.xml
index 5d6a461..9a51b72 100644
--- a/core/res/res/values/symbols.xml
+++ b/core/res/res/values/symbols.xml
@@ -5857,4 +5857,7 @@
<java-symbol type="dimen" name="config_motionExpressiveSlowSpatialDamping"/>
<java-symbol type="dimen" name="config_motionExpressiveSlowEffectDamping"/>
+ <!-- List of protected packages that require biometric authentication for modification -->
+ <java-symbol type="array" name="config_biometric_protected_package_names" />
+
</resources>
diff --git a/core/tests/utiltests/src/com/android/internal/util/ArrayUtilsTest.java b/core/tests/utiltests/src/com/android/internal/util/ArrayUtilsTest.java
index 3b9f35b..3c264f1 100644
--- a/core/tests/utiltests/src/com/android/internal/util/ArrayUtilsTest.java
+++ b/core/tests/utiltests/src/com/android/internal/util/ArrayUtilsTest.java
@@ -496,4 +496,51 @@
// expected
}
}
+
+ // Note: the zeroize() tests only test the behavior that can be tested from a Java test.
+ // They do not verify that no copy of the data is left anywhere.
+
+ @Test
+ @SmallTest
+ public void testZeroizeNonMovableByteArray() {
+ final int length = 10;
+ byte[] array = ArrayUtils.newNonMovableByteArray(length);
+ assertArrayEquals(array, new byte[length]);
+ Arrays.fill(array, (byte) 0xff);
+ ArrayUtils.zeroize(array);
+ assertArrayEquals(array, new byte[length]);
+ }
+
+ @Test
+ @SmallTest
+ public void testZeroizeRegularByteArray() {
+ final int length = 10;
+ byte[] array = new byte[length];
+ assertArrayEquals(array, new byte[length]);
+ Arrays.fill(array, (byte) 0xff);
+ ArrayUtils.zeroize(array);
+ assertArrayEquals(array, new byte[length]);
+ }
+
+ @Test
+ @SmallTest
+ public void testZeroizeNonMovableCharArray() {
+ final int length = 10;
+ char[] array = ArrayUtils.newNonMovableCharArray(length);
+ assertArrayEquals(array, new char[length]);
+ Arrays.fill(array, (char) 0xff);
+ ArrayUtils.zeroize(array);
+ assertArrayEquals(array, new char[length]);
+ }
+
+ @Test
+ @SmallTest
+ public void testZeroizeRegularCharArray() {
+ final int length = 10;
+ char[] array = new char[length];
+ assertArrayEquals(array, new char[length]);
+ Arrays.fill(array, (char) 0xff);
+ ArrayUtils.zeroize(array);
+ assertArrayEquals(array, new char[length]);
+ }
}
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/DesktopModeWindowDecoration.java b/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/DesktopModeWindowDecoration.java
index bd84ccc..e7985de 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/DesktopModeWindowDecoration.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/DesktopModeWindowDecoration.java
@@ -543,9 +543,9 @@
final boolean inFullImmersive = mDesktopUserRepositories.getProfile(taskInfo.userId)
.isTaskInFullImmersiveState(taskInfo.taskId);
- updateRelayoutParams(mRelayoutParams, mContext, taskInfo, applyStartTransactionOnDraw,
- shouldSetTaskVisibilityPositionAndCrop, mIsStatusBarVisible,
- mIsKeyguardVisibleAndOccluded, inFullImmersive,
+ updateRelayoutParams(mRelayoutParams, mContext, taskInfo, mSplitScreenController,
+ applyStartTransactionOnDraw, shouldSetTaskVisibilityPositionAndCrop,
+ mIsStatusBarVisible, mIsKeyguardVisibleAndOccluded, inFullImmersive,
mDisplayController.getInsetsState(taskInfo.displayId), hasGlobalFocus,
displayExclusionRegion);
@@ -877,6 +877,7 @@
RelayoutParams relayoutParams,
Context context,
ActivityManager.RunningTaskInfo taskInfo,
+ SplitScreenController splitScreenController,
boolean applyStartTransactionOnDraw,
boolean shouldSetTaskVisibilityPositionAndCrop,
boolean isStatusBarVisible,
@@ -918,7 +919,10 @@
|| (isStatusBarVisible && !isKeyguardVisibleAndOccluded);
}
relayoutParams.mIsCaptionVisible = showCaption;
- relayoutParams.mIsInsetSource = isAppHeader && !inFullImmersiveMode;
+ final boolean isBottomSplit = !splitScreenController.isLeftRightSplit()
+ && splitScreenController.getSplitPosition(taskInfo.taskId)
+ == SPLIT_POSITION_BOTTOM_OR_RIGHT;
+ relayoutParams.mIsInsetSource = (isAppHeader && !inFullImmersiveMode) || isBottomSplit;
if (isAppHeader) {
if (TaskInfoKt.isTransparentCaptionBarAppearance(taskInfo)) {
// The app is requesting to customize the caption bar, which means input on
diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/desktopmode/DesktopModeKeyGestureHandlerTest.kt b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/desktopmode/DesktopModeKeyGestureHandlerTest.kt
index dc7fb5f..0bc1fb9 100644
--- a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/desktopmode/DesktopModeKeyGestureHandlerTest.kt
+++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/desktopmode/DesktopModeKeyGestureHandlerTest.kt
@@ -56,6 +56,7 @@
import com.android.wm.shell.TestShellExecutor
import com.android.wm.shell.common.DisplayController
import com.android.wm.shell.common.DisplayLayout
+import com.android.wm.shell.desktopmode.common.ToggleTaskSizeInteraction
import com.android.wm.shell.shared.desktopmode.DesktopModeStatus
import com.android.wm.shell.sysui.ShellInit
import com.android.wm.shell.windowdecor.DesktopModeWindowDecorViewModel
@@ -204,9 +205,15 @@
.setModifierState(KeyEvent.META_META_ON)
.build()
val result = keyGestureEventHandler.handleKeyGestureEvent(event, null)
+ testExecutor.flushAll()
assertThat(result).isTrue()
- assertThat(testExecutor.callbacks.size).isEqualTo(1)
+ verify(desktopModeWindowDecorViewModel).onSnapResize(
+ task.taskId,
+ true,
+ DesktopModeEventLogger.Companion.InputMethod.KEYBOARD,
+ /* fromMenu= */ false
+ )
}
@Test
@@ -226,9 +233,15 @@
.setModifierState(KeyEvent.META_META_ON)
.build()
val result = keyGestureEventHandler.handleKeyGestureEvent(event, null)
+ testExecutor.flushAll()
assertThat(result).isTrue()
- assertThat(testExecutor.callbacks.size).isEqualTo(1)
+ verify(desktopModeWindowDecorViewModel).onSnapResize(
+ task.taskId,
+ false,
+ DesktopModeEventLogger.Companion.InputMethod.KEYBOARD,
+ /* fromMenu= */ false
+ )
}
@Test
@@ -248,9 +261,18 @@
.setModifierState(KeyEvent.META_META_ON)
.build()
val result = keyGestureEventHandler.handleKeyGestureEvent(event, null)
+ testExecutor.flushAll()
assertThat(result).isTrue()
- assertThat(testExecutor.callbacks.size).isEqualTo(1)
+ verify(desktopTasksController).toggleDesktopTaskSize(
+ task,
+ ToggleTaskSizeInteraction(
+ isMaximized = isTaskMaximized(task, displayController),
+ source = ToggleTaskSizeInteraction.Source.KEYBOARD_SHORTCUT,
+ inputMethod =
+ DesktopModeEventLogger.Companion.InputMethod.KEYBOARD,
+ ),
+ )
}
@Test
@@ -270,9 +292,10 @@
.setModifierState(KeyEvent.META_META_ON)
.build()
val result = keyGestureEventHandler.handleKeyGestureEvent(event, null)
+ testExecutor.flushAll()
assertThat(result).isTrue()
- assertThat(testExecutor.callbacks.size).isEqualTo(1)
+ verify(desktopTasksController).minimizeTask(task)
}
private fun setUpFreeformTask(
diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/windowdecor/DesktopHeaderManageWindowsMenuTest.kt b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/windowdecor/DesktopHeaderManageWindowsMenuTest.kt
index 4403558..e871711 100644
--- a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/windowdecor/DesktopHeaderManageWindowsMenuTest.kt
+++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/windowdecor/DesktopHeaderManageWindowsMenuTest.kt
@@ -35,7 +35,6 @@
import com.google.common.truth.Truth.assertThat
import org.junit.After
import org.junit.Before
-import org.junit.Ignore
import org.junit.Rule
import org.junit.Test
import org.junit.runner.RunWith
@@ -77,7 +76,6 @@
}
@Test
- @Ignore("Test is failing internally")
@EnableFlags(Flags.FLAG_ENABLE_FULLY_IMMERSIVE_IN_DESKTOP)
fun testShow_forImmersiveTask_usesSystemViewContainer() {
val task = createFreeformTask()
@@ -110,6 +108,7 @@
.setToken(MockToken().token())
.setActivityType(ACTIVITY_TYPE_STANDARD)
.setWindowingMode(WINDOWING_MODE_FREEFORM)
+ .setUserId(DEFAULT_USER_ID)
.build()
private companion object {
diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/windowdecor/DesktopModeWindowDecorationTests.java b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/windowdecor/DesktopModeWindowDecorationTests.java
index 61f3755..0bef4191 100644
--- a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/windowdecor/DesktopModeWindowDecorationTests.java
+++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/windowdecor/DesktopModeWindowDecorationTests.java
@@ -29,6 +29,7 @@
import static com.android.dx.mockito.inline.extended.ExtendedMockito.mockitoSession;
import static com.android.wm.shell.MockSurfaceControlHelper.createMockSurfaceControlTransaction;
+import static com.android.wm.shell.shared.split.SplitScreenConstants.SPLIT_POSITION_BOTTOM_OR_RIGHT;
import static com.android.wm.shell.windowdecor.DesktopModeWindowDecoration.CLOSE_MAXIMIZE_MENU_DELAY_MS;
import static com.android.wm.shell.windowdecor.WindowDecoration.INVALID_CORNER_RADIUS;
@@ -305,7 +306,8 @@
RelayoutParams relayoutParams = new RelayoutParams();
DesktopModeWindowDecoration.updateRelayoutParams(
- relayoutParams, mContext, taskInfo, /* applyStartTransactionOnDraw= */ true,
+ relayoutParams, mContext, taskInfo, mMockSplitScreenController,
+ /* applyStartTransactionOnDraw= */ true,
/* shouldSetTaskPositionAndCrop */ false,
/* isStatusBarVisible */ true,
/* isKeyguardVisibleAndOccluded */ false,
@@ -325,7 +327,8 @@
RelayoutParams relayoutParams = new RelayoutParams();
DesktopModeWindowDecoration.updateRelayoutParams(
- relayoutParams, mContext, taskInfo, /* applyStartTransactionOnDraw= */ true,
+ relayoutParams, mContext, taskInfo, mMockSplitScreenController,
+ /* applyStartTransactionOnDraw= */ true,
/* shouldSetTaskPositionAndCrop */ false,
/* isStatusBarVisible */ true,
/* isKeyguardVisibleAndOccluded */ false,
@@ -344,7 +347,8 @@
RelayoutParams relayoutParams = new RelayoutParams();
DesktopModeWindowDecoration.updateRelayoutParams(
- relayoutParams, mContext, taskInfo, /* applyStartTransactionOnDraw= */ true,
+ relayoutParams, mContext, taskInfo, mMockSplitScreenController,
+ /* applyStartTransactionOnDraw= */ true,
/* shouldSetTaskPositionAndCrop */ false,
/* isStatusBarVisible */ true,
/* isKeyguardVisibleAndOccluded */ false,
@@ -367,6 +371,7 @@
relayoutParams,
mTestableContext,
taskInfo,
+ mMockSplitScreenController,
/* applyStartTransactionOnDraw= */ true,
/* shouldSetTaskPositionAndCrop */ false,
/* isStatusBarVisible */ true,
@@ -390,6 +395,7 @@
relayoutParams,
mTestableContext,
taskInfo,
+ mMockSplitScreenController,
/* applyStartTransactionOnDraw= */ true,
/* shouldSetTaskPositionAndCrop */ false,
/* isStatusBarVisible */ true,
@@ -413,6 +419,7 @@
relayoutParams,
mTestableContext,
taskInfo,
+ mMockSplitScreenController,
/* applyStartTransactionOnDraw= */ true,
/* shouldSetTaskPositionAndCrop */ false,
/* isStatusBarVisible */ true,
@@ -440,6 +447,7 @@
relayoutParams,
mTestableContext,
taskInfo,
+ mMockSplitScreenController,
/* applyStartTransactionOnDraw= */ true,
/* shouldSetTaskPositionAndCrop */ false,
/* isStatusBarVisible */ true,
@@ -468,6 +476,7 @@
relayoutParams,
mTestableContext,
taskInfo,
+ mMockSplitScreenController,
/* applyStartTransactionOnDraw= */ true,
/* shouldSetTaskPositionAndCrop */ false,
/* isStatusBarVisible */ true,
@@ -493,6 +502,7 @@
relayoutParams,
mTestableContext,
taskInfo,
+ mMockSplitScreenController,
/* applyStartTransactionOnDraw= */ true,
/* shouldSetTaskPositionAndCrop */ false,
/* isStatusBarVisible */ true,
@@ -518,6 +528,7 @@
relayoutParams,
mTestableContext,
taskInfo,
+ mMockSplitScreenController,
/* applyStartTransactionOnDraw= */ true,
/* shouldSetTaskPositionAndCrop */ false,
/* isStatusBarVisible */ true,
@@ -542,6 +553,7 @@
relayoutParams,
mTestableContext,
taskInfo,
+ mMockSplitScreenController,
/* applyStartTransactionOnDraw= */ true,
/* shouldSetTaskPositionAndCrop */ false,
/* isStatusBarVisible */ true,
@@ -566,6 +578,7 @@
relayoutParams,
mTestableContext,
taskInfo,
+ mMockSplitScreenController,
/* applyStartTransactionOnDraw= */ true,
/* shouldSetTaskPositionAndCrop */ false,
/* isStatusBarVisible */ true,
@@ -589,6 +602,7 @@
relayoutParams,
mTestableContext,
taskInfo,
+ mMockSplitScreenController,
/* applyStartTransactionOnDraw= */ true,
/* shouldSetTaskPositionAndCrop */ false,
/* isStatusBarVisible */ true,
@@ -612,6 +626,7 @@
relayoutParams,
mTestableContext,
taskInfo,
+ mMockSplitScreenController,
/* applyStartTransactionOnDraw= */ true,
/* shouldSetTaskPositionAndCrop */ false,
/* isStatusBarVisible */ true,
@@ -634,6 +649,7 @@
relayoutParams,
mTestableContext,
taskInfo,
+ mMockSplitScreenController,
/* applyStartTransactionOnDraw= */ true,
/* shouldSetTaskPositionAndCrop */ false,
/* isStatusBarVisible */ true,
@@ -657,6 +673,7 @@
relayoutParams,
mTestableContext,
taskInfo,
+ mMockSplitScreenController,
/* applyStartTransactionOnDraw= */ true,
/* shouldSetTaskPositionAndCrop */ false,
/* isStatusBarVisible */ true,
@@ -680,6 +697,7 @@
relayoutParams,
mTestableContext,
taskInfo,
+ mMockSplitScreenController,
/* applyStartTransactionOnDraw= */ true,
/* shouldSetTaskPositionAndCrop */ false,
/* isStatusBarVisible */ true,
@@ -704,6 +722,7 @@
relayoutParams,
mTestableContext,
taskInfo,
+ mMockSplitScreenController,
/* applyStartTransactionOnDraw= */ true,
/* shouldSetTaskPositionAndCrop */ false,
/* isStatusBarVisible */ true,
@@ -729,6 +748,7 @@
relayoutParams,
mTestableContext,
taskInfo,
+ mMockSplitScreenController,
/* applyStartTransactionOnDraw= */ true,
/* shouldSetTaskPositionAndCrop */ false,
/* isStatusBarVisible */ true,
@@ -752,6 +772,7 @@
relayoutParams,
mTestableContext,
taskInfo,
+ mMockSplitScreenController,
/* applyStartTransactionOnDraw= */ true,
/* shouldSetTaskPositionAndCrop */ false,
/* isStatusBarVisible */ true,
@@ -777,6 +798,7 @@
relayoutParams,
mTestableContext,
taskInfo,
+ mMockSplitScreenController,
/* applyStartTransactionOnDraw= */ true,
/* shouldSetTaskPositionAndCrop */ false,
/* isStatusBarVisible */ true,
@@ -792,6 +814,31 @@
}
@Test
+ public void updateRelayoutParams_handle_bottomSplitIsInsetSource() {
+ final ActivityManager.RunningTaskInfo taskInfo = createTaskInfo(/* visible= */ true);
+ final RelayoutParams relayoutParams = new RelayoutParams();
+ when(mMockSplitScreenController.isLeftRightSplit()).thenReturn(false);
+ when(mMockSplitScreenController.getSplitPosition(taskInfo.taskId))
+ .thenReturn(SPLIT_POSITION_BOTTOM_OR_RIGHT);
+
+ DesktopModeWindowDecoration.updateRelayoutParams(
+ relayoutParams,
+ mTestableContext,
+ taskInfo,
+ mMockSplitScreenController,
+ /* applyStartTransactionOnDraw= */ true,
+ /* shouldSetTaskPositionAndCrop */ false,
+ /* isStatusBarVisible */ true,
+ /* isKeyguardVisibleAndOccluded */ false,
+ /* inFullImmersiveMode */ true,
+ new InsetsState(),
+ /* hasGlobalFocus= */ true,
+ mExclusionRegion);
+
+ assertThat(relayoutParams.mIsInsetSource).isTrue();
+ }
+
+ @Test
@EnableFlags(Flags.FLAG_ENABLE_FULLY_IMMERSIVE_IN_DESKTOP)
public void updateRelayoutParams_header_addsPaddingInFullImmersive() {
final ActivityManager.RunningTaskInfo taskInfo = createTaskInfo(/* visible= */ true);
@@ -808,6 +855,7 @@
relayoutParams,
mTestableContext,
taskInfo,
+ mMockSplitScreenController,
/* applyStartTransactionOnDraw= */ true,
/* shouldSetTaskPositionAndCrop */ false,
/* isStatusBarVisible */ true,
@@ -832,6 +880,7 @@
relayoutParams,
mTestableContext,
taskInfo,
+ mMockSplitScreenController,
/* applyStartTransactionOnDraw= */ true,
/* shouldSetTaskPositionAndCrop */ false,
/* isStatusBarVisible */ true,
@@ -855,6 +904,7 @@
relayoutParams,
mTestableContext,
taskInfo,
+ mMockSplitScreenController,
/* applyStartTransactionOnDraw= */ true,
/* shouldSetTaskPositionAndCrop */ false,
/* isStatusBarVisible */ false,
@@ -878,6 +928,7 @@
relayoutParams,
mTestableContext,
taskInfo,
+ mMockSplitScreenController,
/* applyStartTransactionOnDraw= */ true,
/* shouldSetTaskPositionAndCrop */ false,
/* isStatusBarVisible */ true,
@@ -900,6 +951,7 @@
relayoutParams,
mTestableContext,
taskInfo,
+ mMockSplitScreenController,
/* applyStartTransactionOnDraw= */ true,
/* shouldSetTaskPositionAndCrop */ false,
/* isStatusBarVisible */ false,
@@ -922,6 +974,7 @@
relayoutParams,
mTestableContext,
taskInfo,
+ mMockSplitScreenController,
/* applyStartTransactionOnDraw= */ true,
/* shouldSetTaskPositionAndCrop */ false,
/* isStatusBarVisible */ true,
@@ -945,6 +998,7 @@
relayoutParams,
mTestableContext,
taskInfo,
+ mMockSplitScreenController,
/* applyStartTransactionOnDraw= */ true,
/* shouldSetTaskPositionAndCrop */ false,
/* isStatusBarVisible */ true,
@@ -960,6 +1014,7 @@
relayoutParams,
mTestableContext,
taskInfo,
+ mMockSplitScreenController,
/* applyStartTransactionOnDraw= */ true,
/* shouldSetTaskPositionAndCrop */ false,
/* isStatusBarVisible */ false,
@@ -983,6 +1038,7 @@
relayoutParams,
mTestableContext,
taskInfo,
+ mMockSplitScreenController,
/* applyStartTransactionOnDraw= */ true,
/* shouldSetTaskPositionAndCrop */ false,
/* isStatusBarVisible */ true,
diff --git a/nfc/tests/src/android/nfc/NdefRecordTest.java b/nfc/tests/src/android/nfc/NdefRecordTest.java
index 231e939..044c674 100644
--- a/nfc/tests/src/android/nfc/NdefRecordTest.java
+++ b/nfc/tests/src/android/nfc/NdefRecordTest.java
@@ -24,6 +24,8 @@
import org.junit.Test;
import org.junit.runner.RunWith;
+import java.util.Locale;
+
@SmallTest
@RunWith(AndroidJUnit4.class)
public class NdefRecordTest {
@@ -56,4 +58,20 @@
assertThat(ndefRecord.getType()).isEqualTo(NdefRecord.RTD_URI);
}
+ @Test
+ public void testCreateMime() {
+ NdefRecord ndefRecord = NdefRecord.createMime("text/plain", "example".getBytes());
+ assertThat(ndefRecord).isNotNull();
+ assertThat(ndefRecord.getTnf()).isEqualTo(NdefRecord.TNF_MIME_MEDIA);
+ }
+
+ @Test
+ public void testCreateTextRecord() {
+ String languageCode = Locale.getDefault().getLanguage();
+ NdefRecord ndefRecord = NdefRecord.createTextRecord(languageCode, "testdata");
+ assertThat(ndefRecord).isNotNull();
+ assertThat(ndefRecord.getTnf()).isEqualTo(NdefRecord.TNF_WELL_KNOWN);
+ assertThat(ndefRecord.getType()).isEqualTo(NdefRecord.RTD_TEXT);
+ }
+
}
diff --git a/packages/SettingsProvider/src/com/android/providers/settings/SettingsState.java b/packages/SettingsProvider/src/com/android/providers/settings/SettingsState.java
index 011ffbc..c0e61ee 100644
--- a/packages/SettingsProvider/src/com/android/providers/settings/SettingsState.java
+++ b/packages/SettingsProvider/src/com/android/providers/settings/SettingsState.java
@@ -178,11 +178,6 @@
private static final String APEX_DIR = "/apex";
private static final String APEX_ACONFIG_PATH_SUFFIX = "/etc/aconfig_flags.pb";
- private static final String STORAGE_MIGRATION_FLAG =
- "core_experiments_team_internal/com.android.providers.settings.storage_test_mission_1";
- private static final String STORAGE_MIGRATION_MARKER_FILE =
- "/metadata/aconfig_test_missions/mission_1";
-
/**
* This tag is applied to all aconfig default value-loaded flags.
*/
@@ -1753,32 +1748,6 @@
}
}
- if (isConfigSettingsKey(mKey) && name != null
- && name.equals(STORAGE_MIGRATION_FLAG)) {
- if (value.equals("true")) {
- Path path = Paths.get(STORAGE_MIGRATION_MARKER_FILE);
- if (!Files.exists(path)) {
- Files.createFile(path);
- }
-
- Set<PosixFilePermission> perms =
- Files.readAttributes(path, PosixFileAttributes.class).permissions();
- perms.add(PosixFilePermission.OWNER_WRITE);
- perms.add(PosixFilePermission.OWNER_READ);
- perms.add(PosixFilePermission.GROUP_READ);
- perms.add(PosixFilePermission.OTHERS_READ);
- try {
- Files.setPosixFilePermissions(path, perms);
- } catch (Exception e) {
- Slog.e(LOG_TAG, "failed to set permissions on migration marker", e);
- }
- } else {
- java.nio.file.Path path = Paths.get(STORAGE_MIGRATION_MARKER_FILE);
- if (Files.exists(path)) {
- Files.delete(path);
- }
- }
- }
mSettings.put(name, new Setting(name, value, defaultValue, packageName, tag,
fromSystem, Long.valueOf(id), isPreservedInRestore));
diff --git a/packages/SystemUI/aconfig/systemui.aconfig b/packages/SystemUI/aconfig/systemui.aconfig
index 02e7b5f..e2f28fa 100644
--- a/packages/SystemUI/aconfig/systemui.aconfig
+++ b/packages/SystemUI/aconfig/systemui.aconfig
@@ -1204,6 +1204,13 @@
}
flag {
+ name: "communal_responsive_grid"
+ namespace: "systemui"
+ description: "Enables responsive grid on glanceable hub"
+ bug: "378171351"
+}
+
+flag {
name: "communal_standalone_support"
namespace: "systemui"
description: "Support communal features without a dock"
diff --git a/packages/SystemUI/checks/src/com/android/internal/systemui/lint/ShadeDisplayAwareDetector.kt b/packages/SystemUI/checks/src/com/android/internal/systemui/lint/ShadeDisplayAwareDetector.kt
new file mode 100644
index 0000000..2f83d82
--- /dev/null
+++ b/packages/SystemUI/checks/src/com/android/internal/systemui/lint/ShadeDisplayAwareDetector.kt
@@ -0,0 +1,136 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.internal.systemui.lint
+
+import com.android.tools.lint.client.api.UElementHandler
+import com.android.tools.lint.detector.api.Category
+import com.android.tools.lint.detector.api.Detector
+import com.android.tools.lint.detector.api.Implementation
+import com.android.tools.lint.detector.api.Issue
+import com.android.tools.lint.detector.api.JavaContext
+import com.android.tools.lint.detector.api.Scope
+import com.android.tools.lint.detector.api.Severity
+import com.android.tools.lint.detector.api.SourceCodeScanner
+import org.jetbrains.uast.UClass
+import org.jetbrains.uast.getContainingUFile
+
+class ShadeDisplayAwareDetector : Detector(), SourceCodeScanner {
+ override fun getApplicableUastTypes() = listOf(UClass::class.java)
+
+ override fun createUastHandler(context: JavaContext) =
+ object : UElementHandler() {
+ override fun visitClass(node: UClass) {
+ for (constructor in node.constructors) {
+ // Visit all injected constructors in shade-relevant packages
+ if (!constructor.hasAnnotation(INJECT_ANNOTATION)) continue
+ if (!isInRelevantShadePackage(node)) continue
+ if (IGNORED_PACKAGES.contains(node.qualifiedName)) continue
+
+ // Check the any context-dependent parameter to see if it has @ShadeDisplayAware
+ // annotation
+ for (parameter in constructor.parameterList.parameters) {
+ val shouldReport =
+ CONTEXT_DEPENDENT_SHADE_CLASSES.contains(
+ parameter.type.canonicalText
+ ) && !parameter.hasAnnotation(SHADE_DISPLAY_AWARE_ANNOTATION)
+ if (shouldReport) {
+ context.report(
+ issue = ISSUE,
+ scope = parameter.declarationScope,
+ location = context.getNameLocation(parameter),
+ message = reportMsg(className = parameter.type.presentableText),
+ )
+ }
+ }
+ }
+ }
+ }
+
+ companion object {
+ private const val INJECT_ANNOTATION = "javax.inject.Inject"
+ private const val SHADE_DISPLAY_AWARE_ANNOTATION =
+ "com.android.systemui.shade.ShadeDisplayAware"
+
+ private val CONTEXT_DEPENDENT_SHADE_CLASSES =
+ setOf(
+ "android.content.Context",
+ "android.view.WindowManager",
+ "android.view.LayoutInflater",
+ "android.content.res.Resources",
+ "com.android.systemui.common.ui.ConfigurationState",
+ "com.android.systemui.statusbar.policy.ConfigurationController",
+ "com.android.systemui.common.ui.domain.interactor.ConfigurationInteractor",
+ )
+
+ private val SHADE_WINDOW_PACKAGES =
+ listOf(
+ "com.android.systemui.biometrics",
+ "com.android.systemui.bouncer",
+ "com.android.systemui.keyboard.docking.ui.viewmodel",
+ "com.android.systemui.qs",
+ "com.android.systemui.shade",
+ "com.android.systemui.statusbar.notification",
+ "com.android.systemui.unfold.domain.interactor",
+ )
+
+ private val IGNORED_PACKAGES =
+ setOf(
+ "com.android.systemui.biometrics.UdfpsController",
+ "com.android.systemui.qs.customize.TileAdapter",
+ )
+
+ private fun isInRelevantShadePackage(node: UClass): Boolean {
+ val packageName = node.getContainingUFile()?.packageName
+ if (packageName.isNullOrBlank()) return false
+ return SHADE_WINDOW_PACKAGES.any { relevantPackage ->
+ packageName.startsWith(relevantPackage)
+ }
+ }
+
+ private fun reportMsg(className: String) =
+ """UI elements of the shade window
+ |should use ShadeDisplayAware-annotated $className, as the shade might move between windows, and only
+ |@ShadeDisplayAware resources are updated with the new configuration correctly. Failures to do so
+ |might result in wrong dimensions for shade window classes (e.g. using the wrong density or theme).
+ |If the usage of $className is not related to display specific configuration or UI, then there is
+ |technically no need to use the annotation, and you can annotate the class with
+ |@SuppressLint("ShadeDisplayAwareContextChecker")/@Suppress("ShadeDisplayAwareContextChecker")
+ |"""
+ .trimMargin()
+
+ @JvmField
+ val ISSUE: Issue =
+ Issue.create(
+ id = "ShadeDisplayAwareContextChecker",
+ briefDescription = "Using non-ShadeDisplayAware component within shade",
+ explanation =
+ """
+ Any context-dependent components (Resources, LayoutInflater, ConfigurationState,
+ etc.) being injected into Shade-relevant classes must have the @ShadeDisplayAware
+ annotation to ensure they work with when the shade is moved to a different display.
+ When the shade is moved, the configuration might change, and only @ShadeDisplayAware
+ components will update accordingly to reflect the new display.
+ """
+ .trimIndent(),
+ category = Category.CORRECTNESS,
+ priority = 8,
+ severity = Severity.ERROR,
+ implementation =
+ Implementation(ShadeDisplayAwareDetector::class.java, Scope.JAVA_FILE_SCOPE),
+ )
+ }
+}
diff --git a/packages/SystemUI/checks/src/com/android/internal/systemui/lint/SystemUIIssueRegistry.kt b/packages/SystemUI/checks/src/com/android/internal/systemui/lint/SystemUIIssueRegistry.kt
index a1f4f55..6d18f93 100644
--- a/packages/SystemUI/checks/src/com/android/internal/systemui/lint/SystemUIIssueRegistry.kt
+++ b/packages/SystemUI/checks/src/com/android/internal/systemui/lint/SystemUIIssueRegistry.kt
@@ -46,8 +46,9 @@
DemotingTestWithoutBugDetector.ISSUE,
TestFunctionNameViolationDetector.ISSUE,
MissingApacheLicenseDetector.ISSUE,
+ ShadeDisplayAwareDetector.ISSUE,
RegisterContentObserverSyncViaSettingsProxyDetector.SYNC_WARNING,
- RegisterContentObserverViaContentResolverDetector.CONTENT_RESOLVER_ERROR
+ RegisterContentObserverViaContentResolverDetector.CONTENT_RESOLVER_ERROR,
)
override val api: Int
@@ -60,6 +61,6 @@
Vendor(
vendorName = "Android",
feedbackUrl = "http://b/issues/new?component=78010",
- contact = "jernej@google.com"
+ contact = "jernej@google.com",
)
}
diff --git a/packages/SystemUI/checks/tests/com/android/internal/systemui/lint/ShadeDisplayAwareDetectorTest.kt b/packages/SystemUI/checks/tests/com/android/internal/systemui/lint/ShadeDisplayAwareDetectorTest.kt
new file mode 100644
index 0000000..58ad363
--- /dev/null
+++ b/packages/SystemUI/checks/tests/com/android/internal/systemui/lint/ShadeDisplayAwareDetectorTest.kt
@@ -0,0 +1,375 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+package com.android.internal.systemui.lint
+
+import com.android.tools.lint.checks.infrastructure.TestFile
+import com.android.tools.lint.checks.infrastructure.TestFiles
+import com.android.tools.lint.checks.infrastructure.TestMode
+import com.android.tools.lint.detector.api.Detector
+import com.android.tools.lint.detector.api.Issue
+import org.junit.Test
+
+class ShadeDisplayAwareDetectorTest : SystemUILintDetectorTest() {
+ override fun getDetector(): Detector = ShadeDisplayAwareDetector()
+
+ override fun getIssues(): List<Issue> = listOf(ShadeDisplayAwareDetector.ISSUE)
+
+ private val qsContext: TestFile =
+ java(
+ """
+ package com.android.systemui.qs.dagger;
+
+ import static java.lang.annotation.RetentionPolicy.RUNTIME;
+
+ import java.lang.annotation.Retention;
+
+ @Retention(RUNTIME) public @interface QSThemedContext {}
+ """
+ )
+ .indented()
+
+ private val injectStub: TestFile =
+ kotlin(
+ """
+ package javax.inject
+
+ @Retention(AnnotationRetention.RUNTIME) annotation class Inject
+ """
+ )
+ .indented()
+
+ private val shadeDisplayAwareStub: TestFile =
+ kotlin(
+ """
+ package com.android.systemui.shade
+
+ @Retention(AnnotationRetention.RUNTIME) annotation class ShadeDisplayAware
+ """
+ )
+ .indented()
+
+ private val configStateStub: TestFile =
+ kotlin(
+ """
+ package com.android.systemui.common.ui
+
+ class ConfigurationState
+ """
+ )
+ .indented()
+
+ private val configControllerStub: TestFile =
+ kotlin(
+ """
+ package com.android.systemui.statusbar.policy
+
+ class ConfigurationController
+ """
+ )
+ .indented()
+
+ private val configInteractorStub: TestFile =
+ kotlin(
+ """
+ package com.android.systemui.common.ui.domain.interactor
+
+ class ConfigurationInteractor
+ """
+ )
+ .indented()
+
+ private val otherStubs =
+ arrayOf(
+ injectStub,
+ qsContext,
+ shadeDisplayAwareStub,
+ configStateStub,
+ configControllerStub,
+ configInteractorStub,
+ )
+
+ @Test
+ fun injectedConstructor_inRelevantPackage_withRelevantParameter_withoutAnnotation() {
+ lint()
+ .files(
+ TestFiles.kotlin(
+ """
+ package com.android.systemui.shade.example
+
+ import javax.inject.Inject
+ import android.content.Context
+
+ class ExampleClass
+ @Inject
+ constructor(private val context: Context)
+ """
+ .trimIndent()
+ ),
+ *androidStubs,
+ *otherStubs,
+ )
+ .issues(ShadeDisplayAwareDetector.ISSUE)
+ .testModes(TestMode.DEFAULT)
+ .run()
+ .expectErrorCount(1)
+ .expectContains(errorMsgString(8, "Context"))
+ .expectContains("[ShadeDisplayAwareContextChecker]")
+ .expectContains(
+ "constructor(private val context: Context)\n" +
+ " ~~~~~~~~~~~~~~~~~~~~~~~~~~~~"
+ )
+ .expectContains("1 errors, 0 warnings")
+ }
+
+ @Test
+ fun injectedConstructor_inRelevantPackage_withMultipleRelevantParameters_withoutAnnotation() {
+ lint()
+ .files(
+ TestFiles.kotlin(
+ """
+ package com.android.systemui.shade.example
+
+ import javax.inject.Inject
+ import android.content.Context
+ import android.content.res.Resources
+ import android.view.LayoutInflater
+ import android.view.WindowManager
+ import com.android.systemui.common.ui.ConfigurationState
+ import com.android.systemui.common.ui.domain.interactor.ConfigurationInteractor
+ import com.android.systemui.statusbar.policy.ConfigurationController
+
+ class ExampleClass
+ @Inject
+ constructor(
+ private val context: Context,
+ private val inflater: LayoutInflater,
+ private val windowManager: WindowManager,
+ private val configState: ConfigurationState,
+ private val configController: ConfigurationController,
+ private val configInteractor: ConfigurationInteractor,
+ )
+ """
+ .trimIndent()
+ ),
+ *androidStubs,
+ *otherStubs,
+ )
+ .issues(ShadeDisplayAwareDetector.ISSUE)
+ .testModes(TestMode.DEFAULT)
+ .run()
+ .expectErrorCount(6)
+ .expectContains(errorMsgString(lineNumber = 15, className = "Context"))
+ .expectContains(
+ "private val context: Context,\n" + " ~~~~~~~~~~~~~~~~~~~~~~~~~~~~"
+ )
+ .expectContains(errorMsgString(lineNumber = 16, className = "LayoutInflater"))
+ .expectContains(
+ "private val inflater: LayoutInflater,\n" +
+ " ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"
+ )
+ .expectContains(errorMsgString(lineNumber = 17, className = "WindowManager"))
+ .expectContains(
+ "private val windowManager: WindowManager,\n" +
+ " ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"
+ )
+ .expectContains(errorMsgString(lineNumber = 18, className = "ConfigurationState"))
+ .expectContains(
+ "private val configState: ConfigurationState,\n" +
+ " ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"
+ )
+ .expectContains(errorMsgString(lineNumber = 19, className = "ConfigurationController"))
+ .expectContains(
+ "private val configController: ConfigurationController,\n" +
+ " ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"
+ )
+ .expectContains(errorMsgString(lineNumber = 20, className = "ConfigurationInteractor"))
+ .expectContains(
+ "private val configInteractor: ConfigurationInteractor,\n" +
+ " ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"
+ )
+ .expectContains(" [ShadeDisplayAwareContextChecker]")
+ }
+
+ @Test
+ fun injectedConstructor_inRelevantPackage_withRelevantParameter_withAnnotation() {
+ lint()
+ .files(
+ TestFiles.kotlin(
+ """
+ package com.android.systemui.shade.example
+
+ import javax.inject.Inject
+ import android.content.Context
+ import com.android.systemui.shade.ShadeDisplayAware
+
+ class ExampleClass
+ @Inject
+ constructor(@ShadeDisplayAware private val context: Context)
+ """
+ .trimIndent()
+ ),
+ *androidStubs,
+ *otherStubs,
+ )
+ .issues(ShadeDisplayAwareDetector.ISSUE)
+ .testModes(TestMode.DEFAULT)
+ .run()
+ .expectClean()
+ }
+
+ @Test
+ fun injectedConstructor_inRelevantPackage_withoutRelevantParameter_withoutAnnotation() {
+ lint()
+ .files(
+ TestFiles.kotlin(
+ """
+ package com.android.systemui.shade.example
+
+ import javax.inject.Inject
+ import android.content.ContextWrapper
+
+ class ExampleClass
+ @Inject
+ constructor(private val contextWrapper: ContextWrapper)
+ """
+ .trimIndent()
+ ),
+ *androidStubs,
+ *otherStubs,
+ )
+ .issues(ShadeDisplayAwareDetector.ISSUE)
+ .testModes(TestMode.DEFAULT)
+ .run()
+ .expectClean()
+ }
+
+ @Test
+ fun injectedConstructor_notInRelevantPackage_withRelevantParameter_withoutAnnotation() {
+ lint()
+ .files(
+ TestFiles.kotlin(
+ """
+ package com.android.systemui.keyboard
+
+ import javax.inject.Inject
+ import android.content.Context
+
+ class ExampleClass @Inject constructor(private val context: Context)
+ """
+ .trimIndent()
+ ),
+ *androidStubs,
+ *otherStubs,
+ )
+ .issues(ShadeDisplayAwareDetector.ISSUE)
+ .testModes(TestMode.DEFAULT)
+ .run()
+ .expectClean()
+ }
+
+ @Test
+ fun nonInjectedConstructor_inRelevantPackage_withRelevantParameter_withoutAnnotation() {
+ lint()
+ .files(
+ TestFiles.kotlin(
+ """
+ package com.android.systemui.shade.example
+
+ import android.content.Context
+
+ class ExampleClass(private val context: Context)
+ """
+ .trimIndent()
+ ),
+ *androidStubs,
+ *otherStubs,
+ )
+ .issues(ShadeDisplayAwareDetector.ISSUE)
+ .testModes(TestMode.DEFAULT)
+ .run()
+ .expectClean()
+ }
+
+ @Test
+ fun injectedConstructor_inRelevantPackage_withRelevantParameter_withoutAnnotation_suppressed() {
+ lint()
+ .files(
+ TestFiles.kotlin(
+ """
+ package com.android.systemui.shade.example
+
+ import javax.inject.Inject
+ import android.content.Context
+
+ @Suppress("ShadeDisplayAwareContextChecker")
+ class ExampleClass
+ @Inject
+ constructor(
+ private val context: Context
+ )
+ """
+ .trimIndent()
+ ),
+ *androidStubs,
+ *otherStubs,
+ )
+ .issues(ShadeDisplayAwareDetector.ISSUE)
+ .testModes(TestMode.DEFAULT)
+ .run()
+ .expectClean()
+ }
+
+ @Test
+ fun injectedConstructor_inExemptPackage_withRelevantParameter_withoutAnnotation() {
+ lint()
+ .files(
+ TestFiles.java(
+ """
+ package com.android.systemui.qs.customize;
+
+ import javax.inject.Inject;
+ import com.android.systemui.qs.dagger.QSThemedContext;
+ import android.content.Context;
+
+ public class TileAdapter {
+ @Inject
+ public TileAdapter(@QSThemedContext Context context) {}
+ }
+ """
+ .trimIndent()
+ ),
+ *androidStubs,
+ *otherStubs,
+ )
+ .issues(ShadeDisplayAwareDetector.ISSUE)
+ .testModes(TestMode.DEFAULT)
+ .run()
+ .expectClean()
+ }
+
+ private fun errorMsgString(lineNumber: Int, className: String) =
+ """
+ src/com/android/systemui/shade/example/ExampleClass.kt:$lineNumber: Error: UI elements of the shade window
+ should use ShadeDisplayAware-annotated $className, as the shade might move between windows, and only
+ @ShadeDisplayAware resources are updated with the new configuration correctly. Failures to do so
+ might result in wrong dimensions for shade window classes (e.g. using the wrong density or theme).
+ If the usage of $className is not related to display specific configuration or UI, then there is
+ technically no need to use the annotation, and you can annotate the class with
+ @SuppressLint("ShadeDisplayAwareContextChecker")/@Suppress("ShadeDisplayAwareContextChecker")
+ """
+}
diff --git a/packages/SystemUI/compose/features/src/com/android/systemui/communal/ui/compose/CommunalHub.kt b/packages/SystemUI/compose/features/src/com/android/systemui/communal/ui/compose/CommunalHub.kt
index 787edfb..573e5ca 100644
--- a/packages/SystemUI/compose/features/src/com/android/systemui/communal/ui/compose/CommunalHub.kt
+++ b/packages/SystemUI/compose/features/src/com/android/systemui/communal/ui/compose/CommunalHub.kt
@@ -66,6 +66,7 @@
import androidx.compose.foundation.layout.wrapContentHeight
import androidx.compose.foundation.lazy.grid.GridCells
import androidx.compose.foundation.lazy.grid.GridItemSpan
+import androidx.compose.foundation.lazy.grid.LazyGridScope
import androidx.compose.foundation.lazy.grid.LazyGridState
import androidx.compose.foundation.lazy.grid.LazyHorizontalGrid
import androidx.compose.foundation.lazy.grid.itemsIndexed
@@ -169,6 +170,7 @@
import com.android.compose.ui.graphics.painter.rememberDrawablePainter
import com.android.internal.R.dimen.system_app_widget_background_radius
import com.android.systemui.Flags
+import com.android.systemui.Flags.communalResponsiveGrid
import com.android.systemui.Flags.communalTimerFlickerFix
import com.android.systemui.Flags.communalWidgetResizing
import com.android.systemui.communal.domain.model.CommunalContentModel
@@ -194,7 +196,6 @@
import com.android.systemui.statusbar.phone.SystemUIDialogFactory
import kotlin.math.max
import kotlin.math.min
-import kotlin.math.roundToInt
import kotlinx.coroutines.delay
import kotlinx.coroutines.launch
@@ -693,7 +694,12 @@
onResize = onResize,
minHeightPx = minHeightPx,
maxHeightPx = maxHeightPx,
- resizeMultiple = CommunalContentSize.HALF.span,
+ resizeMultiple =
+ if (communalResponsiveGrid()) {
+ 1
+ } else {
+ CommunalContentSize.FixedSize.HALF.span
+ },
) {
content(Modifier)
}
@@ -701,14 +707,22 @@
}
@Composable
-fun calculateWidgetSize(item: CommunalContentModel, isResizable: Boolean): WidgetSizeInfo {
+fun calculateWidgetSize(
+ cellHeight: Dp?,
+ availableHeight: Dp?,
+ item: CommunalContentModel,
+ isResizable: Boolean,
+): WidgetSizeInfo {
val density = LocalDensity.current
+ val minHeight = cellHeight ?: CommunalContentSize.FixedSize.HALF.dp()
+ val maxHeight = availableHeight ?: CommunalContentSize.FixedSize.FULL.dp()
+
return if (isResizable && item is CommunalContentModel.WidgetContent.Widget) {
with(density) {
val minHeightPx =
(min(item.providerInfo.minResizeHeight, item.providerInfo.minHeight)
- .coerceAtLeast(CommunalContentSize.HALF.dp().toPx().roundToInt()))
+ .coerceAtLeast(minHeight.roundToPx()))
val maxHeightPx =
(if (item.providerInfo.maxResizeHeight > 0) {
@@ -716,7 +730,7 @@
} else {
Int.MAX_VALUE
})
- .coerceIn(minHeightPx, CommunalContentSize.FULL.dp().toPx().roundToInt())
+ .coerceIn(minHeightPx, maxHeight.roundToPx())
WidgetSizeInfo(minHeightPx, maxHeightPx)
}
@@ -725,6 +739,37 @@
}
}
+@Composable
+private fun HorizontalGridWrapper(
+ contentPadding: PaddingValues,
+ gridState: LazyGridState,
+ modifier: Modifier = Modifier,
+ content: LazyGridScope.(sizeInfo: SizeInfo?) -> Unit,
+) {
+ if (communalResponsiveGrid()) {
+ ResponsiveLazyHorizontalGrid(
+ cellAspectRatio = 1.5f,
+ modifier = modifier,
+ state = gridState,
+ minContentPadding = contentPadding,
+ minHorizontalArrangement = Dimensions.ItemSpacing,
+ minVerticalArrangement = Dimensions.ItemSpacing,
+ content = content,
+ )
+ } else {
+ LazyHorizontalGrid(
+ modifier = modifier,
+ state = gridState,
+ rows = GridCells.Fixed(CommunalContentSize.FixedSize.FULL.span),
+ contentPadding = contentPadding,
+ horizontalArrangement = Arrangement.spacedBy(Dimensions.ItemSpacing),
+ verticalArrangement = Arrangement.spacedBy(Dimensions.ItemSpacing),
+ ) {
+ content(null)
+ }
+ }
+}
+
@OptIn(ExperimentalFoundationApi::class)
@Composable
private fun BoxScope.CommunalHubLazyGrid(
@@ -778,28 +823,32 @@
// Since the grid has its own listener for in-grid drag events, we use a separate element
// for android drag events.
Box(Modifier.fillMaxSize().dragAndDropTarget(dragAndDropTargetState)) {}
+ } else if (communalResponsiveGrid()) {
+ gridModifier = gridModifier.fillMaxSize()
} else {
gridModifier = gridModifier.height(hubDimensions.GridHeight)
}
- val itemArrangement = Arrangement.spacedBy(Dimensions.ItemSpacing)
- LazyHorizontalGrid(
+ HorizontalGridWrapper(
modifier = gridModifier,
- state = gridState,
- rows = GridCells.Fixed(CommunalContentSize.FULL.span),
+ gridState = gridState,
contentPadding = contentPadding,
- horizontalArrangement = itemArrangement,
- verticalArrangement = itemArrangement,
- ) {
+ ) { sizeInfo ->
itemsIndexed(
items = list,
key = { _, item -> item.key },
contentType = { _, item -> item.key },
- span = { _, item -> GridItemSpan(item.size.span) },
+ span = { _, item -> GridItemSpan(item.getSpanOrMax(sizeInfo?.gridSize?.height)) },
) { index, item ->
- val size = SizeF(Dimensions.CardWidth.value, item.size.dp().value)
+ val currentItemSpan = item.getSpanOrMax(sizeInfo?.gridSize?.height)
+ val dpSize =
+ if (sizeInfo != null) {
+ DpSize(sizeInfo.cellSize.width, sizeInfo.calculateHeight(currentItemSpan))
+ } else {
+ DpSize(Dimensions.CardWidth, (item.size as CommunalContentSize.FixedSize).dp())
+ }
+ val size = SizeF(dpSize.width.value, dpSize.height.value)
val selected = item.key == selectedKey.value
- val dpSize = DpSize(size.width.dp, size.height.dp)
val isResizable =
if (item is CommunalContentModel.WidgetContent.Widget) {
item.providerInfo.resizeMode and AppWidgetProviderInfo.RESIZE_VERTICAL != 0
@@ -809,7 +858,7 @@
val resizeableItemFrameViewModel =
rememberViewModel(
- key = item.size.span,
+ key = currentItemSpan,
traceName = "ResizeableItemFrame.viewModel.$index",
) {
ResizeableItemFrameViewModel()
@@ -822,13 +871,23 @@
animationSpec = spring(stiffness = Spring.StiffnessMediumLow),
label = "Widget resizing outline alpha",
)
- val widgetSizeInfo = calculateWidgetSize(item, isResizable)
+
+ val widgetSizeInfo =
+ calculateWidgetSize(
+ cellHeight = sizeInfo?.cellSize?.height,
+ availableHeight = sizeInfo?.availableHeight,
+ item = item,
+ isResizable = isResizable,
+ )
ResizableItemFrameWrapper(
key = item.key,
- currentSpan = GridItemSpan(item.size.span),
+ currentSpan = GridItemSpan(currentItemSpan),
gridState = gridState,
gridContentPadding = contentPadding,
- verticalArrangement = itemArrangement,
+ verticalArrangement =
+ Arrangement.spacedBy(
+ sizeInfo?.verticalArrangement ?: Dimensions.ItemSpacing
+ ),
enabled = selected,
alpha = { outlineAlpha },
modifier =
@@ -908,7 +967,7 @@
text = titleForEmptyStateCTA,
style = MaterialTheme.typography.displaySmall,
textAlign = TextAlign.Center,
- color = colors.secondary,
+ color = colors.primary,
modifier =
Modifier.focusable().semantics(mergeDescendants = true) {
contentDescription = titleForEmptyStateCTA
@@ -1686,11 +1745,11 @@
}
}
-private fun CommunalContentSize.dp(): Dp {
+private fun CommunalContentSize.FixedSize.dp(): Dp {
return when (this) {
- CommunalContentSize.FULL -> Dimensions.CardHeightFull
- CommunalContentSize.HALF -> Dimensions.CardHeightHalf
- CommunalContentSize.THIRD -> Dimensions.CardHeightThird
+ CommunalContentSize.FixedSize.FULL -> Dimensions.CardHeightFull
+ CommunalContentSize.FixedSize.HALF -> Dimensions.CardHeightHalf
+ CommunalContentSize.FixedSize.THIRD -> Dimensions.CardHeightThird
}
}
@@ -1709,7 +1768,10 @@
val GridTopSpacing: Dp
get() {
val result =
- if (config.orientation == Configuration.ORIENTATION_LANDSCAPE) {
+ if (
+ communalResponsiveGrid() ||
+ config.orientation == Configuration.ORIENTATION_LANDSCAPE
+ ) {
114.dp
} else {
val windowMetrics =
@@ -1729,7 +1791,7 @@
get() = 530.adjustedDp
val ItemSpacing
- get() = 50.adjustedDp
+ get() = if (communalResponsiveGrid()) 32.adjustedDp else 50.adjustedDp
val CardHeightHalf
get() = (CardHeightFull - ItemSpacing) / 2
@@ -1771,6 +1833,13 @@
data class WidgetSizeInfo(val minHeightPx: Int, val maxHeightPx: Int)
+private fun CommunalContentModel.getSpanOrMax(maxSpan: Int?) =
+ if (maxSpan != null) {
+ size.span.coerceAtMost(maxSpan)
+ } else {
+ size.span
+ }
+
private object Colors {
val DisabledColorFilter by lazy { disabledColorMatrix() }
diff --git a/packages/SystemUI/compose/features/src/com/android/systemui/communal/ui/compose/ResponsiveLazyHorizontalGrid.kt b/packages/SystemUI/compose/features/src/com/android/systemui/communal/ui/compose/ResponsiveLazyHorizontalGrid.kt
index e331078..3642127 100644
--- a/packages/SystemUI/compose/features/src/com/android/systemui/communal/ui/compose/ResponsiveLazyHorizontalGrid.kt
+++ b/packages/SystemUI/compose/features/src/com/android/systemui/communal/ui/compose/ResponsiveLazyHorizontalGrid.kt
@@ -147,9 +147,9 @@
SizeInfo(
cellSize = finalSize,
contentPadding = finalContentPadding,
- horizontalArrangement = minHorizontalArrangement,
verticalArrangement = minVerticalArrangement,
maxHeight = maxHeight,
+ gridSize = gridSize,
)
)
}
@@ -176,16 +176,15 @@
* Provides size info of the responsive grid, since the size is dynamic.
*
* @property cellSize The size of each cell in the grid.
- * @property contentPadding The final content padding of the grid.
- * @property horizontalArrangement The space between columns in the grid.
* @property verticalArrangement The space between rows in the grid.
+ * @property gridSize The size of the grid, in cell units.
* @property availableHeight The maximum height an item in the grid may occupy.
*/
data class SizeInfo(
val cellSize: DpSize,
- val contentPadding: PaddingValues,
- val horizontalArrangement: Dp,
val verticalArrangement: Dp,
+ val gridSize: IntSize,
+ private val contentPadding: PaddingValues,
private val maxHeight: Dp,
) {
val availableHeight: Dp
@@ -193,6 +192,11 @@
maxHeight -
contentPadding.calculateBottomPadding() -
contentPadding.calculateTopPadding()
+
+ /** Calculates the height in dp of a certain number of rows. */
+ fun calculateHeight(numRows: Int): Dp {
+ return numRows * cellSize.height + (numRows - 1) * verticalArrangement
+ }
}
@Composable
diff --git a/packages/SystemUI/customization/src/com/android/systemui/shared/clocks/ClockDesign.kt b/packages/SystemUI/customization/src/com/android/systemui/shared/clocks/ClockDesign.kt
index bcf055b..15373d3 100644
--- a/packages/SystemUI/customization/src/com/android/systemui/shared/clocks/ClockDesign.kt
+++ b/packages/SystemUI/customization/src/com/android/systemui/shared/clocks/ClockDesign.kt
@@ -33,7 +33,7 @@
val thumbnail: String? = null,
val large: ClockFace? = null,
val small: ClockFace? = null,
- val colorPalette: MonetStyle? = null,
+ @MonetStyle.Type val colorPalette: Int? = null,
)
/** Describes a clock using layers */
diff --git a/packages/SystemUI/lint-baseline.xml b/packages/SystemUI/lint-baseline.xml
index 7577147..42694d5 100644
--- a/packages/SystemUI/lint-baseline.xml
+++ b/packages/SystemUI/lint-baseline.xml
@@ -32784,4 +32784,972 @@
column="23"/>
</issue>
+ <issue
+ id="ShadeDisplayAwareContextChecker"
+ message="UI elements of the shade window
should use ShadeDisplayAware-annotated Resources, as the shade might move between windows, and only
@ShadeDisplayAware resources are updated with the new configuration correctly. Failures to do so
might result in wrong dimensions for shade window classes (e.g. using the wrong density or theme).
If the usage of Resources is not related to display specific configuration or UI, then there is
technically no need to use the annotation, and you can annotate the class with
@SuppressLint("ShadeDisplayAwareContextChecker")/@Suppress("ShadeDisplayAwareContextChecker")"
+ errorLine1="constructor(@Main private val resources: Resources, val theme: Theme) :"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/qs/tiles/impl/airplane/domain/AirplaneModeMapper.kt"
+ line="33"
+ column="13"/>
+ </issue>
+
+ <issue
+ id="ShadeDisplayAwareContextChecker"
+ message="UI elements of the shade window
should use ShadeDisplayAware-annotated Resources, as the shade might move between windows, and only
@ShadeDisplayAware resources are updated with the new configuration correctly. Failures to do so
might result in wrong dimensions for shade window classes (e.g. using the wrong density or theme).
If the usage of Resources is not related to display specific configuration or UI, then there is
technically no need to use the annotation, and you can annotate the class with
@SuppressLint("ShadeDisplayAwareContextChecker")/@Suppress("ShadeDisplayAwareContextChecker")"
+ errorLine1=" @Main private val resources: Resources,"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/qs/tiles/impl/alarm/domain/AlarmTileMapper.kt"
+ line="39"
+ column="5"/>
+ </issue>
+
+ <issue
+ id="ShadeDisplayAwareContextChecker"
+ message="UI elements of the shade window
should use ShadeDisplayAware-annotated Context, as the shade might move between windows, and only
@ShadeDisplayAware resources are updated with the new configuration correctly. Failures to do so
might result in wrong dimensions for shade window classes (e.g. using the wrong density or theme).
If the usage of Context is not related to display specific configuration or UI, then there is
technically no need to use the annotation, and you can annotate the class with
@SuppressLint("ShadeDisplayAwareContextChecker")/@Suppress("ShadeDisplayAwareContextChecker")"
+ errorLine1=" @NonNull Context context,"
+ errorLine2=" ~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/AmbientState.java"
+ line="300"
+ column="30"/>
+ </issue>
+
+ <issue
+ id="ShadeDisplayAwareContextChecker"
+ message="UI elements of the shade window
should use ShadeDisplayAware-annotated Context, as the shade might move between windows, and only
@ShadeDisplayAware resources are updated with the new configuration correctly. Failures to do so
might result in wrong dimensions for shade window classes (e.g. using the wrong density or theme).
If the usage of Context is not related to display specific configuration or UI, then there is
technically no need to use the annotation, and you can annotate the class with
@SuppressLint("ShadeDisplayAwareContextChecker")/@Suppress("ShadeDisplayAwareContextChecker")"
+ errorLine1=" Context context, DeviceConfigProxy proxy) {"
+ errorLine2=" ~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/statusbar/notification/AssistantFeedbackController.java"
+ line="75"
+ column="21"/>
+ </issue>
+
+ <issue
+ id="ShadeDisplayAwareContextChecker"
+ message="UI elements of the shade window
should use ShadeDisplayAware-annotated Context, as the shade might move between windows, and only
@ShadeDisplayAware resources are updated with the new configuration correctly. Failures to do so
might result in wrong dimensions for shade window classes (e.g. using the wrong density or theme).
If the usage of Context is not related to display specific configuration or UI, then there is
technically no need to use the annotation, and you can annotate the class with
@SuppressLint("ShadeDisplayAwareContextChecker")/@Suppress("ShadeDisplayAwareContextChecker")"
+ errorLine1=" public AuthController(Context context,"
+ errorLine2=" ~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/biometrics/AuthController.java"
+ line="716"
+ column="35"/>
+ </issue>
+
+ <issue
+ id="ShadeDisplayAwareContextChecker"
+ message="UI elements of the shade window
should use ShadeDisplayAware-annotated WindowManager, as the shade might move between windows, and only
@ShadeDisplayAware resources are updated with the new configuration correctly. Failures to do so
might result in wrong dimensions for shade window classes (e.g. using the wrong density or theme).
If the usage of WindowManager is not related to display specific configuration or UI, then there is
technically no need to use the annotation, and you can annotate the class with
@SuppressLint("ShadeDisplayAwareContextChecker")/@Suppress("ShadeDisplayAwareContextChecker")"
+ errorLine1=" @NonNull WindowManager windowManager,"
+ errorLine2=" ~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/biometrics/AuthController.java"
+ line="721"
+ column="36"/>
+ </issue>
+
+ <issue
+ id="ShadeDisplayAwareContextChecker"
+ message="UI elements of the shade window
should use ShadeDisplayAware-annotated Context, as the shade might move between windows, and only
@ShadeDisplayAware resources are updated with the new configuration correctly. Failures to do so
might result in wrong dimensions for shade window classes (e.g. using the wrong density or theme).
If the usage of Context is not related to display specific configuration or UI, then there is
technically no need to use the annotation, and you can annotate the class with
@SuppressLint("ShadeDisplayAwareContextChecker")/@Suppress("ShadeDisplayAwareContextChecker")"
+ errorLine1=" private val sysuiContext: Context,"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/biometrics/AuthRippleController.kt"
+ line="72"
+ column="5"/>
+ </issue>
+
+ <issue
+ id="ShadeDisplayAwareContextChecker"
+ message="UI elements of the shade window
should use ShadeDisplayAware-annotated ConfigurationController, as the shade might move between windows, and only
@ShadeDisplayAware resources are updated with the new configuration correctly. Failures to do so
might result in wrong dimensions for shade window classes (e.g. using the wrong density or theme).
If the usage of ConfigurationController is not related to display specific configuration or UI, then there is
technically no need to use the annotation, and you can annotate the class with
@SuppressLint("ShadeDisplayAwareContextChecker")/@Suppress("ShadeDisplayAwareContextChecker")"
+ errorLine1=" private val configurationController: ConfigurationController,"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/biometrics/AuthRippleController.kt"
+ line="74"
+ column="5"/>
+ </issue>
+
+ <issue
+ id="ShadeDisplayAwareContextChecker"
+ message="UI elements of the shade window
should use ShadeDisplayAware-annotated Resources, as the shade might move between windows, and only
@ShadeDisplayAware resources are updated with the new configuration correctly. Failures to do so
might result in wrong dimensions for shade window classes (e.g. using the wrong density or theme).
If the usage of Resources is not related to display specific configuration or UI, then there is
technically no need to use the annotation, and you can annotate the class with
@SuppressLint("ShadeDisplayAwareContextChecker")/@Suppress("ShadeDisplayAwareContextChecker")"
+ errorLine1="constructor(@Main protected val resources: Resources, private val theme: Resources.Theme) :"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/qs/tiles/impl/battery/ui/BatterySaverTileMapper.kt"
+ line="32"
+ column="13"/>
+ </issue>
+
+ <issue
+ id="ShadeDisplayAwareContextChecker"
+ message="UI elements of the shade window
should use ShadeDisplayAware-annotated Context, as the shade might move between windows, and only
@ShadeDisplayAware resources are updated with the new configuration correctly. Failures to do so
might result in wrong dimensions for shade window classes (e.g. using the wrong density or theme).
If the usage of Context is not related to display specific configuration or UI, then there is
technically no need to use the annotation, and you can annotate the class with
@SuppressLint("ShadeDisplayAwareContextChecker")/@Suppress("ShadeDisplayAwareContextChecker")"
+ errorLine1=" Context context,"
+ errorLine2=" ~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/biometrics/BiometricNotificationBroadcastReceiver.java"
+ line="46"
+ column="21"/>
+ </issue>
+
+ <issue
+ id="ShadeDisplayAwareContextChecker"
+ message="UI elements of the shade window
should use ShadeDisplayAware-annotated Resources, as the shade might move between windows, and only
@ShadeDisplayAware resources are updated with the new configuration correctly. Failures to do so
might result in wrong dimensions for shade window classes (e.g. using the wrong density or theme).
If the usage of Resources is not related to display specific configuration or UI, then there is
technically no need to use the annotation, and you can annotate the class with
@SuppressLint("ShadeDisplayAwareContextChecker")/@Suppress("ShadeDisplayAwareContextChecker")"
+ errorLine1=" @Main Resources resources,"
+ errorLine2=" ~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/biometrics/BiometricNotificationDialogFactory.java"
+ line="52"
+ column="29"/>
+ </issue>
+
+ <issue
+ id="ShadeDisplayAwareContextChecker"
+ message="UI elements of the shade window
should use ShadeDisplayAware-annotated Context, as the shade might move between windows, and only
@ShadeDisplayAware resources are updated with the new configuration correctly. Failures to do so
might result in wrong dimensions for shade window classes (e.g. using the wrong density or theme).
If the usage of Context is not related to display specific configuration or UI, then there is
technically no need to use the annotation, and you can annotate the class with
@SuppressLint("ShadeDisplayAwareContextChecker")/@Suppress("ShadeDisplayAwareContextChecker")"
+ errorLine1=" public BiometricNotificationService(@NonNull Context context,"
+ errorLine2=" ~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/biometrics/BiometricNotificationService.java"
+ line="148"
+ column="58"/>
+ </issue>
+
+ <issue
+ id="ShadeDisplayAwareContextChecker"
+ message="UI elements of the shade window
should use ShadeDisplayAware-annotated Context, as the shade might move between windows, and only
@ShadeDisplayAware resources are updated with the new configuration correctly. Failures to do so
might result in wrong dimensions for shade window classes (e.g. using the wrong density or theme).
If the usage of Context is not related to display specific configuration or UI, then there is
technically no need to use the annotation, and you can annotate the class with
@SuppressLint("ShadeDisplayAwareContextChecker")/@Suppress("ShadeDisplayAwareContextChecker")"
+ errorLine1=" @Application private val applicationContext: Context,"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/bouncer/domain/interactor/BouncerActionButtonInteractor.kt"
+ line="62"
+ column="5"/>
+ </issue>
+
+ <issue
+ id="ShadeDisplayAwareContextChecker"
+ message="UI elements of the shade window
should use ShadeDisplayAware-annotated Context, as the shade might move between windows, and only
@ShadeDisplayAware resources are updated with the new configuration correctly. Failures to do so
might result in wrong dimensions for shade window classes (e.g. using the wrong density or theme).
If the usage of Context is not related to display specific configuration or UI, then there is
technically no need to use the annotation, and you can annotate the class with
@SuppressLint("ShadeDisplayAwareContextChecker")/@Suppress("ShadeDisplayAwareContextChecker")"
+ errorLine1=" @Application private val applicationContext: Context,"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/bouncer/data/repository/BouncerRepository.kt"
+ line="37"
+ column="5"/>
+ </issue>
+
+ <issue
+ id="ShadeDisplayAwareContextChecker"
+ message="UI elements of the shade window
should use ShadeDisplayAware-annotated Context, as the shade might move between windows, and only
@ShadeDisplayAware resources are updated with the new configuration correctly. Failures to do so
might result in wrong dimensions for shade window classes (e.g. using the wrong density or theme).
If the usage of Context is not related to display specific configuration or UI, then there is
technically no need to use the annotation, and you can annotate the class with
@SuppressLint("ShadeDisplayAwareContextChecker")/@Suppress("ShadeDisplayAwareContextChecker")"
+ errorLine1=" c: Context,"
+ errorLine2=" ~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ChannelEditorDialogController.kt"
+ line="61"
+ column="5"/>
+ </issue>
+
+ <issue
+ id="ShadeDisplayAwareContextChecker"
+ message="UI elements of the shade window
should use ShadeDisplayAware-annotated Resources, as the shade might move between windows, and only
@ShadeDisplayAware resources are updated with the new configuration correctly. Failures to do so
might result in wrong dimensions for shade window classes (e.g. using the wrong density or theme).
If the usage of Resources is not related to display specific configuration or UI, then there is
technically no need to use the annotation, and you can annotate the class with
@SuppressLint("ShadeDisplayAwareContextChecker")/@Suppress("ShadeDisplayAwareContextChecker")"
+ errorLine1="constructor(@Main private val resources: Resources, private val theme: Resources.Theme) :"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/qs/tiles/impl/colorcorrection/domain/ColorCorrectionTileMapper.kt"
+ line="32"
+ column="13"/>
+ </issue>
+
+ <issue
+ id="ShadeDisplayAwareContextChecker"
+ message="UI elements of the shade window
should use ShadeDisplayAware-annotated Resources, as the shade might move between windows, and only
@ShadeDisplayAware resources are updated with the new configuration correctly. Failures to do so
might result in wrong dimensions for shade window classes (e.g. using the wrong density or theme).
If the usage of Resources is not related to display specific configuration or UI, then there is
technically no need to use the annotation, and you can annotate the class with
@SuppressLint("ShadeDisplayAwareContextChecker")/@Suppress("ShadeDisplayAwareContextChecker")"
+ errorLine1="constructor(@Main private val resources: Resources, private val theme: Theme) :"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/qs/tiles/impl/inversion/domain/ColorInversionTileMapper.kt"
+ line="33"
+ column="13"/>
+ </issue>
+
+ <issue
+ id="ShadeDisplayAwareContextChecker"
+ message="UI elements of the shade window
should use ShadeDisplayAware-annotated Context, as the shade might move between windows, and only
@ShadeDisplayAware resources are updated with the new configuration correctly. Failures to do so
might result in wrong dimensions for shade window classes (e.g. using the wrong density or theme).
If the usage of Context is not related to display specific configuration or UI, then there is
technically no need to use the annotation, and you can annotate the class with
@SuppressLint("ShadeDisplayAwareContextChecker")/@Suppress("ShadeDisplayAwareContextChecker")"
+ errorLine1=" @Application private val applicationContext: Context,"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/biometrics/domain/interactor/CredentialInteractor.kt"
+ line="52"
+ column="5"/>
+ </issue>
+
+ <issue
+ id="ShadeDisplayAwareContextChecker"
+ message="UI elements of the shade window
should use ShadeDisplayAware-annotated Context, as the shade might move between windows, and only
@ShadeDisplayAware resources are updated with the new configuration correctly. Failures to do so
might result in wrong dimensions for shade window classes (e.g. using the wrong density or theme).
If the usage of Context is not related to display specific configuration or UI, then there is
technically no need to use the annotation, and you can annotate the class with
@SuppressLint("ShadeDisplayAwareContextChecker")/@Suppress("ShadeDisplayAwareContextChecker")"
+ errorLine1=" @Application private val applicationContext: Context,"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/biometrics/ui/viewmodel/CredentialViewModel.kt"
+ line="30"
+ column="5"/>
+ </issue>
+
+ <issue
+ id="ShadeDisplayAwareContextChecker"
+ message="UI elements of the shade window
should use ShadeDisplayAware-annotated Context, as the shade might move between windows, and only
@ShadeDisplayAware resources are updated with the new configuration correctly. Failures to do so
might result in wrong dimensions for shade window classes (e.g. using the wrong density or theme).
If the usage of Context is not related to display specific configuration or UI, then there is
technically no need to use the annotation, and you can annotate the class with
@SuppressLint("ShadeDisplayAwareContextChecker")/@Suppress("ShadeDisplayAwareContextChecker")"
+ errorLine1="class CustomTileStatePersisterImpl @Inject constructor(context: Context) :"
+ errorLine2=" ~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/qs/external/CustomTileStatePersister.kt"
+ line="74"
+ column="56"/>
+ </issue>
+
+ <issue
+ id="ShadeDisplayAwareContextChecker"
+ message="UI elements of the shade window
should use ShadeDisplayAware-annotated Resources, as the shade might move between windows, and only
@ShadeDisplayAware resources are updated with the new configuration correctly. Failures to do so
might result in wrong dimensions for shade window classes (e.g. using the wrong density or theme).
If the usage of Resources is not related to display specific configuration or UI, then there is
technically no need to use the annotation, and you can annotate the class with
@SuppressLint("ShadeDisplayAwareContextChecker")/@Suppress("ShadeDisplayAwareContextChecker")"
+ errorLine1="constructor(@Main private val resources: Resources, private val theme: Resources.Theme) :"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/qs/tiles/impl/saver/domain/DataSaverTileMapper.kt"
+ line="32"
+ column="13"/>
+ </issue>
+
+ <issue
+ id="ShadeDisplayAwareContextChecker"
+ message="UI elements of the shade window
should use ShadeDisplayAware-annotated Resources, as the shade might move between windows, and only
@ShadeDisplayAware resources are updated with the new configuration correctly. Failures to do so
might result in wrong dimensions for shade window classes (e.g. using the wrong density or theme).
If the usage of Resources is not related to display specific configuration or UI, then there is
technically no need to use the annotation, and you can annotate the class with
@SuppressLint("ShadeDisplayAwareContextChecker")/@Suppress("ShadeDisplayAwareContextChecker")"
+ errorLine1=" @Main private val resources: Resources,"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/qs/pipeline/data/repository/DefaultTilesRepository.kt"
+ line="18"
+ column="5"/>
+ </issue>
+
+ <issue
+ id="ShadeDisplayAwareContextChecker"
+ message="UI elements of the shade window
should use ShadeDisplayAware-annotated Context, as the shade might move between windows, and only
@ShadeDisplayAware resources are updated with the new configuration correctly. Failures to do so
might result in wrong dimensions for shade window classes (e.g. using the wrong density or theme).
If the usage of Context is not related to display specific configuration or UI, then there is
technically no need to use the annotation, and you can annotate the class with
@SuppressLint("ShadeDisplayAwareContextChecker")/@Suppress("ShadeDisplayAwareContextChecker")"
+ errorLine1=" @Application context: Context,"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/biometrics/domain/interactor/DisplayStateInteractor.kt"
+ line="77"
+ column="5"/>
+ </issue>
+
+ <issue
+ id="ShadeDisplayAwareContextChecker"
+ message="UI elements of the shade window
should use ShadeDisplayAware-annotated Context, as the shade might move between windows, and only
@ShadeDisplayAware resources are updated with the new configuration correctly. Failures to do so
might result in wrong dimensions for shade window classes (e.g. using the wrong density or theme).
If the usage of Context is not related to display specific configuration or UI, then there is
technically no need to use the annotation, and you can annotate the class with
@SuppressLint("ShadeDisplayAwareContextChecker")/@Suppress("ShadeDisplayAwareContextChecker")"
+ errorLine1=" @Application val context: Context,"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/biometrics/data/repository/DisplayStateRepository.kt"
+ line="68"
+ column="5"/>
+ </issue>
+
+ <issue
+ id="ShadeDisplayAwareContextChecker"
+ message="UI elements of the shade window
should use ShadeDisplayAware-annotated Resources, as the shade might move between windows, and only
@ShadeDisplayAware resources are updated with the new configuration correctly. Failures to do so
might result in wrong dimensions for shade window classes (e.g. using the wrong density or theme).
If the usage of Resources is not related to display specific configuration or UI, then there is
technically no need to use the annotation, and you can annotate the class with
@SuppressLint("ShadeDisplayAwareContextChecker")/@Suppress("ShadeDisplayAwareContextChecker")"
+ errorLine1=" @Main private val resources: Resources,"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/bouncer/data/repository/EmergencyServicesRepository.kt"
+ line="38"
+ column="5"/>
+ </issue>
+
+ <issue
+ id="ShadeDisplayAwareContextChecker"
+ message="UI elements of the shade window
should use ShadeDisplayAware-annotated Resources, as the shade might move between windows, and only
@ShadeDisplayAware resources are updated with the new configuration correctly. Failures to do so
might result in wrong dimensions for shade window classes (e.g. using the wrong density or theme).
If the usage of Resources is not related to display specific configuration or UI, then there is
technically no need to use the annotation, and you can annotate the class with
@SuppressLint("ShadeDisplayAwareContextChecker")/@Suppress("ShadeDisplayAwareContextChecker")"
+ errorLine1=" @Main private val resources: Resources,"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/biometrics/FaceAuthAccessibilityDelegate.kt"
+ line="37"
+ column="5"/>
+ </issue>
+
+ <issue
+ id="ShadeDisplayAwareContextChecker"
+ message="UI elements of the shade window
should use ShadeDisplayAware-annotated Resources, as the shade might move between windows, and only
@ShadeDisplayAware resources are updated with the new configuration correctly. Failures to do so
might result in wrong dimensions for shade window classes (e.g. using the wrong density or theme).
If the usage of Resources is not related to display specific configuration or UI, then there is
technically no need to use the annotation, and you can annotate the class with
@SuppressLint("ShadeDisplayAwareContextChecker")/@Suppress("ShadeDisplayAwareContextChecker")"
+ errorLine1=" @Main private val resources: Resources,"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/biometrics/FaceHelpMessageDeferral.kt"
+ line="42"
+ column="5"/>
+ </issue>
+
+ <issue
+ id="ShadeDisplayAwareContextChecker"
+ message="UI elements of the shade window
should use ShadeDisplayAware-annotated Context, as the shade might move between windows, and only
@ShadeDisplayAware resources are updated with the new configuration correctly. Failures to do so
might result in wrong dimensions for shade window classes (e.g. using the wrong density or theme).
If the usage of Context is not related to display specific configuration or UI, then there is
technically no need to use the annotation, and you can annotate the class with
@SuppressLint("ShadeDisplayAwareContextChecker")/@Suppress("ShadeDisplayAwareContextChecker")"
+ errorLine1=" @Application val applicationContext: Context,"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/biometrics/data/repository/FacePropertyRepository.kt"
+ line="95"
+ column="5"/>
+ </issue>
+
+ <issue
+ id="ShadeDisplayAwareContextChecker"
+ message="UI elements of the shade window
should use ShadeDisplayAware-annotated Resources, as the shade might move between windows, and only
@ShadeDisplayAware resources are updated with the new configuration correctly. Failures to do so
might result in wrong dimensions for shade window classes (e.g. using the wrong density or theme).
If the usage of Resources is not related to display specific configuration or UI, then there is
technically no need to use the annotation, and you can annotate the class with
@SuppressLint("ShadeDisplayAwareContextChecker")/@Suppress("ShadeDisplayAwareContextChecker")"
+ errorLine1=" @Main private val resources: Resources,"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/qs/FgsManagerController.kt"
+ line="142"
+ column="5"/>
+ </issue>
+
+ <issue
+ id="ShadeDisplayAwareContextChecker"
+ message="UI elements of the shade window
should use ShadeDisplayAware-annotated Context, as the shade might move between windows, and only
@ShadeDisplayAware resources are updated with the new configuration correctly. Failures to do so
might result in wrong dimensions for shade window classes (e.g. using the wrong density or theme).
If the usage of Context is not related to display specific configuration or UI, then there is
technically no need to use the annotation, and you can annotate the class with
@SuppressLint("ShadeDisplayAwareContextChecker")/@Suppress("ShadeDisplayAwareContextChecker")"
+ errorLine1=" @Application private val context: Context,"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/biometrics/domain/interactor/FingerprintPropertyInteractor.kt"
+ line="44"
+ column="5"/>
+ </issue>
+
+ <issue
+ id="ShadeDisplayAwareContextChecker"
+ message="UI elements of the shade window
should use ShadeDisplayAware-annotated Resources, as the shade might move between windows, and only
@ShadeDisplayAware resources are updated with the new configuration correctly. Failures to do so
might result in wrong dimensions for shade window classes (e.g. using the wrong density or theme).
If the usage of Resources is not related to display specific configuration or UI, then there is
technically no need to use the annotation, and you can annotate the class with
@SuppressLint("ShadeDisplayAwareContextChecker")/@Suppress("ShadeDisplayAwareContextChecker")"
+ errorLine1="constructor(@Main private val resources: Resources, private val theme: Theme) :"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/qs/tiles/impl/flashlight/domain/FlashlightMapper.kt"
+ line="33"
+ column="13"/>
+ </issue>
+
+ <issue
+ id="ShadeDisplayAwareContextChecker"
+ message="UI elements of the shade window
should use ShadeDisplayAware-annotated Resources, as the shade might move between windows, and only
@ShadeDisplayAware resources are updated with the new configuration correctly. Failures to do so
might result in wrong dimensions for shade window classes (e.g. using the wrong density or theme).
If the usage of Resources is not related to display specific configuration or UI, then there is
technically no need to use the annotation, and you can annotate the class with
@SuppressLint("ShadeDisplayAwareContextChecker")/@Suppress("ShadeDisplayAwareContextChecker")"
+ errorLine1="constructor(@Main private val resources: Resources, private val theme: Resources.Theme) :"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/qs/tiles/impl/fontscaling/domain/FontScalingTileMapper.kt"
+ line="32"
+ column="13"/>
+ </issue>
+
+ <issue
+ id="ShadeDisplayAwareContextChecker"
+ message="UI elements of the shade window
should use ShadeDisplayAware-annotated Context, as the shade might move between windows, and only
@ShadeDisplayAware resources are updated with the new configuration correctly. Failures to do so
might result in wrong dimensions for shade window classes (e.g. using the wrong density or theme).
If the usage of Context is not related to display specific configuration or UI, then there is
technically no need to use the annotation, and you can annotate the class with
@SuppressLint("ShadeDisplayAwareContextChecker")/@Suppress("ShadeDisplayAwareContextChecker")"
+ errorLine1=" @NonNull final Context context,"
+ errorLine2=" ~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/statusbar/notification/headsup/HeadsUpManagerImpl.java"
+ line="186"
+ column="36"/>
+ </issue>
+
+ <issue
+ id="ShadeDisplayAwareContextChecker"
+ message="UI elements of the shade window
should use ShadeDisplayAware-annotated ConfigurationController, as the shade might move between windows, and only
@ShadeDisplayAware resources are updated with the new configuration correctly. Failures to do so
might result in wrong dimensions for shade window classes (e.g. using the wrong density or theme).
If the usage of ConfigurationController is not related to display specific configuration or UI, then there is
technically no need to use the annotation, and you can annotate the class with
@SuppressLint("ShadeDisplayAwareContextChecker")/@Suppress("ShadeDisplayAwareContextChecker")"
+ errorLine1=" ConfigurationController configurationController,"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/statusbar/notification/headsup/HeadsUpManagerImpl.java"
+ line="192"
+ column="37"/>
+ </issue>
+
+ <issue
+ id="ShadeDisplayAwareContextChecker"
+ message="UI elements of the shade window
should use ShadeDisplayAware-annotated Resources, as the shade might move between windows, and only
@ShadeDisplayAware resources are updated with the new configuration correctly. Failures to do so
might result in wrong dimensions for shade window classes (e.g. using the wrong density or theme).
If the usage of Resources is not related to display specific configuration or UI, then there is
technically no need to use the annotation, and you can annotate the class with
@SuppressLint("ShadeDisplayAwareContextChecker")/@Suppress("ShadeDisplayAwareContextChecker")"
+ errorLine1="constructor(@Main private val resources: Resources, private val theme: Resources.Theme) :"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/qs/tiles/impl/hearingdevices/domain/HearingDevicesTileMapper.kt"
+ line="32"
+ column="13"/>
+ </issue>
+
+ <issue
+ id="ShadeDisplayAwareContextChecker"
+ message="UI elements of the shade window
should use ShadeDisplayAware-annotated Context, as the shade might move between windows, and only
@ShadeDisplayAware resources are updated with the new configuration correctly. Failures to do so
might result in wrong dimensions for shade window classes (e.g. using the wrong density or theme).
If the usage of Context is not related to display specific configuration or UI, then there is
technically no need to use the annotation, and you can annotate the class with
@SuppressLint("ShadeDisplayAwareContextChecker")/@Suppress("ShadeDisplayAwareContextChecker")"
+ errorLine1="class IconBuilder @Inject constructor(private val context: Context) {"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/statusbar/notification/icon/IconBuilder.kt"
+ line="27"
+ column="39"/>
+ </issue>
+
+ <issue
+ id="ShadeDisplayAwareContextChecker"
+ message="UI elements of the shade window
should use ShadeDisplayAware-annotated Resources, as the shade might move between windows, and only
@ShadeDisplayAware resources are updated with the new configuration correctly. Failures to do so
might result in wrong dimensions for shade window classes (e.g. using the wrong density or theme).
If the usage of Resources is not related to display specific configuration or UI, then there is
technically no need to use the annotation, and you can annotate the class with
@SuppressLint("ShadeDisplayAwareContextChecker")/@Suppress("ShadeDisplayAwareContextChecker")"
+ errorLine1="constructor(@Main private val resources: Resources, private val theme: Theme) :"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/qs/tiles/impl/irecording/IssueRecordingMapper.kt"
+ line="31"
+ column="13"/>
+ </issue>
+
+ <issue
+ id="ShadeDisplayAwareContextChecker"
+ message="UI elements of the shade window
should use ShadeDisplayAware-annotated WindowManager, as the shade might move between windows, and only
@ShadeDisplayAware resources are updated with the new configuration correctly. Failures to do so
might result in wrong dimensions for shade window classes (e.g. using the wrong density or theme).
If the usage of WindowManager is not related to display specific configuration or UI, then there is
technically no need to use the annotation, and you can annotate the class with
@SuppressLint("ShadeDisplayAwareContextChecker")/@Suppress("ShadeDisplayAwareContextChecker")"
+ errorLine1=" private val windowManager: WindowManager,"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/keyboard/docking/ui/viewmodel/KeyboardDockingIndicationViewModel.kt"
+ line="39"
+ column="5"/>
+ </issue>
+
+ <issue
+ id="ShadeDisplayAwareContextChecker"
+ message="UI elements of the shade window
should use ShadeDisplayAware-annotated Context, as the shade might move between windows, and only
@ShadeDisplayAware resources are updated with the new configuration correctly. Failures to do so
might result in wrong dimensions for shade window classes (e.g. using the wrong density or theme).
If the usage of Context is not related to display specific configuration or UI, then there is
technically no need to use the annotation, and you can annotate the class with
@SuppressLint("ShadeDisplayAwareContextChecker")/@Suppress("ShadeDisplayAwareContextChecker")"
+ errorLine1=" private val context: Context,"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/keyboard/docking/ui/viewmodel/KeyboardDockingIndicationViewModel.kt"
+ line="40"
+ column="5"/>
+ </issue>
+
+ <issue
+ id="ShadeDisplayAwareContextChecker"
+ message="UI elements of the shade window
should use ShadeDisplayAware-annotated Resources, as the shade might move between windows, and only
@ShadeDisplayAware resources are updated with the new configuration correctly. Failures to do so
might result in wrong dimensions for shade window classes (e.g. using the wrong density or theme).
If the usage of Resources is not related to display specific configuration or UI, then there is
technically no need to use the annotation, and you can annotate the class with
@SuppressLint("ShadeDisplayAwareContextChecker")/@Suppress("ShadeDisplayAwareContextChecker")"
+ errorLine1=" @Main private val resources: Resources,"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/qs/panels/data/repository/LargeTileSpanRepository.kt"
+ line="41"
+ column="5"/>
+ </issue>
+
+ <issue
+ id="ShadeDisplayAwareContextChecker"
+ message="UI elements of the shade window
should use ShadeDisplayAware-annotated Resources, as the shade might move between windows, and only
@ShadeDisplayAware resources are updated with the new configuration correctly. Failures to do so
might result in wrong dimensions for shade window classes (e.g. using the wrong density or theme).
If the usage of Resources is not related to display specific configuration or UI, then there is
technically no need to use the annotation, and you can annotate the class with
@SuppressLint("ShadeDisplayAwareContextChecker")/@Suppress("ShadeDisplayAwareContextChecker")"
+ errorLine1="constructor(@Main private val resources: Resources, private val theme: Theme) :"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/qs/tiles/impl/location/domain/LocationTileMapper.kt"
+ line="33"
+ column="13"/>
+ </issue>
+
+ <issue
+ id="ShadeDisplayAwareContextChecker"
+ message="UI elements of the shade window
should use ShadeDisplayAware-annotated LayoutInflater, as the shade might move between windows, and only
@ShadeDisplayAware resources are updated with the new configuration correctly. Failures to do so
might result in wrong dimensions for shade window classes (e.g. using the wrong density or theme).
If the usage of LayoutInflater is not related to display specific configuration or UI, then there is
technically no need to use the annotation, and you can annotate the class with
@SuppressLint("ShadeDisplayAwareContextChecker")/@Suppress("ShadeDisplayAwareContextChecker")"
+ errorLine1=" private val layoutInflater: LayoutInflater"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/render/MediaContainerController.kt"
+ line="29"
+ column="5"/>
+ </issue>
+
+ <issue
+ id="ShadeDisplayAwareContextChecker"
+ message="UI elements of the shade window
should use ShadeDisplayAware-annotated Resources, as the shade might move between windows, and only
@ShadeDisplayAware resources are updated with the new configuration correctly. Failures to do so
might result in wrong dimensions for shade window classes (e.g. using the wrong density or theme).
If the usage of Resources is not related to display specific configuration or UI, then there is
technically no need to use the annotation, and you can annotate the class with
@SuppressLint("ShadeDisplayAwareContextChecker")/@Suppress("ShadeDisplayAwareContextChecker")"
+ errorLine1="class MinimumTilesResourceRepository @Inject constructor(@Main resources: Resources) :"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/qs/pipeline/data/repository/MinimumTilesRepository.kt"
+ line="38"
+ column="58"/>
+ </issue>
+
+ <issue
+ id="ShadeDisplayAwareContextChecker"
+ message="UI elements of the shade window
should use ShadeDisplayAware-annotated Resources, as the shade might move between windows, and only
@ShadeDisplayAware resources are updated with the new configuration correctly. Failures to do so
might result in wrong dimensions for shade window classes (e.g. using the wrong density or theme).
If the usage of Resources is not related to display specific configuration or UI, then there is
technically no need to use the annotation, and you can annotate the class with
@SuppressLint("ShadeDisplayAwareContextChecker")/@Suppress("ShadeDisplayAwareContextChecker")"
+ errorLine1="constructor(@Main private val resources: Resources, val theme: Resources.Theme) :"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/qs/tiles/impl/modes/ui/ModesTileMapper.kt"
+ line="33"
+ column="13"/>
+ </issue>
+
+ <issue
+ id="ShadeDisplayAwareContextChecker"
+ message="UI elements of the shade window
should use ShadeDisplayAware-annotated Context, as the shade might move between windows, and only
@ShadeDisplayAware resources are updated with the new configuration correctly. Failures to do so
might result in wrong dimensions for shade window classes (e.g. using the wrong density or theme).
If the usage of Context is not related to display specific configuration or UI, then there is
technically no need to use the annotation, and you can annotate the class with
@SuppressLint("ShadeDisplayAwareContextChecker")/@Suppress("ShadeDisplayAwareContextChecker")"
+ errorLine1=" @Application private val context: Context,"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/qs/tiles/impl/night/domain/interactor/NightDisplayTileDataInteractor.kt"
+ line="38"
+ column="5"/>
+ </issue>
+
+ <issue
+ id="ShadeDisplayAwareContextChecker"
+ message="UI elements of the shade window
should use ShadeDisplayAware-annotated Resources, as the shade might move between windows, and only
@ShadeDisplayAware resources are updated with the new configuration correctly. Failures to do so
might result in wrong dimensions for shade window classes (e.g. using the wrong density or theme).
If the usage of Resources is not related to display specific configuration or UI, then there is
technically no need to use the annotation, and you can annotate the class with
@SuppressLint("ShadeDisplayAwareContextChecker")/@Suppress("ShadeDisplayAwareContextChecker")"
+ errorLine1=" @Main private val resources: Resources,"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/qs/tiles/impl/night/ui/NightDisplayTileMapper.kt"
+ line="42"
+ column="5"/>
+ </issue>
+
+ <issue
+ id="ShadeDisplayAwareContextChecker"
+ message="UI elements of the shade window
should use ShadeDisplayAware-annotated Resources, as the shade might move between windows, and only
@ShadeDisplayAware resources are updated with the new configuration correctly. Failures to do so
might result in wrong dimensions for shade window classes (e.g. using the wrong density or theme).
If the usage of Resources is not related to display specific configuration or UI, then there is
technically no need to use the annotation, and you can annotate the class with
@SuppressLint("ShadeDisplayAwareContextChecker")/@Suppress("ShadeDisplayAwareContextChecker")"
+ errorLine1="constructor(@Main private val resources: Resources, private val theme: Resources.Theme) :"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/qs/tiles/impl/notes/domain/NotesTileMapper.kt"
+ line="32"
+ column="13"/>
+ </issue>
+
+ <issue
+ id="ShadeDisplayAwareContextChecker"
+ message="UI elements of the shade window
should use ShadeDisplayAware-annotated Context, as the shade might move between windows, and only
@ShadeDisplayAware resources are updated with the new configuration correctly. Failures to do so
might result in wrong dimensions for shade window classes (e.g. using the wrong density or theme).
If the usage of Context is not related to display specific configuration or UI, then there is
technically no need to use the annotation, and you can annotate the class with
@SuppressLint("ShadeDisplayAwareContextChecker")/@Suppress("ShadeDisplayAwareContextChecker")"
+ errorLine1=" public NotificationGutsManager(Context context,"
+ errorLine2=" ~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationGutsManager.java"
+ line="137"
+ column="44"/>
+ </issue>
+
+ <issue
+ id="ShadeDisplayAwareContextChecker"
+ message="UI elements of the shade window
should use ShadeDisplayAware-annotated Resources, as the shade might move between windows, and only
@ShadeDisplayAware resources are updated with the new configuration correctly. Failures to do so
might result in wrong dimensions for shade window classes (e.g. using the wrong density or theme).
If the usage of Resources is not related to display specific configuration or UI, then there is
technically no need to use the annotation, and you can annotate the class with
@SuppressLint("ShadeDisplayAwareContextChecker")/@Suppress("ShadeDisplayAwareContextChecker")"
+ errorLine1=" @Main resources: Resources,"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/statusbar/notification/icon/ui/viewmodel/NotificationIconContainerAlwaysOnDisplayViewModel.kt"
+ line="47"
+ column="5"/>
+ </issue>
+
+ <issue
+ id="ShadeDisplayAwareContextChecker"
+ message="UI elements of the shade window
should use ShadeDisplayAware-annotated Resources, as the shade might move between windows, and only
@ShadeDisplayAware resources are updated with the new configuration correctly. Failures to do so
might result in wrong dimensions for shade window classes (e.g. using the wrong density or theme).
If the usage of Resources is not related to display specific configuration or UI, then there is
technically no need to use the annotation, and you can annotate the class with
@SuppressLint("ShadeDisplayAwareContextChecker")/@Suppress("ShadeDisplayAwareContextChecker")"
+ errorLine1=" @Main resources: Resources,"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/statusbar/notification/icon/ui/viewmodel/NotificationIconContainerStatusBarViewModel.kt"
+ line="53"
+ column="5"/>
+ </issue>
+
+ <issue
+ id="ShadeDisplayAwareContextChecker"
+ message="UI elements of the shade window
should use ShadeDisplayAware-annotated Context, as the shade might move between windows, and only
@ShadeDisplayAware resources are updated with the new configuration correctly. Failures to do so
might result in wrong dimensions for shade window classes (e.g. using the wrong density or theme).
If the usage of Context is not related to display specific configuration or UI, then there is
technically no need to use the annotation, and you can annotate the class with
@SuppressLint("ShadeDisplayAwareContextChecker")/@Suppress("ShadeDisplayAwareContextChecker")"
+ errorLine1="constructor(val context: Context) {"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationSectionsFeatureManager.kt"
+ line="27"
+ column="13"/>
+ </issue>
+
+ <issue
+ id="ShadeDisplayAwareContextChecker"
+ message="UI elements of the shade window
should use ShadeDisplayAware-annotated ConfigurationController, as the shade might move between windows, and only
@ShadeDisplayAware resources are updated with the new configuration correctly. Failures to do so
might result in wrong dimensions for shade window classes (e.g. using the wrong density or theme).
If the usage of ConfigurationController is not related to display specific configuration or UI, then there is
technically no need to use the annotation, and you can annotate the class with
@SuppressLint("ShadeDisplayAwareContextChecker")/@Suppress("ShadeDisplayAwareContextChecker")"
+ errorLine1=" ConfigurationController configurationController,"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayoutController.java"
+ line="737"
+ column="37"/>
+ </issue>
+
+ <issue
+ id="ShadeDisplayAwareContextChecker"
+ message="UI elements of the shade window
should use ShadeDisplayAware-annotated Resources, as the shade might move between windows, and only
@ShadeDisplayAware resources are updated with the new configuration correctly. Failures to do so
might result in wrong dimensions for shade window classes (e.g. using the wrong density or theme).
If the usage of Resources is not related to display specific configuration or UI, then there is
technically no need to use the annotation, and you can annotate the class with
@SuppressLint("ShadeDisplayAwareContextChecker")/@Suppress("ShadeDisplayAwareContextChecker")"
+ errorLine1=" @Main private val resources: Resources,"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationStackSizeCalculator.kt"
+ line="63"
+ column="5"/>
+ </issue>
+
+ <issue
+ id="ShadeDisplayAwareContextChecker"
+ message="UI elements of the shade window
should use ShadeDisplayAware-annotated Resources, as the shade might move between windows, and only
@ShadeDisplayAware resources are updated with the new configuration correctly. Failures to do so
might result in wrong dimensions for shade window classes (e.g. using the wrong density or theme).
If the usage of Resources is not related to display specific configuration or UI, then there is
technically no need to use the annotation, and you can annotate the class with
@SuppressLint("ShadeDisplayAwareContextChecker")/@Suppress("ShadeDisplayAwareContextChecker")"
+ errorLine1=" Builder(@Main Resources resources, ViewConfiguration viewConfiguration,"
+ errorLine2=" ~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationSwipeHelper.java"
+ line="563"
+ column="33"/>
+ </issue>
+
+ <issue
+ id="ShadeDisplayAwareContextChecker"
+ message="UI elements of the shade window
should use ShadeDisplayAware-annotated Resources, as the shade might move between windows, and only
@ShadeDisplayAware resources are updated with the new configuration correctly. Failures to do so
might result in wrong dimensions for shade window classes (e.g. using the wrong density or theme).
If the usage of Resources is not related to display specific configuration or UI, then there is
technically no need to use the annotation, and you can annotate the class with
@SuppressLint("ShadeDisplayAwareContextChecker")/@Suppress("ShadeDisplayAwareContextChecker")"
+ errorLine1="constructor(@Main private val resources: Resources, private val theme: Resources.Theme) :"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/qs/tiles/impl/onehanded/ui/OneHandedModeTileMapper.kt"
+ line="32"
+ column="13"/>
+ </issue>
+
+ <issue
+ id="ShadeDisplayAwareContextChecker"
+ message="UI elements of the shade window
should use ShadeDisplayAware-annotated Context, as the shade might move between windows, and only
@ShadeDisplayAware resources are updated with the new configuration correctly. Failures to do so
might result in wrong dimensions for shade window classes (e.g. using the wrong density or theme).
If the usage of Context is not related to display specific configuration or UI, then there is
technically no need to use the annotation, and you can annotate the class with
@SuppressLint("ShadeDisplayAwareContextChecker")/@Suppress("ShadeDisplayAwareContextChecker")"
+ errorLine1=" public PackageManagerAdapter(Context context) {"
+ errorLine2=" ~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/qs/external/PackageManagerAdapter.java"
+ line="45"
+ column="42"/>
+ </issue>
+
+ <issue
+ id="ShadeDisplayAwareContextChecker"
+ message="UI elements of the shade window
should use ShadeDisplayAware-annotated Resources, as the shade might move between windows, and only
@ShadeDisplayAware resources are updated with the new configuration correctly. Failures to do so
might result in wrong dimensions for shade window classes (e.g. using the wrong density or theme).
If the usage of Resources is not related to display specific configuration or UI, then there is
technically no need to use the annotation, and you can annotate the class with
@SuppressLint("ShadeDisplayAwareContextChecker")/@Suppress("ShadeDisplayAwareContextChecker")"
+ errorLine1=" @Main private val resources: Resources,"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/qs/panels/data/repository/PaginatedGridRepository.kt"
+ line="36"
+ column="5"/>
+ </issue>
+
+ <issue
+ id="ShadeDisplayAwareContextChecker"
+ message="UI elements of the shade window
should use ShadeDisplayAware-annotated Context, as the shade might move between windows, and only
@ShadeDisplayAware resources are updated with the new configuration correctly. Failures to do so
might result in wrong dimensions for shade window classes (e.g. using the wrong density or theme).
If the usage of Context is not related to display specific configuration or UI, then there is
technically no need to use the annotation, and you can annotate the class with
@SuppressLint("ShadeDisplayAwareContextChecker")/@Suppress("ShadeDisplayAwareContextChecker")"
+ errorLine1=" private val context: Context,"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/bouncer/domain/interactor/PrimaryBouncerInteractor.kt"
+ line="74"
+ column="5"/>
+ </issue>
+
+ <issue
+ id="ShadeDisplayAwareContextChecker"
+ message="UI elements of the shade window
should use ShadeDisplayAware-annotated Context, as the shade might move between windows, and only
@ShadeDisplayAware resources are updated with the new configuration correctly. Failures to do so
might result in wrong dimensions for shade window classes (e.g. using the wrong density or theme).
If the usage of Context is not related to display specific configuration or UI, then there is
technically no need to use the annotation, and you can annotate the class with
@SuppressLint("ShadeDisplayAwareContextChecker")/@Suppress("ShadeDisplayAwareContextChecker")"
+ errorLine1=" private val context: Context,"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/statusbar/notification/promoted/PromotedNotificationContentExtractor.kt"
+ line="41"
+ column="5"/>
+ </issue>
+
+ <issue
+ id="ShadeDisplayAwareContextChecker"
+ message="UI elements of the shade window
should use ShadeDisplayAware-annotated Context, as the shade might move between windows, and only
@ShadeDisplayAware resources are updated with the new configuration correctly. Failures to do so
might result in wrong dimensions for shade window classes (e.g. using the wrong density or theme).
If the usage of Context is not related to display specific configuration or UI, then there is
technically no need to use the annotation, and you can annotate the class with
@SuppressLint("ShadeDisplayAwareContextChecker")/@Suppress("ShadeDisplayAwareContextChecker")"
+ errorLine1=" @Application private val context: Context,"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/biometrics/ui/viewmodel/PromptViewModel.kt"
+ line="82"
+ column="5"/>
+ </issue>
+
+ <issue
+ id="ShadeDisplayAwareContextChecker"
+ message="UI elements of the shade window
should use ShadeDisplayAware-annotated Resources, as the shade might move between windows, and only
@ShadeDisplayAware resources are updated with the new configuration correctly. Failures to do so
might result in wrong dimensions for shade window classes (e.g. using the wrong density or theme).
If the usage of Resources is not related to display specific configuration or UI, then there is
technically no need to use the annotation, and you can annotate the class with
@SuppressLint("ShadeDisplayAwareContextChecker")/@Suppress("ShadeDisplayAwareContextChecker")"
+ errorLine1="constructor(@Main private val resources: Resources, private val theme: Resources.Theme) :"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/qs/tiles/impl/qr/ui/QRCodeScannerTileMapper.kt"
+ line="32"
+ column="13"/>
+ </issue>
+
+ <issue
+ id="ShadeDisplayAwareContextChecker"
+ message="UI elements of the shade window
should use ShadeDisplayAware-annotated Resources, as the shade might move between windows, and only
@ShadeDisplayAware resources are updated with the new configuration correctly. Failures to do so
might result in wrong dimensions for shade window classes (e.g. using the wrong density or theme).
If the usage of Resources is not related to display specific configuration or UI, then there is
technically no need to use the annotation, and you can annotate the class with
@SuppressLint("ShadeDisplayAwareContextChecker")/@Suppress("ShadeDisplayAwareContextChecker")"
+ errorLine1=" @Main private val resources: Resources,"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/qs/panels/data/repository/QSColumnsRepository.kt"
+ line="36"
+ column="5"/>
+ </issue>
+
+ <issue
+ id="ShadeDisplayAwareContextChecker"
+ message="UI elements of the shade window
should use ShadeDisplayAware-annotated Context, as the shade might move between windows, and only
@ShadeDisplayAware resources are updated with the new configuration correctly. Failures to do so
might result in wrong dimensions for shade window classes (e.g. using the wrong density or theme).
If the usage of Context is not related to display specific configuration or UI, then there is
technically no need to use the annotation, and you can annotate the class with
@SuppressLint("ShadeDisplayAwareContextChecker")/@Suppress("ShadeDisplayAwareContextChecker")"
+ errorLine1=" Factory(Context context, QSCustomizerController qsCustomizerController) {"
+ errorLine2=" ~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/qs/QSTileRevealController.java"
+ line="99"
+ column="25"/>
+ </issue>
+
+ <issue
+ id="ShadeDisplayAwareContextChecker"
+ message="UI elements of the shade window
should use ShadeDisplayAware-annotated Resources, as the shade might move between windows, and only
@ShadeDisplayAware resources are updated with the new configuration correctly. Failures to do so
might result in wrong dimensions for shade window classes (e.g. using the wrong density or theme).
If the usage of Resources is not related to display specific configuration or UI, then there is
technically no need to use the annotation, and you can annotate the class with
@SuppressLint("ShadeDisplayAwareContextChecker")/@Suppress("ShadeDisplayAwareContextChecker")"
+ errorLine1=" @Main private val resources: Resources,"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/qs/panels/data/repository/QuickQuickSettingsRowRepository.kt"
+ line="32"
+ column="5"/>
+ </issue>
+
+ <issue
+ id="ShadeDisplayAwareContextChecker"
+ message="UI elements of the shade window
should use ShadeDisplayAware-annotated Resources, as the shade might move between windows, and only
@ShadeDisplayAware resources are updated with the new configuration correctly. Failures to do so
might result in wrong dimensions for shade window classes (e.g. using the wrong density or theme).
If the usage of Resources is not related to display specific configuration or UI, then there is
technically no need to use the annotation, and you can annotate the class with
@SuppressLint("ShadeDisplayAwareContextChecker")/@Suppress("ShadeDisplayAwareContextChecker")"
+ errorLine1="constructor(@Main private val resources: Resources, private val theme: Resources.Theme) :"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/qs/tiles/impl/reducebrightness/ui/ReduceBrightColorsTileMapper.kt"
+ line="33"
+ column="13"/>
+ </issue>
+
+ <issue
+ id="ShadeDisplayAwareContextChecker"
+ message="UI elements of the shade window
should use ShadeDisplayAware-annotated Resources, as the shade might move between windows, and only
@ShadeDisplayAware resources are updated with the new configuration correctly. Failures to do so
might result in wrong dimensions for shade window classes (e.g. using the wrong density or theme).
If the usage of Resources is not related to display specific configuration or UI, then there is
technically no need to use the annotation, and you can annotate the class with
@SuppressLint("ShadeDisplayAwareContextChecker")/@Suppress("ShadeDisplayAwareContextChecker")"
+ errorLine1=" @Main private val resources: Resources,"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/qs/tiles/impl/reducebrightness/domain/interactor/ReduceBrightColorsTileUserActionInteractor.kt"
+ line="36"
+ column="5"/>
+ </issue>
+
+ <issue
+ id="ShadeDisplayAwareContextChecker"
+ message="UI elements of the shade window
should use ShadeDisplayAware-annotated Resources, as the shade might move between windows, and only
@ShadeDisplayAware resources are updated with the new configuration correctly. Failures to do so
might result in wrong dimensions for shade window classes (e.g. using the wrong density or theme).
If the usage of Resources is not related to display specific configuration or UI, then there is
technically no need to use the annotation, and you can annotate the class with
@SuppressLint("ShadeDisplayAwareContextChecker")/@Suppress("ShadeDisplayAwareContextChecker")"
+ errorLine1=" @Main private val resources: Resources,"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/qs/tiles/impl/rotation/domain/interactor/RotationLockTileDataInteractor.kt"
+ line="47"
+ column="5"/>
+ </issue>
+
+ <issue
+ id="ShadeDisplayAwareContextChecker"
+ message="UI elements of the shade window
should use ShadeDisplayAware-annotated Resources, as the shade might move between windows, and only
@ShadeDisplayAware resources are updated with the new configuration correctly. Failures to do so
might result in wrong dimensions for shade window classes (e.g. using the wrong density or theme).
If the usage of Resources is not related to display specific configuration or UI, then there is
technically no need to use the annotation, and you can annotate the class with
@SuppressLint("ShadeDisplayAwareContextChecker")/@Suppress("ShadeDisplayAwareContextChecker")"
+ errorLine1=" @Main private val resources: Resources,"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/qs/tiles/impl/rotation/ui/mapper/RotationLockTileMapper.kt"
+ line="36"
+ column="5"/>
+ </issue>
+
+ <issue
+ id="ShadeDisplayAwareContextChecker"
+ message="UI elements of the shade window
should use ShadeDisplayAware-annotated Resources, as the shade might move between windows, and only
@ShadeDisplayAware resources are updated with the new configuration correctly. Failures to do so
might result in wrong dimensions for shade window classes (e.g. using the wrong density or theme).
If the usage of Resources is not related to display specific configuration or UI, then there is
technically no need to use the annotation, and you can annotate the class with
@SuppressLint("ShadeDisplayAwareContextChecker")/@Suppress("ShadeDisplayAwareContextChecker")"
+ errorLine1=" @Main private val resources: Resources,"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/qs/pipeline/domain/autoaddable/SafetyCenterAutoAddable.kt"
+ line="51"
+ column="5"/>
+ </issue>
+
+ <issue
+ id="ShadeDisplayAwareContextChecker"
+ message="UI elements of the shade window
should use ShadeDisplayAware-annotated Resources, as the shade might move between windows, and only
@ShadeDisplayAware resources are updated with the new configuration correctly. Failures to do so
might result in wrong dimensions for shade window classes (e.g. using the wrong density or theme).
If the usage of Resources is not related to display specific configuration or UI, then there is
technically no need to use the annotation, and you can annotate the class with
@SuppressLint("ShadeDisplayAwareContextChecker")/@Suppress("ShadeDisplayAwareContextChecker")"
+ errorLine1="constructor(@Main private val resources: Resources, private val theme: Resources.Theme) :"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/qs/tiles/impl/screenrecord/domain/ui/ScreenRecordTileMapper.kt"
+ line="33"
+ column="13"/>
+ </issue>
+
+ <issue
+ id="ShadeDisplayAwareContextChecker"
+ message="UI elements of the shade window
should use ShadeDisplayAware-annotated LayoutInflater, as the shade might move between windows, and only
@ShadeDisplayAware resources are updated with the new configuration correctly. Failures to do so
might result in wrong dimensions for shade window classes (e.g. using the wrong density or theme).
If the usage of LayoutInflater is not related to display specific configuration or UI, then there is
technically no need to use the annotation, and you can annotate the class with
@SuppressLint("ShadeDisplayAwareContextChecker")/@Suppress("ShadeDisplayAwareContextChecker")"
+ errorLine1=" private val layoutInflater: LayoutInflater,"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/render/SectionHeaderController.kt"
+ line="43"
+ column="5"/>
+ </issue>
+
+ <issue
+ id="ShadeDisplayAwareContextChecker"
+ message="UI elements of the shade window
should use ShadeDisplayAware-annotated Context, as the shade might move between windows, and only
@ShadeDisplayAware resources are updated with the new configuration correctly. Failures to do so
might result in wrong dimensions for shade window classes (e.g. using the wrong density or theme).
If the usage of Context is not related to display specific configuration or UI, then there is
technically no need to use the annotation, and you can annotate the class with
@SuppressLint("ShadeDisplayAwareContextChecker")/@Suppress("ShadeDisplayAwareContextChecker")"
+ errorLine1=" context: Context"
+ errorLine2=" ~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/provider/SectionHeaderVisibilityProvider.kt"
+ line="35"
+ column="5"/>
+ </issue>
+
+ <issue
+ id="ShadeDisplayAwareContextChecker"
+ message="UI elements of the shade window
should use ShadeDisplayAware-annotated Context, as the shade might move between windows, and only
@ShadeDisplayAware resources are updated with the new configuration correctly. Failures to do so
might result in wrong dimensions for shade window classes (e.g. using the wrong density or theme).
If the usage of Context is not related to display specific configuration or UI, then there is
technically no need to use the annotation, and you can annotate the class with
@SuppressLint("ShadeDisplayAwareContextChecker")/@Suppress("ShadeDisplayAwareContextChecker")"
+ errorLine1=" @Application private val applicationContext: Context,"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/biometrics/ui/binder/SideFpsOverlayViewBinder.kt"
+ line="63"
+ column="5"/>
+ </issue>
+
+ <issue
+ id="ShadeDisplayAwareContextChecker"
+ message="UI elements of the shade window
should use ShadeDisplayAware-annotated Context, as the shade might move between windows, and only
@ShadeDisplayAware resources are updated with the new configuration correctly. Failures to do so
might result in wrong dimensions for shade window classes (e.g. using the wrong density or theme).
If the usage of Context is not related to display specific configuration or UI, then there is
technically no need to use the annotation, and you can annotate the class with
@SuppressLint("ShadeDisplayAwareContextChecker")/@Suppress("ShadeDisplayAwareContextChecker")"
+ errorLine1=" @Application private val applicationContext: Context,"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/biometrics/ui/viewmodel/SideFpsOverlayViewModel.kt"
+ line="53"
+ column="5"/>
+ </issue>
+
+ <issue
+ id="ShadeDisplayAwareContextChecker"
+ message="UI elements of the shade window
should use ShadeDisplayAware-annotated Context, as the shade might move between windows, and only
@ShadeDisplayAware resources are updated with the new configuration correctly. Failures to do so
might result in wrong dimensions for shade window classes (e.g. using the wrong density or theme).
If the usage of Context is not related to display specific configuration or UI, then there is
technically no need to use the annotation, and you can annotate the class with
@SuppressLint("ShadeDisplayAwareContextChecker")/@Suppress("ShadeDisplayAwareContextChecker")"
+ errorLine1=" private val context: Context,"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/biometrics/domain/interactor/SideFpsSensorInteractor.kt"
+ line="51"
+ column="5"/>
+ </issue>
+
+ <issue
+ id="ShadeDisplayAwareContextChecker"
+ message="UI elements of the shade window
should use ShadeDisplayAware-annotated WindowManager, as the shade might move between windows, and only
@ShadeDisplayAware resources are updated with the new configuration correctly. Failures to do so
might result in wrong dimensions for shade window classes (e.g. using the wrong density or theme).
If the usage of WindowManager is not related to display specific configuration or UI, then there is
technically no need to use the annotation, and you can annotate the class with
@SuppressLint("ShadeDisplayAwareContextChecker")/@Suppress("ShadeDisplayAwareContextChecker")"
+ errorLine1=" windowManager: WindowManager,"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/biometrics/domain/interactor/SideFpsSensorInteractor.kt"
+ line="53"
+ column="5"/>
+ </issue>
+
+ <issue
+ id="ShadeDisplayAwareContextChecker"
+ message="UI elements of the shade window
should use ShadeDisplayAware-annotated Context, as the shade might move between windows, and only
@ShadeDisplayAware resources are updated with the new configuration correctly. Failures to do so
might result in wrong dimensions for shade window classes (e.g. using the wrong density or theme).
If the usage of Context is not related to display specific configuration or UI, then there is
technically no need to use the annotation, and you can annotate the class with
@SuppressLint("ShadeDisplayAwareContextChecker")/@Suppress("ShadeDisplayAwareContextChecker")"
+ errorLine1=" @Application private val applicationContext: Context,"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/bouncer/domain/interactor/SimBouncerInteractor.kt"
+ line="60"
+ column="5"/>
+ </issue>
+
+ <issue
+ id="ShadeDisplayAwareContextChecker"
+ message="UI elements of the shade window
should use ShadeDisplayAware-annotated Resources, as the shade might move between windows, and only
@ShadeDisplayAware resources are updated with the new configuration correctly. Failures to do so
might result in wrong dimensions for shade window classes (e.g. using the wrong density or theme).
If the usage of Resources is not related to display specific configuration or UI, then there is
technically no need to use the annotation, and you can annotate the class with
@SuppressLint("ShadeDisplayAwareContextChecker")/@Suppress("ShadeDisplayAwareContextChecker")"
+ errorLine1=" @Main private val resources: Resources,"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/bouncer/domain/interactor/SimBouncerInteractor.kt"
+ line="65"
+ column="5"/>
+ </issue>
+
+ <issue
+ id="ShadeDisplayAwareContextChecker"
+ message="UI elements of the shade window
should use ShadeDisplayAware-annotated Resources, as the shade might move between windows, and only
@ShadeDisplayAware resources are updated with the new configuration correctly. Failures to do so
might result in wrong dimensions for shade window classes (e.g. using the wrong density or theme).
If the usage of Resources is not related to display specific configuration or UI, then there is
technically no need to use the annotation, and you can annotate the class with
@SuppressLint("ShadeDisplayAwareContextChecker")/@Suppress("ShadeDisplayAwareContextChecker")"
+ errorLine1=" @Main resources: Resources,"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/bouncer/data/repository/SimBouncerRepository.kt"
+ line="91"
+ column="5"/>
+ </issue>
+
+ <issue
+ id="ShadeDisplayAwareContextChecker"
+ message="UI elements of the shade window
should use ShadeDisplayAware-annotated Context, as the shade might move between windows, and only
@ShadeDisplayAware resources are updated with the new configuration correctly. Failures to do so
might result in wrong dimensions for shade window classes (e.g. using the wrong density or theme).
If the usage of Context is not related to display specific configuration or UI, then there is
technically no need to use the annotation, and you can annotate the class with
@SuppressLint("ShadeDisplayAwareContextChecker")/@Suppress("ShadeDisplayAwareContextChecker")"
+ errorLine1="constructor(context: Context, val shadeViewController: ShadeViewController) {"
+ errorLine2=" ~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/shade/StatusBarLongPressGestureDetector.kt"
+ line="30"
+ column="13"/>
+ </issue>
+
+ <issue
+ id="ShadeDisplayAwareContextChecker"
+ message="UI elements of the shade window
should use ShadeDisplayAware-annotated Resources, as the shade might move between windows, and only
@ShadeDisplayAware resources are updated with the new configuration correctly. Failures to do so
might result in wrong dimensions for shade window classes (e.g. using the wrong density or theme).
If the usage of Resources is not related to display specific configuration or UI, then there is
technically no need to use the annotation, and you can annotate the class with
@SuppressLint("ShadeDisplayAwareContextChecker")/@Suppress("ShadeDisplayAwareContextChecker")"
+ errorLine1=" @Main private val resources: Resources,"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/qs/panels/data/repository/StockTilesRepository.kt"
+ line="31"
+ column="5"/>
+ </issue>
+
+ <issue
+ id="ShadeDisplayAwareContextChecker"
+ message="UI elements of the shade window
should use ShadeDisplayAware-annotated Context, as the shade might move between windows, and only
@ShadeDisplayAware resources are updated with the new configuration correctly. Failures to do so
might result in wrong dimensions for shade window classes (e.g. using the wrong density or theme).
If the usage of Context is not related to display specific configuration or UI, then there is
technically no need to use the annotation, and you can annotate the class with
@SuppressLint("ShadeDisplayAwareContextChecker")/@Suppress("ShadeDisplayAwareContextChecker")"
+ errorLine1=" private val context: Context"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/TargetSdkResolver.kt"
+ line="33"
+ column="5"/>
+ </issue>
+
+ <issue
+ id="ShadeDisplayAwareContextChecker"
+ message="UI elements of the shade window
should use ShadeDisplayAware-annotated Resources, as the shade might move between windows, and only
@ShadeDisplayAware resources are updated with the new configuration correctly. Failures to do so
might result in wrong dimensions for shade window classes (e.g. using the wrong density or theme).
If the usage of Resources is not related to display specific configuration or UI, then there is
technically no need to use the annotation, and you can annotate the class with
@SuppressLint("ShadeDisplayAwareContextChecker")/@Suppress("ShadeDisplayAwareContextChecker")"
+ errorLine1=" @Main private val resources: Resources,"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/qs/pipeline/data/repository/TileSpecRepository.kt"
+ line="95"
+ column="5"/>
+ </issue>
+
+ <issue
+ id="ShadeDisplayAwareContextChecker"
+ message="UI elements of the shade window
should use ShadeDisplayAware-annotated Resources, as the shade might move between windows, and only
@ShadeDisplayAware resources are updated with the new configuration correctly. Failures to do so
might result in wrong dimensions for shade window classes (e.g. using the wrong density or theme).
If the usage of Resources is not related to display specific configuration or UI, then there is
technically no need to use the annotation, and you can annotate the class with
@SuppressLint("ShadeDisplayAwareContextChecker")/@Suppress("ShadeDisplayAwareContextChecker")"
+ errorLine1=" @Main private val resources: Resources,"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsKeyguardAccessibilityDelegate.kt"
+ line="33"
+ column="5"/>
+ </issue>
+
+ <issue
+ id="ShadeDisplayAwareContextChecker"
+ message="UI elements of the shade window
should use ShadeDisplayAware-annotated Context, as the shade might move between windows, and only
@ShadeDisplayAware resources are updated with the new configuration correctly. Failures to do so
might result in wrong dimensions for shade window classes (e.g. using the wrong density or theme).
If the usage of Context is not related to display specific configuration or UI, then there is
technically no need to use the annotation, and you can annotate the class with
@SuppressLint("ShadeDisplayAwareContextChecker")/@Suppress("ShadeDisplayAwareContextChecker")"
+ errorLine1=" @Application private val context: Context,"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/biometrics/domain/interactor/UdfpsOverlayInteractor.kt"
+ line="49"
+ column="5"/>
+ </issue>
+
+ <issue
+ id="ShadeDisplayAwareContextChecker"
+ message="UI elements of the shade window
should use ShadeDisplayAware-annotated ConfigurationController, as the shade might move between windows, and only
@ShadeDisplayAware resources are updated with the new configuration correctly. Failures to do so
might result in wrong dimensions for shade window classes (e.g. using the wrong density or theme).
If the usage of ConfigurationController is not related to display specific configuration or UI, then there is
technically no need to use the annotation, and you can annotate the class with
@SuppressLint("ShadeDisplayAwareContextChecker")/@Suppress("ShadeDisplayAwareContextChecker")"
+ errorLine1=" private val configurationController: ConfigurationController,"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/qs/tiles/impl/uimodenight/domain/interactor/UiModeNightTileDataInteractor.kt"
+ line="43"
+ column="5"/>
+ </issue>
+
+ <issue
+ id="ShadeDisplayAwareContextChecker"
+ message="UI elements of the shade window
should use ShadeDisplayAware-annotated Resources, as the shade might move between windows, and only
@ShadeDisplayAware resources are updated with the new configuration correctly. Failures to do so
might result in wrong dimensions for shade window classes (e.g. using the wrong density or theme).
If the usage of Resources is not related to display specific configuration or UI, then there is
technically no need to use the annotation, and you can annotate the class with
@SuppressLint("ShadeDisplayAwareContextChecker")/@Suppress("ShadeDisplayAwareContextChecker")"
+ errorLine1="constructor(@Main private val resources: Resources, private val theme: Theme) :"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/qs/tiles/impl/uimodenight/domain/UiModeNightTileMapper.kt"
+ line="37"
+ column="13"/>
+ </issue>
+
+ <issue
+ id="ShadeDisplayAwareContextChecker"
+ message="UI elements of the shade window
should use ShadeDisplayAware-annotated Resources, as the shade might move between windows, and only
@ShadeDisplayAware resources are updated with the new configuration correctly. Failures to do so
might result in wrong dimensions for shade window classes (e.g. using the wrong density or theme).
If the usage of Resources is not related to display specific configuration or UI, then there is
technically no need to use the annotation, and you can annotate the class with
@SuppressLint("ShadeDisplayAwareContextChecker")/@Suppress("ShadeDisplayAwareContextChecker")"
+ errorLine1=" @Main private val resources: Resources,"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/qs/tiles/impl/work/ui/WorkModeTileMapper.kt"
+ line="36"
+ column="5"/>
+ </issue>
+
</issues>
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/communal/data/db/DefaultWidgetPopulationTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/communal/data/db/DefaultWidgetPopulationTest.kt
index 596db07..f1c58a2 100644
--- a/packages/SystemUI/multivalentTests/src/com/android/systemui/communal/data/db/DefaultWidgetPopulationTest.kt
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/communal/data/db/DefaultWidgetPopulationTest.kt
@@ -24,6 +24,7 @@
import androidx.test.filters.SmallTest
import com.android.systemui.SysuiTestCase
import com.android.systemui.communal.data.db.DefaultWidgetPopulation.SkipReason.RESTORED_FROM_BACKUP
+import com.android.systemui.communal.shared.model.SpanValue
import com.android.systemui.communal.widgets.CommunalWidgetHost
import com.android.systemui.kosmos.applicationCoroutineScope
import com.android.systemui.kosmos.testScope
@@ -117,7 +118,7 @@
componentName = defaultWidgets[0],
rank = 0,
userSerialNumber = 0,
- spanY = 3,
+ spanY = SpanValue.Fixed(3),
)
verify(communalWidgetDao)
.addWidget(
@@ -125,7 +126,7 @@
componentName = defaultWidgets[1],
rank = 1,
userSerialNumber = 0,
- spanY = 3,
+ spanY = SpanValue.Fixed(3),
)
verify(communalWidgetDao)
.addWidget(
@@ -133,7 +134,7 @@
componentName = defaultWidgets[2],
rank = 2,
userSerialNumber = 0,
- spanY = 3,
+ spanY = SpanValue.Fixed(3),
)
}
@@ -155,7 +156,7 @@
componentName = any(),
rank = anyInt(),
userSerialNumber = anyInt(),
- spanY = anyInt(),
+ spanY = any(),
)
}
}
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/communal/data/repository/CommunalWidgetRepositoryLocalImplTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/communal/data/repository/CommunalWidgetRepositoryLocalImplTest.kt
index 55d7d08..335e399 100644
--- a/packages/SystemUI/multivalentTests/src/com/android/systemui/communal/data/repository/CommunalWidgetRepositoryLocalImplTest.kt
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/communal/data/repository/CommunalWidgetRepositoryLocalImplTest.kt
@@ -24,11 +24,15 @@
import android.content.applicationContext
import android.graphics.Bitmap
import android.os.UserHandle
+import android.os.UserManager
import android.os.userManager
+import android.platform.test.annotations.DisableFlags
import android.platform.test.annotations.EnableFlags
-import androidx.test.ext.junit.runners.AndroidJUnit4
+import android.platform.test.flag.junit.FlagsParameterization
import androidx.test.filters.SmallTest
+import com.android.systemui.Flags.FLAG_COMMUNAL_RESPONSIVE_GRID
import com.android.systemui.Flags.FLAG_COMMUNAL_WIDGET_RESIZING
+import com.android.systemui.Flags.communalResponsiveGrid
import com.android.systemui.SysuiTestCase
import com.android.systemui.common.data.repository.fakePackageChangeRepository
import com.android.systemui.common.shared.model.PackageInstallSession
@@ -40,11 +44,15 @@
import com.android.systemui.communal.nano.CommunalHubState
import com.android.systemui.communal.proto.toByteArray
import com.android.systemui.communal.shared.model.CommunalWidgetContentModel
+import com.android.systemui.communal.shared.model.SpanValue
import com.android.systemui.communal.widgets.CommunalAppWidgetHost
import com.android.systemui.communal.widgets.CommunalWidgetHost
import com.android.systemui.communal.widgets.widgetConfiguratorFail
import com.android.systemui.communal.widgets.widgetConfiguratorSuccess
-import com.android.systemui.coroutines.collectLastValue
+import com.android.systemui.kosmos.Kosmos
+import com.android.systemui.kosmos.collectLastValue
+import com.android.systemui.kosmos.runCurrent
+import com.android.systemui.kosmos.runTest
import com.android.systemui.kosmos.testDispatcher
import com.android.systemui.kosmos.testScope
import com.android.systemui.log.LogBuffer
@@ -52,48 +60,55 @@
import com.android.systemui.res.R
import com.android.systemui.testKosmos
import com.google.common.truth.Truth.assertThat
-import kotlinx.coroutines.ExperimentalCoroutinesApi
import kotlinx.coroutines.flow.MutableStateFlow
-import kotlinx.coroutines.test.runCurrent
-import kotlinx.coroutines.test.runTest
import org.junit.Before
import org.junit.Test
import org.junit.runner.RunWith
import org.mockito.ArgumentMatchers.anyInt
-import org.mockito.Mock
import org.mockito.Mockito.eq
import org.mockito.Mockito.never
import org.mockito.Mockito.verify
-import org.mockito.MockitoAnnotations
import org.mockito.kotlin.any
import org.mockito.kotlin.argumentCaptor
+import org.mockito.kotlin.doReturn
import org.mockito.kotlin.mock
import org.mockito.kotlin.whenever
+import platform.test.runner.parameterized.ParameterizedAndroidJunit4
+import platform.test.runner.parameterized.Parameters
-@OptIn(ExperimentalCoroutinesApi::class)
@SmallTest
-@RunWith(AndroidJUnit4::class)
-class CommunalWidgetRepositoryLocalImplTest : SysuiTestCase() {
- @Mock private lateinit var appWidgetHost: CommunalAppWidgetHost
- @Mock private lateinit var providerInfoA: AppWidgetProviderInfo
- @Mock private lateinit var providerInfoB: AppWidgetProviderInfo
- @Mock private lateinit var providerInfoC: AppWidgetProviderInfo
- @Mock private lateinit var communalWidgetHost: CommunalWidgetHost
- @Mock private lateinit var communalWidgetDao: CommunalWidgetDao
- @Mock private lateinit var backupManager: BackupManager
+@RunWith(ParameterizedAndroidJunit4::class)
+class CommunalWidgetRepositoryLocalImplTest(flags: FlagsParameterization) : SysuiTestCase() {
+ private val kosmos = testKosmos()
+
+ private val appWidgetHost = mock<CommunalAppWidgetHost>()
+ private val providerInfoA = mock<AppWidgetProviderInfo>()
+ private val providerInfoB = mock<AppWidgetProviderInfo>()
+ private val providerInfoC = mock<AppWidgetProviderInfo>()
private val communalHubStateCaptor = argumentCaptor<CommunalHubState>()
private val componentNameCaptor = argumentCaptor<ComponentName>()
- private lateinit var backupUtils: CommunalBackupUtils
- private lateinit var logBuffer: LogBuffer
- private lateinit var fakeWidgets: MutableStateFlow<Map<CommunalItemRank, CommunalWidgetItem>>
- private lateinit var fakeProviders: MutableStateFlow<Map<Int, AppWidgetProviderInfo?>>
+ private val Kosmos.communalWidgetHost by
+ Kosmos.Fixture {
+ mock<CommunalWidgetHost> { on { appWidgetProviders } doReturn fakeProviders }
+ }
+ private val Kosmos.communalWidgetDao by
+ Kosmos.Fixture { mock<CommunalWidgetDao> { on { getWidgets() } doReturn fakeWidgets } }
- private val kosmos = testKosmos()
- private val testScope = kosmos.testScope
- private val packageChangeRepository = kosmos.fakePackageChangeRepository
- private val userManager = kosmos.userManager
+ private val Kosmos.backupManager by Kosmos.Fixture { mock<BackupManager>() }
+
+ private val Kosmos.backupUtils: CommunalBackupUtils by
+ Kosmos.Fixture { CommunalBackupUtils(applicationContext) }
+
+ private val Kosmos.logBuffer: LogBuffer by
+ Kosmos.Fixture { logcatLogBuffer(name = "CommunalWidgetRepoLocalImplTest") }
+
+ private val Kosmos.fakeWidgets: MutableStateFlow<Map<CommunalItemRank, CommunalWidgetItem>> by
+ Kosmos.Fixture { MutableStateFlow(emptyMap()) }
+
+ private val Kosmos.fakeProviders: MutableStateFlow<Map<Int, AppWidgetProviderInfo?>> by
+ Kosmos.Fixture { MutableStateFlow(emptyMap()) }
private val mainUser = UserHandle(0)
private val workProfile = UserHandle(10)
@@ -105,48 +120,49 @@
"com.android.fake/WidgetProviderC",
)
- private lateinit var underTest: CommunalWidgetRepositoryLocalImpl
-
- @Before
- fun setUp() {
- MockitoAnnotations.initMocks(this)
- fakeWidgets = MutableStateFlow(emptyMap())
- fakeProviders = MutableStateFlow(emptyMap())
- logBuffer = logcatLogBuffer(name = "CommunalWidgetRepoLocalImplTest")
- backupUtils = CommunalBackupUtils(kosmos.applicationContext)
-
- setAppWidgetIds(emptyList())
-
- overrideResource(R.array.config_communalWidgetAllowlist, fakeAllowlist.toTypedArray())
-
- whenever(communalWidgetDao.getWidgets()).thenReturn(fakeWidgets)
- whenever(communalWidgetHost.appWidgetProviders).thenReturn(fakeProviders)
- whenever(userManager.mainUser).thenReturn(mainUser)
-
- restoreUser(mainUser)
-
- underTest =
+ private val Kosmos.underTest by
+ Kosmos.Fixture {
CommunalWidgetRepositoryLocalImpl(
appWidgetHost,
testScope.backgroundScope,
- kosmos.testDispatcher,
+ testDispatcher,
communalWidgetHost,
communalWidgetDao,
logBuffer,
backupManager,
backupUtils,
- packageChangeRepository,
+ fakePackageChangeRepository,
userManager,
- kosmos.defaultWidgetPopulation,
+ defaultWidgetPopulation,
)
+ }
+
+ init {
+ mSetFlagsRule.setFlagsParameterization(flags)
+ }
+
+ @Before
+ fun setUp() {
+ kosmos.userManager = mock<UserManager> { on { mainUser } doReturn mainUser }
+ setAppWidgetIds(emptyList())
+ overrideResource(R.array.config_communalWidgetAllowlist, fakeAllowlist.toTypedArray())
+ restoreUser(mainUser)
}
@Test
fun communalWidgets_queryWidgetsFromDb() =
- testScope.runTest {
+ kosmos.runTest {
val communalItemRankEntry = CommunalItemRank(uid = 1L, rank = 1)
val communalWidgetItemEntry =
- CommunalWidgetItem(uid = 1L, 1, "pk_name/cls_name", 1L, 0, 3)
+ CommunalWidgetItem(
+ uid = 1L,
+ widgetId = 1,
+ componentName = "pk_name/cls_name",
+ itemId = 1L,
+ userSerialNumber = 0,
+ spanY = 3,
+ spanYNew = 1,
+ )
fakeWidgets.value = mapOf(communalItemRankEntry to communalWidgetItemEntry)
fakeProviders.value = mapOf(1 to providerInfoA)
@@ -158,7 +174,12 @@
appWidgetId = communalWidgetItemEntry.widgetId,
providerInfo = providerInfoA,
rank = communalItemRankEntry.rank,
- spanY = communalWidgetItemEntry.spanY,
+ spanY =
+ if (communalResponsiveGrid()) {
+ communalWidgetItemEntry.spanYNew
+ } else {
+ communalWidgetItemEntry.spanY
+ },
)
)
@@ -168,18 +189,50 @@
@Test
fun communalWidgets_widgetsWithoutMatchingProvidersAreSkipped() =
- testScope.runTest {
+ kosmos.runTest {
// Set up 4 widgets, but widget 3 and 4 don't have matching providers
fakeWidgets.value =
mapOf(
CommunalItemRank(uid = 1L, rank = 1) to
- CommunalWidgetItem(uid = 1L, 1, "pk_1/cls_1", 1L, 0, 3),
+ CommunalWidgetItem(
+ uid = 1L,
+ widgetId = 1,
+ componentName = "pk_1/cls_1",
+ itemId = 1L,
+ userSerialNumber = 0,
+ spanY = 3,
+ spanYNew = 1,
+ ),
CommunalItemRank(uid = 2L, rank = 2) to
- CommunalWidgetItem(uid = 2L, 2, "pk_2/cls_2", 2L, 0, 3),
+ CommunalWidgetItem(
+ uid = 2L,
+ widgetId = 2,
+ componentName = "pk_2/cls_2",
+ itemId = 2L,
+ userSerialNumber = 0,
+ spanY = 3,
+ spanYNew = 1,
+ ),
CommunalItemRank(uid = 3L, rank = 3) to
- CommunalWidgetItem(uid = 3L, 3, "pk_3/cls_3", 3L, 0, 3),
+ CommunalWidgetItem(
+ uid = 3L,
+ widgetId = 3,
+ componentName = "pk_3/cls_3",
+ itemId = 3L,
+ userSerialNumber = 0,
+ spanY = 3,
+ spanYNew = 1,
+ ),
CommunalItemRank(uid = 4L, rank = 4) to
- CommunalWidgetItem(uid = 4L, 4, "pk_4/cls_4", 4L, 0, 3),
+ CommunalWidgetItem(
+ uid = 4L,
+ widgetId = 4,
+ componentName = "pk_4/cls_4",
+ itemId = 4L,
+ userSerialNumber = 0,
+ spanY = 3,
+ spanYNew = 1,
+ ),
)
fakeProviders.value = mapOf(1 to providerInfoA, 2 to providerInfoB)
@@ -191,27 +244,43 @@
appWidgetId = 1,
providerInfo = providerInfoA,
rank = 1,
- spanY = 3,
+ spanY = if (communalResponsiveGrid()) 1 else 3,
),
CommunalWidgetContentModel.Available(
appWidgetId = 2,
providerInfo = providerInfoB,
rank = 2,
- spanY = 3,
+ spanY = if (communalResponsiveGrid()) 1 else 3,
),
)
}
@Test
fun communalWidgets_updatedWhenProvidersUpdate() =
- testScope.runTest {
+ kosmos.runTest {
// Set up widgets and providers
fakeWidgets.value =
mapOf(
CommunalItemRank(uid = 1L, rank = 1) to
- CommunalWidgetItem(uid = 1L, 1, "pk_1/cls_1", 1L, 0, 3),
+ CommunalWidgetItem(
+ uid = 1L,
+ widgetId = 1,
+ componentName = "pk_1/cls_1",
+ itemId = 1L,
+ userSerialNumber = 0,
+ spanY = 3,
+ spanYNew = 1,
+ ),
CommunalItemRank(uid = 2L, rank = 2) to
- CommunalWidgetItem(uid = 2L, 2, "pk_2/cls_2", 2L, 0, 3),
+ CommunalWidgetItem(
+ uid = 2L,
+ widgetId = 2,
+ componentName = "pk_2/cls_2",
+ itemId = 2L,
+ userSerialNumber = 0,
+ spanY = 6,
+ spanYNew = 2,
+ ),
)
fakeProviders.value = mapOf(1 to providerInfoA, 2 to providerInfoB)
@@ -224,13 +293,13 @@
appWidgetId = 1,
providerInfo = providerInfoA,
rank = 1,
- spanY = 3,
+ spanY = if (communalResponsiveGrid()) 1 else 3,
),
CommunalWidgetContentModel.Available(
appWidgetId = 2,
providerInfo = providerInfoB,
rank = 2,
- spanY = 3,
+ spanY = if (communalResponsiveGrid()) 2 else 6,
),
)
@@ -245,20 +314,20 @@
// Verify that provider info updated
providerInfo = providerInfoC,
rank = 1,
- spanY = 3,
+ spanY = if (communalResponsiveGrid()) 1 else 3,
),
CommunalWidgetContentModel.Available(
appWidgetId = 2,
providerInfo = providerInfoB,
rank = 2,
- spanY = 3,
+ spanY = if (communalResponsiveGrid()) 2 else 6,
),
)
}
@Test
fun addWidget_allocateId_bindWidget_andAddToDb() =
- testScope.runTest {
+ kosmos.runTest {
val provider = ComponentName("pkg_name", "cls_name")
val id = 1
val rank = 1
@@ -275,7 +344,8 @@
runCurrent()
verify(communalWidgetHost).allocateIdAndBindWidget(provider, mainUser)
- verify(communalWidgetDao).addWidget(id, provider, rank, testUserSerialNumber(mainUser))
+ verify(communalWidgetDao)
+ .addWidget(id, provider, rank, testUserSerialNumber(mainUser), SpanValue.Fixed(3))
// Verify backup requested
verify(backupManager).dataChanged()
@@ -283,7 +353,7 @@
@Test
fun addWidget_configurationFails_doNotAddWidgetToDb() =
- testScope.runTest {
+ kosmos.runTest {
val provider = ComponentName("pkg_name", "cls_name")
val id = 1
val rank = 1
@@ -301,7 +371,7 @@
verify(communalWidgetHost).allocateIdAndBindWidget(provider, mainUser)
verify(communalWidgetDao, never())
- .addWidget(anyInt(), any<ComponentName>(), anyInt(), anyInt(), anyInt())
+ .addWidget(anyInt(), any<ComponentName>(), anyInt(), anyInt(), any())
verify(appWidgetHost).deleteAppWidgetId(id)
// Verify backup not requested
@@ -310,7 +380,7 @@
@Test
fun addWidget_configurationThrowsError_doNotAddWidgetToDb() =
- testScope.runTest {
+ kosmos.runTest {
val provider = ComponentName("pkg_name", "cls_name")
val id = 1
val rank = 1
@@ -330,7 +400,7 @@
verify(communalWidgetHost).allocateIdAndBindWidget(provider, mainUser)
verify(communalWidgetDao, never())
- .addWidget(anyInt(), any<ComponentName>(), anyInt(), anyInt(), anyInt())
+ .addWidget(anyInt(), any<ComponentName>(), anyInt(), anyInt(), any())
verify(appWidgetHost).deleteAppWidgetId(id)
// Verify backup not requested
@@ -339,7 +409,7 @@
@Test
fun addWidget_configurationNotRequired_doesNotConfigure_addWidgetToDb() =
- testScope.runTest {
+ kosmos.runTest {
val provider = ComponentName("pkg_name", "cls_name")
val id = 1
val rank = 1
@@ -356,7 +426,8 @@
runCurrent()
verify(communalWidgetHost).allocateIdAndBindWidget(provider, mainUser)
- verify(communalWidgetDao).addWidget(id, provider, rank, testUserSerialNumber(mainUser))
+ verify(communalWidgetDao)
+ .addWidget(id, provider, rank, testUserSerialNumber(mainUser), SpanValue.Fixed(3))
// Verify backup requested
verify(backupManager).dataChanged()
@@ -364,7 +435,7 @@
@Test
fun deleteWidget_deleteFromDbTrue_alsoDeleteFromHost() =
- testScope.runTest {
+ kosmos.runTest {
val id = 1
whenever(communalWidgetDao.deleteWidgetById(eq(id))).thenReturn(true)
underTest.deleteWidget(id)
@@ -379,7 +450,7 @@
@Test
fun deleteWidget_deleteFromDbFalse_doesNotDeleteFromHost() =
- testScope.runTest {
+ kosmos.runTest {
val id = 1
whenever(communalWidgetDao.deleteWidgetById(eq(id))).thenReturn(false)
underTest.deleteWidget(id)
@@ -394,7 +465,7 @@
@Test
fun reorderWidgets_queryDb() =
- testScope.runTest {
+ kosmos.runTest {
val widgetIdToRankMap = mapOf(104 to 1, 103 to 2, 101 to 3)
underTest.updateWidgetOrder(widgetIdToRankMap)
runCurrent()
@@ -407,7 +478,7 @@
@Test
fun restoreWidgets_deleteStateFileIfRestoreFails() =
- testScope.runTest {
+ kosmos.runTest {
// Write a state file that is invalid, and verify it is written
backupUtils.writeBytesToDisk(byteArrayOf(1, 2, 3, 4, 5, 6))
assertThat(backupUtils.fileExists()).isTrue()
@@ -422,7 +493,7 @@
@Test
fun restoreWidgets_deleteStateFileAfterWidgetsRestored() =
- testScope.runTest {
+ kosmos.runTest {
// Write a state file, and verify it is written
backupUtils.writeBytesToDisk(fakeState.toByteArray())
assertThat(backupUtils.fileExists()).isTrue()
@@ -443,7 +514,7 @@
@Test
fun restoreWidgets_restoredWidgetsNotRegisteredWithHostAreSkipped() =
- testScope.runTest {
+ kosmos.runTest {
// Write fake state to file
backupUtils.writeBytesToDisk(fakeState.toByteArray())
@@ -470,7 +541,7 @@
@Test
fun restoreWidgets_registeredWidgetsNotRestoredAreRemoved() =
- testScope.runTest {
+ kosmos.runTest {
// Write fake state to file
backupUtils.writeBytesToDisk(fakeState.toByteArray())
@@ -504,7 +575,7 @@
@Test
fun restoreWidgets_onlySomeWidgetsGotNewIds() =
- testScope.runTest {
+ kosmos.runTest {
// Write fake state to file
backupUtils.writeBytesToDisk(fakeState.toByteArray())
@@ -536,7 +607,7 @@
@Test
fun restoreWidgets_undefinedUser_restoredAsMain() =
- testScope.runTest {
+ kosmos.runTest {
// Write two widgets to file, both of which have user serial number undefined.
val fakeState =
CommunalHubState().apply {
@@ -584,7 +655,7 @@
@Test
fun restoreWidgets_workProfileNotRestored_widgetSkipped() =
- testScope.runTest {
+ kosmos.runTest {
// Write fake state to file
backupUtils.writeBytesToDisk(fakeStateWithWorkProfile.toByteArray())
@@ -610,7 +681,7 @@
@Test
fun restoreWidgets_workProfileRestored_manuallyBindWidget() =
- testScope.runTest {
+ kosmos.runTest {
// Write fake state to file
backupUtils.writeBytesToDisk(fakeStateWithWorkProfile.toByteArray())
@@ -649,7 +720,7 @@
componentNameCaptor.capture(),
eq(2),
eq(testUserSerialNumber(workProfile)),
- anyInt(),
+ any(),
)
assertThat(componentNameCaptor.firstValue)
@@ -658,13 +729,29 @@
@Test
fun pendingWidgets() =
- testScope.runTest {
+ kosmos.runTest {
fakeWidgets.value =
mapOf(
CommunalItemRank(uid = 1L, rank = 1) to
- CommunalWidgetItem(uid = 1L, 1, "pk_1/cls_1", 1L, 0, 3),
+ CommunalWidgetItem(
+ uid = 1L,
+ widgetId = 1,
+ componentName = "pk_1/cls_1",
+ itemId = 1L,
+ userSerialNumber = 0,
+ spanY = 3,
+ spanYNew = 1,
+ ),
CommunalItemRank(uid = 2L, rank = 2) to
- CommunalWidgetItem(uid = 2L, 2, "pk_2/cls_2", 2L, 0, 3),
+ CommunalWidgetItem(
+ uid = 2L,
+ widgetId = 2,
+ componentName = "pk_2/cls_2",
+ itemId = 2L,
+ userSerialNumber = 0,
+ spanY = 3,
+ spanYNew = 1,
+ ),
)
// Widget 1 is installed
@@ -672,7 +759,7 @@
// Widget 2 is pending install
val fakeIcon = mock<Bitmap>()
- packageChangeRepository.setInstallSessions(
+ fakePackageChangeRepository.setInstallSessions(
listOf(
PackageInstallSession(
sessionId = 1,
@@ -690,7 +777,7 @@
appWidgetId = 1,
providerInfo = providerInfoA,
rank = 1,
- spanY = 3,
+ spanY = if (communalResponsiveGrid()) 1 else 3,
),
CommunalWidgetContentModel.Pending(
appWidgetId = 2,
@@ -698,23 +785,31 @@
componentName = ComponentName("pk_2", "cls_2"),
icon = fakeIcon,
user = mainUser,
- spanY = 3,
+ spanY = if (communalResponsiveGrid()) 1 else 3,
),
)
}
@Test
fun pendingWidgets_pendingWidgetBecomesAvailableAfterInstall() =
- testScope.runTest {
+ kosmos.runTest {
fakeWidgets.value =
mapOf(
CommunalItemRank(uid = 1L, rank = 1) to
- CommunalWidgetItem(uid = 1L, 1, "pk_1/cls_1", 1L, 0, 3)
+ CommunalWidgetItem(
+ uid = 1L,
+ widgetId = 1,
+ componentName = "pk_1/cls_1",
+ itemId = 1L,
+ userSerialNumber = 0,
+ spanY = 3,
+ spanYNew = 1,
+ )
)
// Widget 1 is pending install
val fakeIcon = mock<Bitmap>()
- packageChangeRepository.setInstallSessions(
+ fakePackageChangeRepository.setInstallSessions(
listOf(
PackageInstallSession(
sessionId = 1,
@@ -734,12 +829,12 @@
componentName = ComponentName("pk_1", "cls_1"),
icon = fakeIcon,
user = mainUser,
- spanY = 3,
+ spanY = if (communalResponsiveGrid()) 1 else 3,
)
)
// Package for widget 1 finished installing
- packageChangeRepository.setInstallSessions(emptyList())
+ fakePackageChangeRepository.setInstallSessions(emptyList())
// Provider info for widget 1 becomes available
fakeProviders.value = mapOf(1 to providerInfoA)
@@ -752,15 +847,16 @@
appWidgetId = 1,
providerInfo = providerInfoA,
rank = 1,
- spanY = 3,
+ spanY = if (communalResponsiveGrid()) 1 else 3,
)
)
}
@Test
@EnableFlags(FLAG_COMMUNAL_WIDGET_RESIZING)
- fun updateWidgetSpanY_updatesWidgetInDaoAndRequestsBackup() =
- testScope.runTest {
+ @DisableFlags(FLAG_COMMUNAL_RESPONSIVE_GRID)
+ fun updateWidgetSpanY_updatesWidgetInDaoAndRequestsBackup_fixed() =
+ kosmos.runTest {
val widgetId = 1
val newSpanY = 6
val widgetIdToRankMap = emptyMap<Int, Int>()
@@ -768,7 +864,24 @@
underTest.resizeWidget(widgetId, newSpanY, widgetIdToRankMap)
runCurrent()
- verify(communalWidgetDao).resizeWidget(widgetId, newSpanY, widgetIdToRankMap)
+ verify(communalWidgetDao)
+ .resizeWidget(widgetId, SpanValue.Fixed(newSpanY), widgetIdToRankMap)
+ verify(backupManager).dataChanged()
+ }
+
+ @Test
+ @EnableFlags(FLAG_COMMUNAL_WIDGET_RESIZING, FLAG_COMMUNAL_RESPONSIVE_GRID)
+ fun updateWidgetSpanY_updatesWidgetInDaoAndRequestsBackup_responsive() =
+ kosmos.runTest {
+ val widgetId = 1
+ val newSpanY = 6
+ val widgetIdToRankMap = emptyMap<Int, Int>()
+
+ underTest.resizeWidget(widgetId, newSpanY, widgetIdToRankMap)
+ runCurrent()
+
+ verify(communalWidgetDao)
+ .resizeWidget(widgetId, SpanValue.Responsive(newSpanY), widgetIdToRankMap)
verify(backupManager).dataChanged()
}
@@ -784,13 +897,19 @@
}
private fun restoreUser(user: UserHandle) {
- whenever(backupManager.getUserForAncestralSerialNumber(user.identifier.toLong()))
+ whenever(kosmos.backupManager.getUserForAncestralSerialNumber(user.identifier.toLong()))
.thenReturn(user)
- whenever(userManager.getUserSerialNumber(user.identifier))
+ whenever(kosmos.userManager.getUserSerialNumber(user.identifier))
.thenReturn(testUserSerialNumber(user))
}
- private companion object {
+ companion object {
+ @JvmStatic
+ @Parameters(name = "{0}")
+ fun getParams(): List<FlagsParameterization> {
+ return FlagsParameterization.allCombinationsOf(FLAG_COMMUNAL_RESPONSIVE_GRID)
+ }
+
val PROVIDER_INFO_REQUIRES_CONFIGURATION =
AppWidgetProviderInfo().apply { configure = ComponentName("test.pkg", "test.cmp") }
val PROVIDER_INFO_CONFIGURATION_OPTIONAL =
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/communal/domain/interactor/CommunalInteractorTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/communal/domain/interactor/CommunalInteractorTest.kt
index 611a61a6..b9e646f 100644
--- a/packages/SystemUI/multivalentTests/src/com/android/systemui/communal/domain/interactor/CommunalInteractorTest.kt
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/communal/domain/interactor/CommunalInteractorTest.kt
@@ -24,14 +24,16 @@
import android.os.UserHandle
import android.os.UserManager
import android.os.userManager
+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.provider.Settings.Secure.HUB_MODE_TUTORIAL_COMPLETED
import android.widget.RemoteViews
-import androidx.test.ext.junit.runners.AndroidJUnit4
import androidx.test.filters.SmallTest
import com.android.compose.animation.scene.ObservableTransitionState
import com.android.systemui.Flags.FLAG_COMMUNAL_HUB
+import com.android.systemui.Flags.FLAG_COMMUNAL_RESPONSIVE_GRID
import com.android.systemui.Flags.FLAG_COMMUNAL_WIDGET_RESIZING
import com.android.systemui.SysuiTestCase
import com.android.systemui.broadcast.broadcastDispatcher
@@ -96,6 +98,8 @@
import org.mockito.Mockito.mock
import org.mockito.Mockito.verify
import org.mockito.MockitoAnnotations
+import platform.test.runner.parameterized.ParameterizedAndroidJunit4
+import platform.test.runner.parameterized.Parameters
/**
* This class of test cases assume that communal is enabled. For disabled cases, see
@@ -103,8 +107,8 @@
*/
@SmallTest
@OptIn(ExperimentalCoroutinesApi::class)
-@RunWith(AndroidJUnit4::class)
-class CommunalInteractorTest : SysuiTestCase() {
+@RunWith(ParameterizedAndroidJunit4::class)
+class CommunalInteractorTest(flags: FlagsParameterization) : SysuiTestCase() {
@Mock private lateinit var mainUser: UserInfo
@Mock private lateinit var secondaryUser: UserInfo
@@ -129,6 +133,10 @@
private lateinit var underTest: CommunalInteractor
+ init {
+ mSetFlagsRule.setFlagsParameterization(flags)
+ }
+
@Before
fun setUp() {
MockitoAnnotations.initMocks(this)
@@ -262,71 +270,84 @@
assertThat(widgetContent!![2].appWidgetId).isEqualTo(3)
}
+ /** TODO(b/378171351): Handle ongoing content in responsive grid. */
@Test
+ @DisableFlags(FLAG_COMMUNAL_RESPONSIVE_GRID)
fun smartspaceDynamicSizing_oneCard_fullSize() =
testSmartspaceDynamicSizing(
totalTargets = 1,
- expectedSizes = listOf(CommunalContentSize.FULL),
+ expectedSizes = listOf(CommunalContentSize.FixedSize.FULL),
)
+ /** TODO(b/378171351): Handle ongoing content in responsive grid. */
@Test
+ @DisableFlags(FLAG_COMMUNAL_RESPONSIVE_GRID)
fun smartspace_dynamicSizing_twoCards_halfSize() =
testSmartspaceDynamicSizing(
totalTargets = 2,
- expectedSizes = listOf(CommunalContentSize.HALF, CommunalContentSize.HALF),
+ expectedSizes =
+ listOf(CommunalContentSize.FixedSize.HALF, CommunalContentSize.FixedSize.HALF),
)
+ /** TODO(b/378171351): Handle ongoing content in responsive grid. */
@Test
+ @DisableFlags(FLAG_COMMUNAL_RESPONSIVE_GRID)
fun smartspace_dynamicSizing_threeCards_thirdSize() =
testSmartspaceDynamicSizing(
totalTargets = 3,
expectedSizes =
listOf(
- CommunalContentSize.THIRD,
- CommunalContentSize.THIRD,
- CommunalContentSize.THIRD,
+ CommunalContentSize.FixedSize.THIRD,
+ CommunalContentSize.FixedSize.THIRD,
+ CommunalContentSize.FixedSize.THIRD,
),
)
+ /** TODO(b/378171351): Handle ongoing content in responsive grid. */
@Test
+ @DisableFlags(FLAG_COMMUNAL_RESPONSIVE_GRID)
fun smartspace_dynamicSizing_fourCards_threeThirdSizeAndOneFullSize() =
testSmartspaceDynamicSizing(
totalTargets = 4,
expectedSizes =
listOf(
- CommunalContentSize.THIRD,
- CommunalContentSize.THIRD,
- CommunalContentSize.THIRD,
- CommunalContentSize.FULL,
+ CommunalContentSize.FixedSize.THIRD,
+ CommunalContentSize.FixedSize.THIRD,
+ CommunalContentSize.FixedSize.THIRD,
+ CommunalContentSize.FixedSize.FULL,
),
)
+ /** TODO(b/378171351): Handle ongoing content in responsive grid. */
@Test
+ @DisableFlags(FLAG_COMMUNAL_RESPONSIVE_GRID)
fun smartspace_dynamicSizing_fiveCards_threeThirdAndTwoHalfSize() =
testSmartspaceDynamicSizing(
totalTargets = 5,
expectedSizes =
listOf(
- CommunalContentSize.THIRD,
- CommunalContentSize.THIRD,
- CommunalContentSize.THIRD,
- CommunalContentSize.HALF,
- CommunalContentSize.HALF,
+ CommunalContentSize.FixedSize.THIRD,
+ CommunalContentSize.FixedSize.THIRD,
+ CommunalContentSize.FixedSize.THIRD,
+ CommunalContentSize.FixedSize.HALF,
+ CommunalContentSize.FixedSize.HALF,
),
)
+ /** TODO(b/378171351): Handle ongoing content in responsive grid. */
@Test
+ @DisableFlags(FLAG_COMMUNAL_RESPONSIVE_GRID)
fun smartspace_dynamicSizing_sixCards_allThirdSize() =
testSmartspaceDynamicSizing(
totalTargets = 6,
expectedSizes =
listOf(
- CommunalContentSize.THIRD,
- CommunalContentSize.THIRD,
- CommunalContentSize.THIRD,
- CommunalContentSize.THIRD,
- CommunalContentSize.THIRD,
- CommunalContentSize.THIRD,
+ CommunalContentSize.FixedSize.THIRD,
+ CommunalContentSize.FixedSize.THIRD,
+ CommunalContentSize.FixedSize.THIRD,
+ CommunalContentSize.FixedSize.THIRD,
+ CommunalContentSize.FixedSize.THIRD,
+ CommunalContentSize.FixedSize.THIRD,
),
)
@@ -383,7 +404,9 @@
assertThat(umoContent?.size).isEqualTo(0)
}
+ /** TODO(b/378171351): Handle ongoing content in responsive grid. */
@Test
+ @DisableFlags(FLAG_COMMUNAL_RESPONSIVE_GRID)
fun ongoing_shouldOrderAndSizeByTimestamp() =
testScope.runTest {
// Keyguard showing, and tutorial completed.
@@ -410,15 +433,15 @@
assertThat(ongoingContent?.size).isEqualTo(4)
assertThat(ongoingContent?.get(0)?.key)
.isEqualTo(CommunalContentModel.KEY.smartspace("timer3"))
- assertThat(ongoingContent?.get(0)?.size).isEqualTo(CommunalContentSize.HALF)
+ assertThat(ongoingContent?.get(0)?.size).isEqualTo(CommunalContentSize.FixedSize.HALF)
assertThat(ongoingContent?.get(1)?.key)
.isEqualTo(CommunalContentModel.KEY.smartspace("timer2"))
- assertThat(ongoingContent?.get(1)?.size).isEqualTo(CommunalContentSize.HALF)
+ assertThat(ongoingContent?.get(1)?.size).isEqualTo(CommunalContentSize.FixedSize.HALF)
assertThat(ongoingContent?.get(2)?.key).isEqualTo(CommunalContentModel.KEY.umo())
- assertThat(ongoingContent?.get(2)?.size).isEqualTo(CommunalContentSize.HALF)
+ assertThat(ongoingContent?.get(2)?.size).isEqualTo(CommunalContentSize.FixedSize.HALF)
assertThat(ongoingContent?.get(3)?.key)
.isEqualTo(CommunalContentModel.KEY.smartspace("timer1"))
- assertThat(ongoingContent?.get(3)?.size).isEqualTo(CommunalContentSize.HALF)
+ assertThat(ongoingContent?.get(3)?.size).isEqualTo(CommunalContentSize.FixedSize.HALF)
}
@Test
@@ -1082,6 +1105,7 @@
@Test
@EnableFlags(FLAG_COMMUNAL_WIDGET_RESIZING)
+ @DisableFlags(FLAG_COMMUNAL_RESPONSIVE_GRID)
fun resizeWidget_withoutUpdatingOrder() =
testScope.runTest {
val userInfos = listOf(MAIN_USER_INFO)
@@ -1094,45 +1118,97 @@
appWidgetId = 1,
userId = MAIN_USER_INFO.id,
rank = 0,
- spanY = CommunalContentSize.HALF.span,
+ spanY = CommunalContentSize.FixedSize.HALF.span,
)
widgetRepository.addWidget(
appWidgetId = 2,
userId = MAIN_USER_INFO.id,
rank = 1,
- spanY = CommunalContentSize.HALF.span,
+ spanY = CommunalContentSize.FixedSize.HALF.span,
)
widgetRepository.addWidget(
appWidgetId = 3,
userId = MAIN_USER_INFO.id,
rank = 2,
- spanY = CommunalContentSize.HALF.span,
+ spanY = CommunalContentSize.FixedSize.HALF.span,
)
val widgetContent by collectLastValue(underTest.widgetContent)
assertThat(widgetContent?.map { it.appWidgetId to it.size })
.containsExactly(
- 1 to CommunalContentSize.HALF,
- 2 to CommunalContentSize.HALF,
- 3 to CommunalContentSize.HALF,
+ 1 to CommunalContentSize.FixedSize.HALF,
+ 2 to CommunalContentSize.FixedSize.HALF,
+ 3 to CommunalContentSize.FixedSize.HALF,
)
.inOrder()
- underTest.resizeWidget(2, CommunalContentSize.FULL.span, emptyMap())
+ underTest.resizeWidget(2, CommunalContentSize.FixedSize.FULL.span, emptyMap())
// Widget 2 should have been resized to FULL
assertThat(widgetContent?.map { it.appWidgetId to it.size })
.containsExactly(
- 1 to CommunalContentSize.HALF,
- 2 to CommunalContentSize.FULL,
- 3 to CommunalContentSize.HALF,
+ 1 to CommunalContentSize.FixedSize.HALF,
+ 2 to CommunalContentSize.FixedSize.FULL,
+ 3 to CommunalContentSize.FixedSize.HALF,
+ )
+ .inOrder()
+ }
+
+ @Test
+ @EnableFlags(FLAG_COMMUNAL_WIDGET_RESIZING, FLAG_COMMUNAL_RESPONSIVE_GRID)
+ fun resizeWidget_withoutUpdatingOrder_responsive() =
+ testScope.runTest {
+ val userInfos = listOf(MAIN_USER_INFO)
+ userRepository.setUserInfos(userInfos)
+ userTracker.set(userInfos = userInfos, selectedUserIndex = 0)
+ runCurrent()
+
+ // Widgets available.
+ widgetRepository.addWidget(
+ appWidgetId = 1,
+ userId = MAIN_USER_INFO.id,
+ rank = 0,
+ spanY = 1,
+ )
+ widgetRepository.addWidget(
+ appWidgetId = 2,
+ userId = MAIN_USER_INFO.id,
+ rank = 1,
+ spanY = 1,
+ )
+ widgetRepository.addWidget(
+ appWidgetId = 3,
+ userId = MAIN_USER_INFO.id,
+ rank = 2,
+ spanY = 1,
+ )
+
+ val widgetContent by collectLastValue(underTest.widgetContent)
+
+ assertThat(widgetContent?.map { it.appWidgetId to it.size })
+ .containsExactly(
+ 1 to CommunalContentSize.Responsive(1),
+ 2 to CommunalContentSize.Responsive(1),
+ 3 to CommunalContentSize.Responsive(1),
+ )
+ .inOrder()
+
+ underTest.resizeWidget(appWidgetId = 2, spanY = 5, widgetIdToRankMap = emptyMap())
+
+ // Widget 2 should have been resized to FULL
+ assertThat(widgetContent?.map { it.appWidgetId to it.size })
+ .containsExactly(
+ 1 to CommunalContentSize.Responsive(1),
+ 2 to CommunalContentSize.Responsive(5),
+ 3 to CommunalContentSize.Responsive(1),
)
.inOrder()
}
@Test
@EnableFlags(FLAG_COMMUNAL_WIDGET_RESIZING)
+ @DisableFlags(FLAG_COMMUNAL_RESPONSIVE_GRID)
fun resizeWidget_andUpdateOrder() =
testScope.runTest {
val userInfos = listOf(MAIN_USER_INFO)
@@ -1145,39 +1221,98 @@
appWidgetId = 1,
userId = MAIN_USER_INFO.id,
rank = 0,
- spanY = CommunalContentSize.HALF.span,
+ spanY = CommunalContentSize.FixedSize.HALF.span,
)
widgetRepository.addWidget(
appWidgetId = 2,
userId = MAIN_USER_INFO.id,
rank = 1,
- spanY = CommunalContentSize.HALF.span,
+ spanY = CommunalContentSize.FixedSize.HALF.span,
)
widgetRepository.addWidget(
appWidgetId = 3,
userId = MAIN_USER_INFO.id,
rank = 2,
- spanY = CommunalContentSize.HALF.span,
+ spanY = CommunalContentSize.FixedSize.HALF.span,
)
val widgetContent by collectLastValue(underTest.widgetContent)
assertThat(widgetContent?.map { it.appWidgetId to it.size })
.containsExactly(
- 1 to CommunalContentSize.HALF,
- 2 to CommunalContentSize.HALF,
- 3 to CommunalContentSize.HALF,
+ 1 to CommunalContentSize.FixedSize.HALF,
+ 2 to CommunalContentSize.FixedSize.HALF,
+ 3 to CommunalContentSize.FixedSize.HALF,
)
.inOrder()
- underTest.resizeWidget(2, CommunalContentSize.FULL.span, mapOf(2 to 0, 1 to 1))
+ underTest.resizeWidget(
+ 2,
+ CommunalContentSize.FixedSize.FULL.span,
+ mapOf(2 to 0, 1 to 1),
+ )
// Widget 2 should have been resized to FULL and moved to the front of the list
assertThat(widgetContent?.map { it.appWidgetId to it.size })
.containsExactly(
- 2 to CommunalContentSize.FULL,
- 1 to CommunalContentSize.HALF,
- 3 to CommunalContentSize.HALF,
+ 2 to CommunalContentSize.FixedSize.FULL,
+ 1 to CommunalContentSize.FixedSize.HALF,
+ 3 to CommunalContentSize.FixedSize.HALF,
+ )
+ .inOrder()
+ }
+
+ @Test
+ @EnableFlags(FLAG_COMMUNAL_WIDGET_RESIZING, FLAG_COMMUNAL_RESPONSIVE_GRID)
+ fun resizeWidget_andUpdateOrder_responsive() =
+ testScope.runTest {
+ val userInfos = listOf(MAIN_USER_INFO)
+ userRepository.setUserInfos(userInfos)
+ userTracker.set(userInfos = userInfos, selectedUserIndex = 0)
+ runCurrent()
+
+ // Widgets available.
+ widgetRepository.addWidget(
+ appWidgetId = 1,
+ userId = MAIN_USER_INFO.id,
+ rank = 0,
+ spanY = 1,
+ )
+ widgetRepository.addWidget(
+ appWidgetId = 2,
+ userId = MAIN_USER_INFO.id,
+ rank = 1,
+ spanY = 1,
+ )
+ widgetRepository.addWidget(
+ appWidgetId = 3,
+ userId = MAIN_USER_INFO.id,
+ rank = 2,
+ spanY = 1,
+ )
+
+ val widgetContent by collectLastValue(underTest.widgetContent)
+
+ assertThat(widgetContent?.map { it.appWidgetId to it.size })
+ .containsExactly(
+ 1 to CommunalContentSize.Responsive(1),
+ 2 to CommunalContentSize.Responsive(1),
+ 3 to CommunalContentSize.Responsive(1),
+ )
+ .inOrder()
+
+ underTest.resizeWidget(
+ appWidgetId = 2,
+ spanY = 5,
+ widgetIdToRankMap = mapOf(2 to 0, 1 to 1),
+ )
+
+ // Widget 2 should have been resized to FULL and moved to the front of the list
+ assertThat(widgetContent?.map { it.appWidgetId to it.size })
+ .containsExactly(
+ 2 to CommunalContentSize.Responsive(5),
+ 1 to CommunalContentSize.Responsive(1),
+ 3 to CommunalContentSize.Responsive(1),
)
.inOrder()
}
@@ -1191,9 +1326,15 @@
)
}
- private companion object {
- val MAIN_USER_INFO = UserInfo(0, "primary", UserInfo.FLAG_MAIN)
- val USER_INFO_WORK =
+ companion object {
+ @JvmStatic
+ @Parameters(name = "{0}")
+ fun getParams(): List<FlagsParameterization> {
+ return FlagsParameterization.allCombinationsOf(FLAG_COMMUNAL_RESPONSIVE_GRID)
+ }
+
+ private val MAIN_USER_INFO = UserInfo(0, "primary", UserInfo.FLAG_MAIN)
+ private val USER_INFO_WORK =
UserInfo(
10,
"work",
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/communal/view/viewmodel/CommunalViewModelTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/communal/view/viewmodel/CommunalViewModelTest.kt
index 3eba8ff..763ea39 100644
--- a/packages/SystemUI/multivalentTests/src/com/android/systemui/communal/view/viewmodel/CommunalViewModelTest.kt
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/communal/view/viewmodel/CommunalViewModelTest.kt
@@ -18,12 +18,14 @@
import android.content.ComponentName
import android.content.pm.UserInfo
+import android.platform.test.annotations.DisableFlags
import android.platform.test.flag.junit.FlagsParameterization
import android.provider.Settings
import android.widget.RemoteViews
import androidx.test.filters.SmallTest
import com.android.compose.animation.scene.ObservableTransitionState
import com.android.systemui.Flags.FLAG_COMMUNAL_HUB
+import com.android.systemui.Flags.FLAG_COMMUNAL_RESPONSIVE_GRID
import com.android.systemui.SysuiTestCase
import com.android.systemui.communal.data.model.CommunalSmartspaceTimer
import com.android.systemui.communal.data.repository.FakeCommunalMediaRepository
@@ -248,7 +250,9 @@
.isInstanceOf(CommunalContentModel.CtaTileInViewMode::class.java)
}
+ /** TODO(b/378171351): Handle ongoing content in responsive grid. */
@Test
+ @DisableFlags(FLAG_COMMUNAL_RESPONSIVE_GRID)
fun ongoingContent_umoAndOneTimer_sizedAppropriately() =
testScope.runTest {
// Widgets available.
@@ -280,11 +284,13 @@
assertThat(timer).isInstanceOf(CommunalContentModel.Smartspace::class.java)
assertThat(umo).isInstanceOf(CommunalContentModel.Umo::class.java)
- assertThat(timer?.size).isEqualTo(CommunalContentSize.HALF)
- assertThat(umo?.size).isEqualTo(CommunalContentSize.HALF)
+ assertThat(timer?.size).isEqualTo(CommunalContentSize.FixedSize.HALF)
+ assertThat(umo?.size).isEqualTo(CommunalContentSize.FixedSize.HALF)
}
+ /** TODO(b/378171351): Handle ongoing content in responsive grid. */
@Test
+ @DisableFlags(FLAG_COMMUNAL_RESPONSIVE_GRID)
fun ongoingContent_umoAndTwoTimers_sizedAppropriately() =
testScope.runTest {
// Widgets available.
@@ -324,9 +330,9 @@
assertThat(umo).isInstanceOf(CommunalContentModel.Umo::class.java)
// One full-sized timer and a half-sized timer and half-sized UMO.
- assertThat(timer1?.size).isEqualTo(CommunalContentSize.HALF)
- assertThat(timer2?.size).isEqualTo(CommunalContentSize.HALF)
- assertThat(umo?.size).isEqualTo(CommunalContentSize.FULL)
+ assertThat(timer1?.size).isEqualTo(CommunalContentSize.FixedSize.HALF)
+ assertThat(timer2?.size).isEqualTo(CommunalContentSize.FixedSize.HALF)
+ assertThat(umo?.size).isEqualTo(CommunalContentSize.FixedSize.FULL)
}
@Test
@@ -891,7 +897,8 @@
@JvmStatic
@Parameters(name = "{0}")
fun getParams(): List<FlagsParameterization> {
- return FlagsParameterization.allCombinationsOf().andSceneContainer()
+ return FlagsParameterization.allCombinationsOf(FLAG_COMMUNAL_RESPONSIVE_GRID)
+ .andSceneContainer()
}
}
}
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/qs/tiles/QuickAccessWalletTileTest.java b/packages/SystemUI/multivalentTests/src/com/android/systemui/qs/tiles/QuickAccessWalletTileTest.java
index 03c1f92..4068d9f 100644
--- a/packages/SystemUI/multivalentTests/src/com/android/systemui/qs/tiles/QuickAccessWalletTileTest.java
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/qs/tiles/QuickAccessWalletTileTest.java
@@ -46,6 +46,9 @@
import android.graphics.drawable.Icon;
import android.os.Handler;
import android.os.UserHandle;
+import android.platform.test.annotations.DisableFlags;
+import android.platform.test.annotations.EnableFlags;
+import android.service.quickaccesswallet.Flags;
import android.service.quickaccesswallet.GetWalletCardsError;
import android.service.quickaccesswallet.GetWalletCardsResponse;
import android.service.quickaccesswallet.QuickAccessWalletClient;
@@ -221,6 +224,7 @@
}
@Test
+ @DisableFlags({Flags.FLAG_LAUNCH_SELECTED_CARD_FROM_QS_TILE})
public void testHandleClick_startQuickAccessUiIntent_noCard() {
setUpWalletCard(/* hasCard= */ false);
@@ -234,6 +238,7 @@
}
@Test
+ @DisableFlags({Flags.FLAG_LAUNCH_SELECTED_CARD_FROM_QS_TILE})
public void testHandleClick_startQuickAccessUiIntent_hasCard() {
setUpWalletCard(/* hasCard= */ true);
@@ -247,6 +252,34 @@
}
@Test
+ @EnableFlags({Flags.FLAG_LAUNCH_SELECTED_CARD_FROM_QS_TILE})
+ public void testHandleClick_startCardIntent_noCard() {
+ setUpWalletCard(/* hasCard= */ false);
+
+ mTile.handleClick(/* view= */ null);
+ mTestableLooper.processAllMessages();
+
+ verify(mController).startQuickAccessUiIntent(
+ eq(mActivityStarter),
+ eq(null),
+ /* hasCard= */ eq(false));
+ }
+
+ @Test
+ @EnableFlags({Flags.FLAG_LAUNCH_SELECTED_CARD_FROM_QS_TILE})
+ public void testHandleClick_startCardIntent_hasCard() {
+ setUpWalletCard(/* hasCard= */ true);
+
+ mTile.handleClick(null /* view */);
+ mTestableLooper.processAllMessages();
+
+ verify(mController).startWalletCardPendingIntent(
+ any(),
+ eq(mActivityStarter),
+ eq(null));
+ }
+
+ @Test
public void testHandleUpdateState_updateLabelAndIcon() {
QSTile.State state = new QSTile.State();
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/shade/NotificationShadeWindowControllerImplTest.java b/packages/SystemUI/multivalentTests/src/com/android/systemui/shade/NotificationShadeWindowControllerImplTest.java
index 093ef46..764068e 100644
--- a/packages/SystemUI/multivalentTests/src/com/android/systemui/shade/NotificationShadeWindowControllerImplTest.java
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/shade/NotificationShadeWindowControllerImplTest.java
@@ -172,7 +172,8 @@
mUserTracker,
mKosmos.getNotificationShadeWindowModel(),
mSecureSettings,
- mKosmos::getCommunalInteractor);
+ mKosmos::getCommunalInteractor,
+ mKosmos.getShadeLayoutParams());
mNotificationShadeWindowController.setScrimsVisibilityListener((visibility) -> {});
mNotificationShadeWindowController.fetchWindowRootView();
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/shade/domain/interactor/ShadeDisplaysInteractorTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/shade/domain/interactor/ShadeDisplaysInteractorTest.kt
index 80cf2f0..a8d5c31 100644
--- a/packages/SystemUI/multivalentTests/src/com/android/systemui/shade/domain/interactor/ShadeDisplaysInteractorTest.kt
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/shade/domain/interactor/ShadeDisplaysInteractorTest.kt
@@ -16,29 +16,25 @@
package com.android.systemui.shade.domain.interactor
-import android.content.Context
+import android.content.mockedContext
import android.content.res.Configuration
-import android.content.res.Resources
+import android.content.res.mockResources
import android.view.Display
-import android.view.WindowManager
-import android.view.WindowManager.LayoutParams.TYPE_NOTIFICATION_SHADE
+import android.view.mockWindowManager
import androidx.test.ext.junit.runners.AndroidJUnit4
import androidx.test.filters.SmallTest
import com.android.systemui.SysuiTestCase
-import com.android.systemui.display.data.repository.FakeDisplayWindowPropertiesRepository
-import com.android.systemui.display.shared.model.DisplayWindowProperties
-import com.android.systemui.scene.ui.view.WindowRootView
-import com.android.systemui.shade.data.repository.FakeShadeDisplayRepository
-import java.util.Optional
+import com.android.systemui.kosmos.testScope
+import com.android.systemui.kosmos.useUnconfinedTestDispatcher
+import com.android.systemui.scene.ui.view.mockShadeRootView
+import com.android.systemui.shade.data.repository.fakeShadeDisplaysRepository
+import com.android.systemui.testKosmos
import kotlinx.coroutines.ExperimentalCoroutinesApi
-import kotlinx.coroutines.test.TestScope
-import kotlinx.coroutines.test.UnconfinedTestDispatcher
import kotlinx.coroutines.test.advanceUntilIdle
import org.junit.Before
import org.junit.Test
import org.junit.runner.RunWith
import org.mockito.Mockito.inOrder
-import org.mockito.Mockito.verify
import org.mockito.kotlin.any
import org.mockito.kotlin.eq
import org.mockito.kotlin.mock
@@ -49,26 +45,18 @@
@RunWith(AndroidJUnit4::class)
@SmallTest
class ShadeDisplaysInteractorTest : SysuiTestCase() {
+ val kosmos = testKosmos().useUnconfinedTestDispatcher()
- private val shadeRootview = mock<WindowRootView>()
- private val positionRepository = FakeShadeDisplayRepository()
- private val shadeContext = mock<Context>()
- private val contextStore = FakeDisplayWindowPropertiesRepository(context)
- private val testScope = TestScope(UnconfinedTestDispatcher())
- private val shadeWm = mock<WindowManager>()
- private val resources = mock<Resources>()
+ private val shadeRootview = kosmos.mockShadeRootView
+ private val positionRepository = kosmos.fakeShadeDisplaysRepository
+ private val shadeContext = kosmos.mockedContext
+ private val testScope = kosmos.testScope
+ private val shadeWm = kosmos.mockWindowManager
+ private val resources = kosmos.mockResources
private val configuration = mock<Configuration>()
private val display = mock<Display>()
- private val interactor =
- ShadeDisplaysInteractor(
- Optional.of(shadeRootview),
- positionRepository,
- shadeContext,
- shadeWm,
- testScope.backgroundScope,
- testScope.backgroundScope.coroutineContext,
- )
+ private val underTest = kosmos.shadeDisplaysInteractor
@Before
fun setup() {
@@ -80,23 +68,14 @@
whenever(shadeContext.displayId).thenReturn(0)
whenever(shadeContext.getSystemService(any())).thenReturn(shadeWm)
whenever(shadeContext.resources).thenReturn(resources)
- contextStore.insert(
- DisplayWindowProperties(
- displayId = 0,
- windowType = TYPE_NOTIFICATION_SHADE,
- context = shadeContext,
- windowManager = shadeWm,
- layoutInflater = mock(),
- )
- )
}
@Test
fun start_shadeInCorrectPosition_notAddedOrRemoved() {
whenever(display.displayId).thenReturn(0)
positionRepository.setDisplayId(0)
- interactor.start()
- testScope.advanceUntilIdle()
+
+ underTest.start()
verifyNoMoreInteractions(shadeWm)
}
@@ -105,7 +84,8 @@
fun start_shadeInWrongPosition_changes() {
whenever(display.displayId).thenReturn(0)
positionRepository.setDisplayId(1)
- interactor.start()
+
+ underTest.start()
inOrder(shadeWm).apply {
verify(shadeWm).removeView(eq(shadeRootview))
@@ -117,9 +97,10 @@
fun start_shadePositionChanges_removedThenAdded() {
whenever(display.displayId).thenReturn(0)
positionRepository.setDisplayId(0)
- interactor.start()
+ underTest.start()
positionRepository.setDisplayId(1)
+ testScope.advanceUntilIdle()
inOrder(shadeWm).apply {
verify(shadeWm).removeView(eq(shadeRootview))
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/theme/ThemeOverlayControllerTest.java b/packages/SystemUI/multivalentTests/src/com/android/systemui/theme/ThemeOverlayControllerTest.java
index e7ca1dd..7b52dd8 100644
--- a/packages/SystemUI/multivalentTests/src/com/android/systemui/theme/ThemeOverlayControllerTest.java
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/theme/ThemeOverlayControllerTest.java
@@ -434,13 +434,13 @@
@Test
public void onSettingChanged_honorThemeStyle() {
when(mDeviceProvisionedController.isUserSetup(anyInt())).thenReturn(true);
- List<Style> validStyles = Arrays.asList(Style.EXPRESSIVE, Style.SPRITZ, Style.TONAL_SPOT,
- Style.FRUIT_SALAD, Style.RAINBOW, Style.VIBRANT);
- for (Style style : validStyles) {
+ @Style.Type List<Integer> validStyles = Arrays.asList(Style.EXPRESSIVE, Style.SPRITZ,
+ Style.TONAL_SPOT, Style.FRUIT_SALAD, Style.RAINBOW, Style.VIBRANT);
+ for (@Style.Type int style : validStyles) {
reset(mSecureSettings);
String jsonString = "{\"android.theme.customization.system_palette\":\"A16B00\","
- + "\"android.theme.customization.theme_style\":\"" + style.name() + "\"}";
+ + "\"android.theme.customization.theme_style\":\"" + Style.name(style) + "\"}";
when(mSecureSettings.getStringForUser(
eq(Settings.Secure.THEME_CUSTOMIZATION_OVERLAY_PACKAGES), anyInt()))
diff --git a/packages/SystemUI/res/values/strings.xml b/packages/SystemUI/res/values/strings.xml
index a0a61c7..bc81a4b 100644
--- a/packages/SystemUI/res/values/strings.xml
+++ b/packages/SystemUI/res/values/strings.xml
@@ -1336,10 +1336,12 @@
<string name="communal_widgets_disclaimer_text">To open an app using a widget, you\u2019ll need to verify it\u2019s you. Also, keep in mind that anyone can view them, even when your tablet\u2019s locked. Some widgets may not have been intended for your lock screen and may be unsafe to add here.</string>
<!-- Button for user to verify they understand the information presented. [CHAR LIMIT=50] -->
<string name="communal_widgets_disclaimer_button">Got it</string>
- <!-- Lockscreen affordance to open glanceable hub. [CHAR LIMIT=20] -->
+ <!-- Label for a lock screen affordance to show widgets on the lock screen. [CHAR LIMIT=20] -->
<string name="glanceable_hub_lockscreen_affordance_label">Widgets</string>
- <!-- Text explaining that the glanceable hub affordance is disabled. [CHAR LIMIT=NONE] -->
- <string name="glanceable_hub_lockscreen_affordance_disabled_text">To add Widgets on the lock screen as a shortcut, make sure it is enabled in settings.</string>
+ <!-- Text explaining why the lock screen affordance to show widgets on the lockscreen is disabled and how to enable the affordance in settings. [CHAR LIMIT=NONE] -->
+ <string name="glanceable_hub_lockscreen_affordance_disabled_text">To add the \"Widgets\" shortcut, make sure \"Show widgets on lock screen\" is enabled in settings.</string>
+ <!-- Label for a button used to open Settings in order to enable showing widgets on the lock screen. [CHAR LIMIT=NONE] -->
+ <string name="glanceable_hub_lockscreen_affordance_action_button_label">Settings</string>
<!-- Related to user switcher --><skip/>
diff --git a/packages/SystemUI/schemas/com.android.systemui.communal.data.db.CommunalDatabase/5.json b/packages/SystemUI/schemas/com.android.systemui.communal.data.db.CommunalDatabase/5.json
new file mode 100644
index 0000000..c5a83c4
--- /dev/null
+++ b/packages/SystemUI/schemas/com.android.systemui.communal.data.db.CommunalDatabase/5.json
@@ -0,0 +1,95 @@
+{
+ "formatVersion": 1,
+ "database": {
+ "version": 5,
+ "identityHash": "a83f96ef4babe730b3a00e8acb777a25",
+ "entities": [
+ {
+ "tableName": "communal_widget_table",
+ "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`uid` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `widget_id` INTEGER NOT NULL, `component_name` TEXT NOT NULL, `item_id` INTEGER NOT NULL, `user_serial_number` INTEGER NOT NULL DEFAULT -1, `span_y` INTEGER NOT NULL DEFAULT 3, `span_y_new` INTEGER NOT NULL DEFAULT 1)",
+ "fields": [
+ {
+ "fieldPath": "uid",
+ "columnName": "uid",
+ "affinity": "INTEGER",
+ "notNull": true
+ },
+ {
+ "fieldPath": "widgetId",
+ "columnName": "widget_id",
+ "affinity": "INTEGER",
+ "notNull": true
+ },
+ {
+ "fieldPath": "componentName",
+ "columnName": "component_name",
+ "affinity": "TEXT",
+ "notNull": true
+ },
+ {
+ "fieldPath": "itemId",
+ "columnName": "item_id",
+ "affinity": "INTEGER",
+ "notNull": true
+ },
+ {
+ "fieldPath": "userSerialNumber",
+ "columnName": "user_serial_number",
+ "affinity": "INTEGER",
+ "notNull": true,
+ "defaultValue": "-1"
+ },
+ {
+ "fieldPath": "spanY",
+ "columnName": "span_y",
+ "affinity": "INTEGER",
+ "notNull": true,
+ "defaultValue": "3"
+ },
+ {
+ "fieldPath": "spanYNew",
+ "columnName": "span_y_new",
+ "affinity": "INTEGER",
+ "notNull": true,
+ "defaultValue": "1"
+ }
+ ],
+ "primaryKey": {
+ "autoGenerate": true,
+ "columnNames": [
+ "uid"
+ ]
+ }
+ },
+ {
+ "tableName": "communal_item_rank_table",
+ "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`uid` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `rank` INTEGER NOT NULL DEFAULT 0)",
+ "fields": [
+ {
+ "fieldPath": "uid",
+ "columnName": "uid",
+ "affinity": "INTEGER",
+ "notNull": true
+ },
+ {
+ "fieldPath": "rank",
+ "columnName": "rank",
+ "affinity": "INTEGER",
+ "notNull": true,
+ "defaultValue": "0"
+ }
+ ],
+ "primaryKey": {
+ "autoGenerate": true,
+ "columnNames": [
+ "uid"
+ ]
+ }
+ }
+ ],
+ "setupQueries": [
+ "CREATE TABLE IF NOT EXISTS room_master_table (id INTEGER PRIMARY KEY,identity_hash TEXT)",
+ "INSERT OR REPLACE INTO room_master_table (id,identity_hash) VALUES(42, 'a83f96ef4babe730b3a00e8acb777a25')"
+ ]
+ }
+}
\ No newline at end of file
diff --git a/packages/SystemUI/src/com/android/systemui/communal/data/backup/CommunalBackupUtils.kt b/packages/SystemUI/src/com/android/systemui/communal/data/backup/CommunalBackupUtils.kt
index c3d2683..41ea7b6 100644
--- a/packages/SystemUI/src/com/android/systemui/communal/data/backup/CommunalBackupUtils.kt
+++ b/packages/SystemUI/src/com/android/systemui/communal/data/backup/CommunalBackupUtils.kt
@@ -29,9 +29,7 @@
import kotlinx.coroutines.runBlocking
/** Utilities for communal backup and restore. */
-class CommunalBackupUtils(
- private val context: Context,
-) {
+class CommunalBackupUtils(private val context: Context) {
/**
* Retrieves a communal hub state protobuf that represents the current state of the communal
@@ -50,6 +48,8 @@
widgetId = widget.widgetId
componentName = widget.componentName
userSerialNumber = widget.userSerialNumber
+ spanY = widget.spanY
+ spanYNew = widget.spanYNew
}
)
}
diff --git a/packages/SystemUI/src/com/android/systemui/communal/data/db/CommunalDatabase.kt b/packages/SystemUI/src/com/android/systemui/communal/data/db/CommunalDatabase.kt
index e72088f..679d071 100644
--- a/packages/SystemUI/src/com/android/systemui/communal/data/db/CommunalDatabase.kt
+++ b/packages/SystemUI/src/com/android/systemui/communal/data/db/CommunalDatabase.kt
@@ -26,9 +26,11 @@
import androidx.room.migration.Migration
import androidx.sqlite.db.SupportSQLiteDatabase
import com.android.systemui.communal.shared.model.GlanceableHubMultiUserHelperImpl
+import com.android.systemui.communal.shared.model.SpanValue
+import com.android.systemui.communal.shared.model.toResponsive
import com.android.systemui.res.R
-@Database(entities = [CommunalWidgetItem::class, CommunalItemRank::class], version = 4)
+@Database(entities = [CommunalWidgetItem::class, CommunalItemRank::class], version = 5)
abstract class CommunalDatabase : RoomDatabase() {
abstract fun communalWidgetDao(): CommunalWidgetDao
@@ -59,7 +61,12 @@
context.resources.getString(R.string.config_communalDatabase),
)
.also { builder ->
- builder.addMigrations(MIGRATION_1_2, MIGRATION_2_3, MIGRATION_3_4)
+ builder.addMigrations(
+ MIGRATION_1_2,
+ MIGRATION_2_3,
+ MIGRATION_3_4,
+ MIGRATION_4_5,
+ )
builder.fallbackToDestructiveMigration(dropAllTables = true)
callback?.let { callback -> builder.addCallback(callback) }
}
@@ -123,5 +130,30 @@
)
}
}
+
+ /** This migration adds a new spanY column for responsive grid sizing. */
+ @VisibleForTesting
+ val MIGRATION_4_5 =
+ object : Migration(4, 5) {
+ override fun migrate(db: SupportSQLiteDatabase) {
+ Log.i(TAG, "Migrating from version 4 to 5")
+ db.execSQL(
+ "ALTER TABLE communal_widget_table " +
+ "ADD COLUMN span_y_new INTEGER NOT NULL DEFAULT 1"
+ )
+ db.query("SELECT item_id, span_y FROM communal_widget_table").use { cursor ->
+ while (cursor.moveToNext()) {
+ val id = cursor.getInt(cursor.getColumnIndex("item_id"))
+ val spanYFixed =
+ SpanValue.Fixed(cursor.getInt(cursor.getColumnIndex("span_y")))
+ val spanYResponsive = spanYFixed.toResponsive()
+ db.execSQL(
+ "UPDATE communal_widget_table SET span_y_new = " +
+ "${spanYResponsive.value} WHERE item_id = $id"
+ )
+ }
+ }
+ }
+ }
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/communal/data/db/CommunalEntities.kt b/packages/SystemUI/src/com/android/systemui/communal/data/db/CommunalEntities.kt
index f9d2a84..6ef4bb8 100644
--- a/packages/SystemUI/src/com/android/systemui/communal/data/db/CommunalEntities.kt
+++ b/packages/SystemUI/src/com/android/systemui/communal/data/db/CommunalEntities.kt
@@ -45,7 +45,12 @@
* The vertical span of the widget. Span_Y default value corresponds to
* CommunalContentSize.HALF.span
*/
- @ColumnInfo(name = "span_y", defaultValue = "3") val spanY: Int,
+ @Deprecated("Use spanYNew instead")
+ @ColumnInfo(name = "span_y", defaultValue = "3")
+ val spanY: Int,
+
+ /** The vertical span of the widget in grid cell units. */
+ @ColumnInfo(name = "span_y_new", defaultValue = "1") val spanYNew: Int,
) {
companion object {
/**
diff --git a/packages/SystemUI/src/com/android/systemui/communal/data/db/CommunalWidgetDao.kt b/packages/SystemUI/src/com/android/systemui/communal/data/db/CommunalWidgetDao.kt
index 3d40aa7..3907a37 100644
--- a/packages/SystemUI/src/com/android/systemui/communal/data/db/CommunalWidgetDao.kt
+++ b/packages/SystemUI/src/com/android/systemui/communal/data/db/CommunalWidgetDao.kt
@@ -27,7 +27,9 @@
import androidx.sqlite.db.SupportSQLiteDatabase
import com.android.app.tracing.coroutines.launchTraced as launch
import com.android.systemui.communal.nano.CommunalHubState
-import com.android.systemui.communal.shared.model.CommunalContentSize
+import com.android.systemui.communal.shared.model.SpanValue
+import com.android.systemui.communal.shared.model.toFixed
+import com.android.systemui.communal.shared.model.toResponsive
import com.android.systemui.communal.widgets.CommunalWidgetHost
import com.android.systemui.communal.widgets.CommunalWidgetModule.Companion.DEFAULT_WIDGETS
import com.android.systemui.dagger.SysUISingleton
@@ -101,6 +103,7 @@
componentName = name,
rank = index,
userSerialNumber = userSerialNumber,
+ spanY = SpanValue.Fixed(3),
)
}
}
@@ -155,15 +158,16 @@
@Query(
"INSERT INTO communal_widget_table" +
- "(widget_id, component_name, item_id, user_serial_number, span_y) " +
- "VALUES(:widgetId, :componentName, :itemId, :userSerialNumber, :spanY)"
+ "(widget_id, component_name, item_id, user_serial_number, span_y, span_y_new) " +
+ "VALUES(:widgetId, :componentName, :itemId, :userSerialNumber, :spanY, :spanYNew)"
)
fun insertWidget(
widgetId: Int,
componentName: String,
itemId: Long,
userSerialNumber: Int,
- spanY: Int = 3,
+ spanY: Int,
+ spanYNew: Int,
): Long
@Query("INSERT INTO communal_item_rank_table(rank) VALUES(:rank)")
@@ -189,10 +193,12 @@
}
@Transaction
- fun resizeWidget(appWidgetId: Int, spanY: Int, widgetIdToRankMap: Map<Int, Int>) {
+ fun resizeWidget(appWidgetId: Int, spanY: SpanValue, widgetIdToRankMap: Map<Int, Int>) {
val widget = getWidgetByIdNow(appWidgetId)
if (widget != null) {
- updateWidget(widget.copy(spanY = spanY))
+ updateWidget(
+ widget.copy(spanY = spanY.toFixed().value, spanYNew = spanY.toResponsive().value)
+ )
}
updateWidgetOrder(widgetIdToRankMap)
}
@@ -203,7 +209,7 @@
provider: ComponentName,
rank: Int? = null,
userSerialNumber: Int,
- spanY: Int = CommunalContentSize.HALF.span,
+ spanY: SpanValue,
): Long {
return addWidget(
widgetId = widgetId,
@@ -220,7 +226,7 @@
componentName: String,
rank: Int? = null,
userSerialNumber: Int,
- spanY: Int = 3,
+ spanY: SpanValue,
): Long {
val widgets = getWidgetsNow()
@@ -241,7 +247,8 @@
componentName = componentName,
itemId = insertItemRank(newRank),
userSerialNumber = userSerialNumber,
- spanY = spanY,
+ spanY = spanY.toFixed().value,
+ spanYNew = spanY.toResponsive().value,
)
}
@@ -264,7 +271,11 @@
clearCommunalItemRankTable()
state.widgets.forEach {
- val spanY = if (it.spanY != 0) it.spanY else CommunalContentSize.HALF.span
+ // Check if there is a new value to restore. If so, restore that new value.
+ val spanYResponsive = if (it.spanYNew != 0) SpanValue.Responsive(it.spanYNew) else null
+ // If no new value, restore any existing old values.
+ val spanY = spanYResponsive ?: SpanValue.Fixed(it.spanY.coerceIn(3, 6))
+
addWidget(it.widgetId, it.componentName, it.rank, it.userSerialNumber, spanY)
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/communal/data/repository/CommunalWidgetRepository.kt b/packages/SystemUI/src/com/android/systemui/communal/data/repository/CommunalWidgetRepository.kt
index 29569f8..e44d78b 100644
--- a/packages/SystemUI/src/com/android/systemui/communal/data/repository/CommunalWidgetRepository.kt
+++ b/packages/SystemUI/src/com/android/systemui/communal/data/repository/CommunalWidgetRepository.kt
@@ -22,6 +22,7 @@
import android.os.UserHandle
import android.os.UserManager
import com.android.app.tracing.coroutines.launchTraced as launch
+import com.android.systemui.Flags.communalResponsiveGrid
import com.android.systemui.Flags.communalWidgetResizing
import com.android.systemui.common.data.repository.PackageChangeRepository
import com.android.systemui.common.shared.model.PackageInstallSession
@@ -33,6 +34,7 @@
import com.android.systemui.communal.nano.CommunalHubState
import com.android.systemui.communal.proto.toCommunalHubState
import com.android.systemui.communal.shared.model.CommunalWidgetContentModel
+import com.android.systemui.communal.shared.model.SpanValue
import com.android.systemui.communal.widgets.CommunalAppWidgetHost
import com.android.systemui.communal.widgets.CommunalWidgetHost
import com.android.systemui.communal.widgets.WidgetConfigurator
@@ -143,15 +145,21 @@
componentName = widget.componentName,
rank = rank.rank,
providerInfo = providers[widget.widgetId],
- spanY = widget.spanY,
+ spanY = if (communalResponsiveGrid()) widget.spanYNew else widget.spanY,
)
}
}
override fun resizeWidget(appWidgetId: Int, spanY: Int, widgetIdToRankMap: Map<Int, Int>) {
if (!communalWidgetResizing()) return
+ val spanValue =
+ if (communalResponsiveGrid()) {
+ SpanValue.Responsive(spanY)
+ } else {
+ SpanValue.Fixed(spanY)
+ }
bgScope.launch {
- communalWidgetDao.resizeWidget(appWidgetId, spanY, widgetIdToRankMap)
+ communalWidgetDao.resizeWidget(appWidgetId, spanValue, widgetIdToRankMap)
logger.i({ "Updated spanY of widget $int1 to $int2." }) {
int1 = appWidgetId
int2 = spanY
@@ -225,7 +233,7 @@
provider = provider,
rank = rank,
userSerialNumber = userManager.getUserSerialNumber(user.identifier),
- spanY = 3,
+ spanY = SpanValue.Fixed(3),
)
backupManager.dataChanged()
} else {
diff --git a/packages/SystemUI/src/com/android/systemui/communal/domain/interactor/CommunalInteractor.kt b/packages/SystemUI/src/com/android/systemui/communal/domain/interactor/CommunalInteractor.kt
index 602fe30..f9b30c6 100644
--- a/packages/SystemUI/src/com/android/systemui/communal/domain/interactor/CommunalInteractor.kt
+++ b/packages/SystemUI/src/com/android/systemui/communal/domain/interactor/CommunalInteractor.kt
@@ -34,9 +34,9 @@
import com.android.systemui.communal.domain.model.CommunalContentModel
import com.android.systemui.communal.domain.model.CommunalContentModel.WidgetContent
import com.android.systemui.communal.shared.model.CommunalContentSize
-import com.android.systemui.communal.shared.model.CommunalContentSize.FULL
-import com.android.systemui.communal.shared.model.CommunalContentSize.HALF
-import com.android.systemui.communal.shared.model.CommunalContentSize.THIRD
+import com.android.systemui.communal.shared.model.CommunalContentSize.FixedSize.FULL
+import com.android.systemui.communal.shared.model.CommunalContentSize.FixedSize.HALF
+import com.android.systemui.communal.shared.model.CommunalContentSize.FixedSize.THIRD
import com.android.systemui.communal.shared.model.CommunalScenes
import com.android.systemui.communal.shared.model.CommunalWidgetContentModel
import com.android.systemui.communal.shared.model.EditModeState
diff --git a/packages/SystemUI/src/com/android/systemui/communal/domain/model/CommunalContentModel.kt b/packages/SystemUI/src/com/android/systemui/communal/domain/model/CommunalContentModel.kt
index 30f580e..da613f5 100644
--- a/packages/SystemUI/src/com/android/systemui/communal/domain/model/CommunalContentModel.kt
+++ b/packages/SystemUI/src/com/android/systemui/communal/domain/model/CommunalContentModel.kt
@@ -22,6 +22,7 @@
import android.content.pm.ApplicationInfo
import android.graphics.Bitmap
import android.widget.RemoteViews
+import com.android.systemui.Flags.communalResponsiveGrid
import com.android.systemui.communal.shared.model.CommunalContentSize
import java.util.UUID
@@ -35,7 +36,7 @@
/** The minimum size content can be resized to. */
val minSize: CommunalContentSize
- get() = CommunalContentSize.HALF
+ get() = fixedHalfOrResponsiveSize()
/**
* A type of communal content is ongoing / live / ephemeral, and can be sized and ordered
@@ -44,7 +45,12 @@
sealed interface Ongoing : CommunalContentModel {
override var size: CommunalContentSize
override val minSize
- get() = CommunalContentSize.THIRD
+ get() =
+ if (communalResponsiveGrid()) {
+ CommunalContentSize.Responsive(1)
+ } else {
+ CommunalContentSize.FixedSize.THIRD
+ }
/** Timestamp in milliseconds of when the content was created. */
val createdTimestampMillis: Long
@@ -100,14 +106,16 @@
class WidgetPlaceholder : CommunalContentModel {
override val key: String = KEY.widgetPlaceholder()
// Same as widget size.
- override val size = CommunalContentSize.HALF
+ override val size: CommunalContentSize
+ get() = fixedHalfOrResponsiveSize()
}
/** A CTA tile in the glanceable hub view mode which can be dismissed. */
class CtaTileInViewMode : CommunalContentModel {
override val key: String = KEY.CTA_TILE_IN_VIEW_MODE_KEY
// Same as widget size.
- override val size = CommunalContentSize.HALF
+ override val size: CommunalContentSize
+ get() = fixedHalfOrResponsiveSize()
}
class Tutorial(id: Int, override var size: CommunalContentSize) : CommunalContentModel {
@@ -118,15 +126,15 @@
smartspaceTargetId: String,
val remoteViews: RemoteViews,
override val createdTimestampMillis: Long,
- override var size: CommunalContentSize = CommunalContentSize.HALF,
+ override var size: CommunalContentSize = fixedHalfOrResponsiveSize(),
) : Ongoing {
override val key = KEY.smartspace(smartspaceTargetId)
}
class Umo(
override val createdTimestampMillis: Long,
- override var size: CommunalContentSize = CommunalContentSize.HALF,
- override var minSize: CommunalContentSize = CommunalContentSize.HALF,
+ override var size: CommunalContentSize = fixedHalfOrResponsiveSize(),
+ override var minSize: CommunalContentSize = fixedHalfOrResponsiveSize(),
) : Ongoing {
override val key = KEY.umo()
}
@@ -170,3 +178,10 @@
fun isLiveContent() = this is Smartspace || this is Umo
}
+
+private fun fixedHalfOrResponsiveSize() =
+ if (communalResponsiveGrid()) {
+ CommunalContentSize.Responsive(1)
+ } else {
+ CommunalContentSize.FixedSize.HALF
+ }
diff --git a/packages/SystemUI/src/com/android/systemui/communal/proto/communal_hub_state.proto b/packages/SystemUI/src/com/android/systemui/communal/proto/communal_hub_state.proto
index 7602a7a..04717d0 100644
--- a/packages/SystemUI/src/com/android/systemui/communal/proto/communal_hub_state.proto
+++ b/packages/SystemUI/src/com/android/systemui/communal/proto/communal_hub_state.proto
@@ -39,7 +39,10 @@
// Serial number of the user associated with the widget.
int32 user_serial_number = 4;
- // The vertical span of the widget
+ // The vertical span of the widget, replaced by span_y_new.
int32 span_y = 5;
+
+ // The vertical span of the widget.
+ int32 span_y_new = 6;
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/communal/shared/model/CommunalContentSize.kt b/packages/SystemUI/src/com/android/systemui/communal/shared/model/CommunalContentSize.kt
index cf80b7d..df30716 100644
--- a/packages/SystemUI/src/com/android/systemui/communal/shared/model/CommunalContentSize.kt
+++ b/packages/SystemUI/src/com/android/systemui/communal/shared/model/CommunalContentSize.kt
@@ -16,27 +16,39 @@
package com.android.systemui.communal.shared.model
+import com.android.systemui.Flags.communalResponsiveGrid
+
/**
* Supported sizes for communal content in the layout grid.
*
- * @param span The span of the content in a column. For example, if FULL is 6, then 3 represents
- * HALF, 2 represents THIRD, and 1 represents SIXTH.
+ * @property span The span of the content in a column.
*/
-enum class CommunalContentSize(val span: Int) {
- /** Content takes the full height of the column. */
- FULL(6),
+sealed interface CommunalContentSize {
+ val span: Int
- /** Content takes half of the height of the column. */
- HALF(3),
+ @Deprecated("Use Responsive size instead")
+ enum class FixedSize(override val span: Int) : CommunalContentSize {
+ /** Content takes the full height of the column. */
+ FULL(6),
- /** Content takes a third of the height of the column. */
- THIRD(2);
+ /** Content takes half of the height of the column. */
+ HALF(3),
+
+ /** Content takes a third of the height of the column. */
+ THIRD(2),
+ }
+
+ @JvmInline value class Responsive(override val span: Int) : CommunalContentSize
companion object {
/** Converts from span to communal content size. */
fun toSize(span: Int): CommunalContentSize {
- return entries.find { it.span == span }
- ?: throw IllegalArgumentException("$span is not a valid span size")
+ return if (communalResponsiveGrid()) {
+ Responsive(span)
+ } else {
+ FixedSize.entries.find { it.span == span }
+ ?: throw IllegalArgumentException("$span is not a valid span size")
+ }
}
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/communal/shared/model/SpanValue.kt b/packages/SystemUI/src/com/android/systemui/communal/shared/model/SpanValue.kt
new file mode 100644
index 0000000..15cc6b0
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/communal/shared/model/SpanValue.kt
@@ -0,0 +1,40 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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.communal.shared.model
+
+/** Models possible span values for different grid formats. */
+sealed interface SpanValue {
+ val value: Int
+
+ @Deprecated("Use Responsive sizes instead")
+ @JvmInline
+ value class Fixed(override val value: Int) : SpanValue
+
+ @JvmInline value class Responsive(override val value: Int) : SpanValue
+}
+
+fun SpanValue.toResponsive(): SpanValue.Responsive =
+ when (this) {
+ is SpanValue.Responsive -> this
+ is SpanValue.Fixed -> SpanValue.Responsive((this.value / 3).coerceAtMost(1))
+ }
+
+fun SpanValue.toFixed(): SpanValue.Fixed =
+ when (this) {
+ is SpanValue.Fixed -> this
+ is SpanValue.Responsive -> SpanValue.Fixed((this.value * 3).coerceIn(3, 6))
+ }
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/data/quickaffordance/GlanceableHubQuickAffordanceConfig.kt b/packages/SystemUI/src/com/android/systemui/keyguard/data/quickaffordance/GlanceableHubQuickAffordanceConfig.kt
index 8906156..71f29c0 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/data/quickaffordance/GlanceableHubQuickAffordanceConfig.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/data/quickaffordance/GlanceableHubQuickAffordanceConfig.kt
@@ -17,6 +17,8 @@
package com.android.systemui.keyguard.data.quickaffordance
import android.content.Context
+import android.content.Intent
+import android.provider.Settings
import android.util.Log
import com.android.systemui.Flags.glanceableHubShortcutButton
import com.android.systemui.animation.Expandable
@@ -86,7 +88,13 @@
} else if (!communalInteractor.isCommunalEnabled.value) {
Log.i(TAG, "Button disabled in picker: hub not enabled in settings.")
KeyguardQuickAffordanceConfig.PickerScreenState.Disabled(
- context.getString(R.string.glanceable_hub_lockscreen_affordance_disabled_text)
+ explanation =
+ context.getString(R.string.glanceable_hub_lockscreen_affordance_disabled_text),
+ actionText =
+ context.getString(
+ R.string.glanceable_hub_lockscreen_affordance_action_button_label
+ ),
+ actionIntent = Intent(Settings.ACTION_LOCKSCREEN_SETTINGS),
)
} else {
KeyguardQuickAffordanceConfig.PickerScreenState.Default()
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/ui/preview/KeyguardPreviewRenderer.kt b/packages/SystemUI/src/com/android/systemui/keyguard/ui/preview/KeyguardPreviewRenderer.kt
index 494de9a..7d77e71 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/ui/preview/KeyguardPreviewRenderer.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/ui/preview/KeyguardPreviewRenderer.kt
@@ -188,7 +188,8 @@
private val shortcutsBindings = mutableSetOf<KeyguardQuickAffordanceViewBinder.Binding>()
private val coroutineScope: CoroutineScope
- private var themeStyle: Style? = null
+
+ @Style.Type private var themeStyle: Int? = null
init {
coroutineScope =
@@ -660,6 +661,7 @@
// Seed color null means users do not override any color on the clock. The default
// color will need to use wallpaper's extracted color and consider if the
// wallpaper's color is dark or light.
+ @Style.Type
val style = themeStyle ?: fetchThemeStyleFromSetting().also { themeStyle = it }
val wallpaperColorScheme = ColorScheme(colors, false, style)
val lightClockColor = wallpaperColorScheme.accent1.s100
@@ -712,7 +714,8 @@
}
}
- private suspend fun fetchThemeStyleFromSetting(): Style {
+ @Style.Type
+ private suspend fun fetchThemeStyleFromSetting(): Int {
val overlayPackageJson =
withContext(backgroundDispatcher) {
secureSettings.getString(Settings.Secure.THEME_CUSTOMIZATION_OVERLAY_PACKAGES)
diff --git a/packages/SystemUI/src/com/android/systemui/media/controls/ui/util/MediaArtworkHelper.kt b/packages/SystemUI/src/com/android/systemui/media/controls/ui/util/MediaArtworkHelper.kt
index c21513b..14a4e26 100644
--- a/packages/SystemUI/src/com/android/systemui/media/controls/ui/util/MediaArtworkHelper.kt
+++ b/packages/SystemUI/src/com/android/systemui/media/controls/ui/util/MediaArtworkHelper.kt
@@ -98,7 +98,11 @@
}
/** Returns [ColorScheme] of media app given its [icon]. */
- fun getColorScheme(icon: Drawable, tag: String, style: Style = Style.TONAL_SPOT): ColorScheme? {
+ fun getColorScheme(
+ icon: Drawable,
+ tag: String,
+ @Style.Type style: Int = Style.TONAL_SPOT,
+ ): ColorScheme? {
return try {
ColorScheme(WallpaperColors.fromDrawable(icon), true, style)
} catch (e: PackageManager.NameNotFoundException) {
diff --git a/packages/SystemUI/src/com/android/systemui/qs/FgsManagerController.kt b/packages/SystemUI/src/com/android/systemui/qs/FgsManagerController.kt
index 2a5ffc6..5c9baa0 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/FgsManagerController.kt
+++ b/packages/SystemUI/src/com/android/systemui/qs/FgsManagerController.kt
@@ -55,8 +55,7 @@
import com.android.internal.config.sysui.SystemUiDeviceConfigFlags.TASK_MANAGER_SHOW_USER_VISIBLE_JOBS
import com.android.internal.jank.InteractionJankMonitor
import com.android.systemui.Dumpable
-import com.android.systemui.Flags;
-import com.android.systemui.res.R
+import com.android.systemui.Flags
import com.android.systemui.animation.DialogCuj
import com.android.systemui.animation.DialogTransitionAnimator
import com.android.systemui.animation.Expandable
@@ -65,7 +64,9 @@
import com.android.systemui.dagger.qualifiers.Background
import com.android.systemui.dagger.qualifiers.Main
import com.android.systemui.dump.DumpManager
+import com.android.systemui.res.R
import com.android.systemui.settings.UserTracker
+import com.android.systemui.shade.ShadeDisplayAware
import com.android.systemui.shared.system.SysUiStatsLog
import com.android.systemui.statusbar.phone.SystemUIDialog
import com.android.systemui.util.DeviceConfigProxy
@@ -106,8 +107,8 @@
fun init()
/**
- * Show the foreground services dialog. The dialog will be expanded from [expandable] if
- * it's not `null`.
+ * Show the foreground services dialog. The dialog will be expanded from [expandable] if it's
+ * not `null`.
*/
fun showDialog(expandable: Expandable?)
@@ -123,8 +124,7 @@
/** Remove a [OnDialogDismissedListener]. */
fun removeOnDialogDismissedListener(listener: OnDialogDismissedListener)
- @VisibleForTesting
- fun visibleButtonsCount(): Int
+ @VisibleForTesting fun visibleButtonsCount(): Int
interface OnNumberOfPackagesChangedListener {
/** Called when [numRunningPackages] changed. */
@@ -138,8 +138,10 @@
}
@SysUISingleton
-class FgsManagerControllerImpl @Inject constructor(
- @Main private val resources: Resources,
+class FgsManagerControllerImpl
+@Inject
+constructor(
+ @ShadeDisplayAware private val resources: Resources,
@Main private val mainExecutor: Executor,
@Background private val backgroundExecutor: Executor,
private val systemClock: SystemClock,
@@ -187,50 +189,46 @@
private val lock = Any()
- @GuardedBy("lock")
- var initialized = false
+ @GuardedBy("lock") var initialized = false
- @GuardedBy("lock")
- private var lastNumberOfVisiblePackages = 0
+ @GuardedBy("lock") private var lastNumberOfVisiblePackages = 0
- @GuardedBy("lock")
- private var currentProfileIds = mutableSetOf<Int>()
+ @GuardedBy("lock") private var currentProfileIds = mutableSetOf<Int>()
@GuardedBy("lock")
private val runningTaskIdentifiers = mutableMapOf<UserPackage, StartTimeAndIdentifiers>()
- @GuardedBy("lock")
- private var dialog: SystemUIDialog? = null
+ @GuardedBy("lock") private var dialog: SystemUIDialog? = null
- @GuardedBy("lock")
- private val appListAdapter: AppListAdapter = AppListAdapter()
+ @GuardedBy("lock") private val appListAdapter: AppListAdapter = AppListAdapter()
/* Only mutate on the background thread */
private var runningApps: ArrayMap<UserPackage, RunningApp> = ArrayMap()
- private val userTrackerCallback = object : UserTracker.Callback {
- override fun onUserChanged(newUser: Int, userContext: Context) {}
+ private val userTrackerCallback =
+ object : UserTracker.Callback {
+ override fun onUserChanged(newUser: Int, userContext: Context) {}
- override fun onProfilesChanged(profiles: List<UserInfo>) {
- synchronized(lock) {
- currentProfileIds.clear()
- currentProfileIds.addAll(profiles.map { it.id })
- lastNumberOfVisiblePackages = 0
- updateNumberOfVisibleRunningPackagesLocked()
+ override fun onProfilesChanged(profiles: List<UserInfo>) {
+ synchronized(lock) {
+ currentProfileIds.clear()
+ currentProfileIds.addAll(profiles.map { it.id })
+ lastNumberOfVisiblePackages = 0
+ updateNumberOfVisibleRunningPackagesLocked()
+ }
}
}
- }
private val foregroundServiceObserver = ForegroundServiceObserver()
private val userVisibleJobObserver = UserVisibleJobObserver()
- private val stoppableApps by lazy { resources
- .getStringArray(com.android.internal.R.array.stoppable_fgs_system_apps)
+ private val stoppableApps by lazy {
+ resources.getStringArray(com.android.internal.R.array.stoppable_fgs_system_apps)
}
- private val vendorStoppableApps by lazy { resources
- .getStringArray(com.android.internal.R.array.vendor_stoppable_fgs_system_apps)
+ private val vendorStoppableApps by lazy {
+ resources.getStringArray(com.android.internal.R.array.vendor_stoppable_fgs_system_apps)
}
override fun init() {
@@ -239,14 +237,19 @@
return
}
- showUserVisibleJobs = deviceConfigProxy.getBoolean(
- NAMESPACE_SYSTEMUI,
- TASK_MANAGER_SHOW_USER_VISIBLE_JOBS, DEFAULT_TASK_MANAGER_SHOW_USER_VISIBLE_JOBS)
+ showUserVisibleJobs =
+ deviceConfigProxy.getBoolean(
+ NAMESPACE_SYSTEMUI,
+ TASK_MANAGER_SHOW_USER_VISIBLE_JOBS,
+ DEFAULT_TASK_MANAGER_SHOW_USER_VISIBLE_JOBS,
+ )
- informJobSchedulerOfPendingAppStop = deviceConfigProxy.getBoolean(
- NAMESPACE_SYSTEMUI,
- TASK_MANAGER_INFORM_JOB_SCHEDULER_OF_PENDING_APP_STOP,
- DEFAULT_TASK_MANAGER_INFORM_JOB_SCHEDULER_OF_PENDING_APP_STOP)
+ informJobSchedulerOfPendingAppStop =
+ deviceConfigProxy.getBoolean(
+ NAMESPACE_SYSTEMUI,
+ TASK_MANAGER_INFORM_JOB_SCHEDULER_OF_PENDING_APP_STOP,
+ DEFAULT_TASK_MANAGER_INFORM_JOB_SCHEDULER_OF_PENDING_APP_STOP,
+ )
try {
activityManager.registerForegroundServiceObserver(foregroundServiceObserver)
@@ -267,31 +270,39 @@
deviceConfigProxy.addOnPropertiesChangedListener(
NAMESPACE_SYSTEMUI,
- backgroundExecutor
+ backgroundExecutor,
) {
_showFooterDot.value =
it.getBoolean(TASK_MANAGER_SHOW_FOOTER_DOT, _showFooterDot.value)
- showStopBtnForUserAllowlistedApps = it.getBoolean(
- TASK_MANAGER_SHOW_STOP_BUTTON_FOR_USER_ALLOWLISTED_APPS,
- showStopBtnForUserAllowlistedApps)
+ showStopBtnForUserAllowlistedApps =
+ it.getBoolean(
+ TASK_MANAGER_SHOW_STOP_BUTTON_FOR_USER_ALLOWLISTED_APPS,
+ showStopBtnForUserAllowlistedApps,
+ )
var wasShowingUserVisibleJobs = showUserVisibleJobs
- showUserVisibleJobs = it.getBoolean(
- TASK_MANAGER_SHOW_USER_VISIBLE_JOBS, showUserVisibleJobs)
+ showUserVisibleJobs =
+ it.getBoolean(TASK_MANAGER_SHOW_USER_VISIBLE_JOBS, showUserVisibleJobs)
if (showUserVisibleJobs != wasShowingUserVisibleJobs) {
onShowUserVisibleJobsFlagChanged()
}
- informJobSchedulerOfPendingAppStop = it.getBoolean(
- TASK_MANAGER_SHOW_STOP_BUTTON_FOR_USER_ALLOWLISTED_APPS,
- informJobSchedulerOfPendingAppStop)
+ informJobSchedulerOfPendingAppStop =
+ it.getBoolean(
+ TASK_MANAGER_SHOW_STOP_BUTTON_FOR_USER_ALLOWLISTED_APPS,
+ informJobSchedulerOfPendingAppStop,
+ )
}
- _showFooterDot.value = deviceConfigProxy.getBoolean(
- NAMESPACE_SYSTEMUI,
- TASK_MANAGER_SHOW_FOOTER_DOT, DEFAULT_TASK_MANAGER_SHOW_FOOTER_DOT
- )
- showStopBtnForUserAllowlistedApps = deviceConfigProxy.getBoolean(
- NAMESPACE_SYSTEMUI,
- TASK_MANAGER_SHOW_STOP_BUTTON_FOR_USER_ALLOWLISTED_APPS,
- DEFAULT_TASK_MANAGER_SHOW_STOP_BUTTON_FOR_USER_ALLOWLISTED_APPS)
+ _showFooterDot.value =
+ deviceConfigProxy.getBoolean(
+ NAMESPACE_SYSTEMUI,
+ TASK_MANAGER_SHOW_FOOTER_DOT,
+ DEFAULT_TASK_MANAGER_SHOW_FOOTER_DOT,
+ )
+ showStopBtnForUserAllowlistedApps =
+ deviceConfigProxy.getBoolean(
+ NAMESPACE_SYSTEMUI,
+ TASK_MANAGER_SHOW_STOP_BUTTON_FOR_USER_ALLOWLISTED_APPS,
+ DEFAULT_TASK_MANAGER_SHOW_STOP_BUTTON_FOR_USER_ALLOWLISTED_APPS,
+ )
dumpManager.registerDumpable(this)
@@ -305,7 +316,7 @@
},
IntentFilter(Intent.ACTION_SHOW_FOREGROUND_SERVICE_MANAGER),
executor = mainExecutor,
- flags = Context.RECEIVER_NOT_EXPORTED
+ flags = Context.RECEIVER_NOT_EXPORTED,
)
initialized = true
@@ -323,33 +334,25 @@
override fun addOnNumberOfPackagesChangedListener(
listener: FgsManagerController.OnNumberOfPackagesChangedListener
) {
- synchronized(lock) {
- onNumberOfPackagesChangedListeners.add(listener)
- }
+ synchronized(lock) { onNumberOfPackagesChangedListeners.add(listener) }
}
override fun removeOnNumberOfPackagesChangedListener(
listener: FgsManagerController.OnNumberOfPackagesChangedListener
) {
- synchronized(lock) {
- onNumberOfPackagesChangedListeners.remove(listener)
- }
+ synchronized(lock) { onNumberOfPackagesChangedListeners.remove(listener) }
}
override fun addOnDialogDismissedListener(
listener: FgsManagerController.OnDialogDismissedListener
) {
- synchronized(lock) {
- onDialogDismissedListeners.add(listener)
- }
+ synchronized(lock) { onDialogDismissedListeners.add(listener) }
}
override fun removeOnDialogDismissedListener(
listener: FgsManagerController.OnDialogDismissedListener
) {
- synchronized(lock) {
- onDialogDismissedListeners.remove(listener)
- }
+ synchronized(lock) { onDialogDismissedListeners.remove(listener) }
}
private fun getNumVisiblePackagesLocked(): Int {
@@ -364,9 +367,7 @@
lastNumberOfVisiblePackages = num
newChangesSinceDialogWasDismissed = true
onNumberOfPackagesChangedListeners.forEach {
- backgroundExecutor.execute {
- it.onNumberOfPackagesChanged(num)
- }
+ backgroundExecutor.execute { it.onNumberOfPackagesChanged(num) }
}
}
}
@@ -396,8 +397,10 @@
recyclerView.layoutManager = LinearLayoutManager(dialogContext)
recyclerView.adapter = appListAdapter
- val topSpacing = dialogContext.resources
- .getDimensionPixelSize(R.dimen.fgs_manager_list_top_spacing)
+ val topSpacing =
+ dialogContext.resources.getDimensionPixelSize(
+ R.dimen.fgs_manager_list_top_spacing
+ )
dialog.setView(recyclerView, 0, topSpacing, 0, 0)
this.dialog = dialog
@@ -436,9 +439,7 @@
@GuardedBy("lock")
private fun updateAppItemsLocked(refreshUiControls: Boolean = false) {
if (dialog == null) {
- backgroundExecutor.execute {
- clearRunningApps()
- }
+ backgroundExecutor.execute { clearRunningApps() }
return
}
@@ -449,59 +450,61 @@
}
}
- /**
- * Must be called on the background thread.
- */
+ /** Must be called on the background thread. */
@WorkerThread
private fun updateAppItems(
packages: Map<UserPackage, Long>,
profileIds: Set<Int>,
- refreshUiControls: Boolean = true
+ refreshUiControls: Boolean = true,
) {
if (refreshUiControls) {
- packages.forEach { (pkg, _) ->
- pkg.updateUiControl()
- }
+ packages.forEach { (pkg, _) -> pkg.updateUiControl() }
}
- val addedPackages = packages.keys.filter {
- profileIds.contains(it.userId) &&
- it.uiControl != UIControl.HIDE_ENTRY && runningApps[it]?.stopped != true
- }
+ val addedPackages =
+ packages.keys.filter {
+ profileIds.contains(it.userId) &&
+ it.uiControl != UIControl.HIDE_ENTRY &&
+ runningApps[it]?.stopped != true
+ }
val removedPackages = runningApps.keys.filter { it !in packages }
addedPackages.forEach {
val ai = packageManager.getApplicationInfoAsUser(it.packageName, 0, it.userId)
- runningApps[it] = RunningApp(
- it.userId, it.packageName,
- packages[it]!!, it.uiControl,
- packageManager.getApplicationLabel(ai),
- packageManager.getUserBadgedIcon(
- packageManager.getApplicationIcon(ai), UserHandle.of(it.userId)
+ runningApps[it] =
+ RunningApp(
+ it.userId,
+ it.packageName,
+ packages[it]!!,
+ it.uiControl,
+ packageManager.getApplicationLabel(ai),
+ packageManager.getUserBadgedIcon(
+ packageManager.getApplicationIcon(ai),
+ UserHandle.of(it.userId),
+ ),
)
- )
logEvent(stopped = false, it.packageName, it.userId, runningApps[it]!!.timeStarted)
}
removedPackages.forEach { pkg ->
val ra = runningApps[pkg]!!
- val ra2 = ra.copy().also {
- it.stopped = true
- it.appLabel = ra.appLabel
- it.icon = ra.icon
- }
+ val ra2 =
+ ra.copy().also {
+ it.stopped = true
+ it.appLabel = ra.appLabel
+ it.icon = ra.icon
+ }
runningApps[pkg] = ra2
}
mainExecutor.execute {
- appListAdapter
- .setData(runningApps.values.toList().sortedByDescending { it.timeStarted })
+ appListAdapter.setData(
+ runningApps.values.toList().sortedByDescending { it.timeStarted }
+ )
}
}
- /**
- * Must be called on the background thread.
- */
+ /** Must be called on the background thread. */
@WorkerThread
private fun clearRunningApps() {
runningApps.clear()
@@ -545,16 +548,19 @@
private fun logEvent(stopped: Boolean, packageName: String, userId: Int, timeStarted: Long) {
val timeLogged = systemClock.elapsedRealtime()
- val event = if (stopped) {
- SysUiStatsLog.TASK_MANAGER_EVENT_REPORTED__EVENT__STOPPED
- } else {
- SysUiStatsLog.TASK_MANAGER_EVENT_REPORTED__EVENT__VIEWED
- }
+ val event =
+ if (stopped) {
+ SysUiStatsLog.TASK_MANAGER_EVENT_REPORTED__EVENT__STOPPED
+ } else {
+ SysUiStatsLog.TASK_MANAGER_EVENT_REPORTED__EVENT__VIEWED
+ }
backgroundExecutor.execute {
val uid = packageManager.getPackageUidAsUser(packageName, userId)
SysUiStatsLog.write(
- SysUiStatsLog.TASK_MANAGER_EVENT_REPORTED, uid, event,
- timeLogged - timeStarted
+ SysUiStatsLog.TASK_MANAGER_EVENT_REPORTED,
+ uid,
+ event,
+ timeLogged - timeStarted,
)
}
}
@@ -562,8 +568,7 @@
private inner class AppListAdapter : RecyclerView.Adapter<AppItemViewHolder>() {
private val lock = Any()
- @GuardedBy("lock")
- private var data: List<RunningApp> = listOf()
+ @GuardedBy("lock") private var data: List<RunningApp> = listOf()
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): AppItemViewHolder {
return AppItemViewHolder(
@@ -574,16 +579,15 @@
override fun onBindViewHolder(holder: AppItemViewHolder, position: Int) {
var runningApp: RunningApp
- synchronized(lock) {
- runningApp = data[position]
- }
+ synchronized(lock) { runningApp = data[position] }
with(holder) {
iconView.setImageDrawable(runningApp.icon)
appLabelView.text = runningApp.appLabel
- durationView.text = DateUtils.formatDuration(
- max(systemClock.elapsedRealtime() - runningApp.timeStarted, 60000),
- DateUtils.LENGTH_MEDIUM
- )
+ durationView.text =
+ DateUtils.formatDuration(
+ max(systemClock.elapsedRealtime() - runningApp.timeStarted, 60000),
+ DateUtils.LENGTH_MEDIUM,
+ )
stopButton.setOnClickListener {
stopButton.setText(R.string.fgs_manager_app_item_stop_button_stopped_label)
stopPackage(runningApp.userId, runningApp.packageName, runningApp.timeStarted)
@@ -611,46 +615,54 @@
var oldData = data
data = newData
- DiffUtil.calculateDiff(object : DiffUtil.Callback() {
- override fun getOldListSize(): Int {
- return oldData.size
- }
+ DiffUtil.calculateDiff(
+ object : DiffUtil.Callback() {
+ override fun getOldListSize(): Int {
+ return oldData.size
+ }
- override fun getNewListSize(): Int {
- return newData.size
- }
+ override fun getNewListSize(): Int {
+ return newData.size
+ }
- override fun areItemsTheSame(oldItemPosition: Int, newItemPosition: Int): Boolean {
- return oldData[oldItemPosition] == newData[newItemPosition]
- }
+ override fun areItemsTheSame(
+ oldItemPosition: Int,
+ newItemPosition: Int,
+ ): Boolean {
+ return oldData[oldItemPosition] == newData[newItemPosition]
+ }
- override fun areContentsTheSame(
- oldItemPosition: Int,
- newItemPosition: Int
- ): Boolean {
- return oldData[oldItemPosition].stopped == newData[newItemPosition].stopped
- }
- }).dispatchUpdatesTo(this)
+ override fun areContentsTheSame(
+ oldItemPosition: Int,
+ newItemPosition: Int,
+ ): Boolean {
+ return oldData[oldItemPosition].stopped ==
+ newData[newItemPosition].stopped
+ }
+ }
+ )
+ .dispatchUpdatesTo(this)
}
}
private inner class ForegroundServiceObserver : IForegroundServiceObserver.Stub() {
override fun onForegroundStateChanged(
- token: IBinder,
- packageName: String,
- userId: Int,
- isForeground: Boolean
+ token: IBinder,
+ packageName: String,
+ userId: Int,
+ isForeground: Boolean,
) {
synchronized(lock) {
val userPackageKey = UserPackage(userId, packageName)
if (isForeground) {
runningTaskIdentifiers
- .getOrPut(userPackageKey) { StartTimeAndIdentifiers(systemClock) }
- .addFgsToken(token)
+ .getOrPut(userPackageKey) { StartTimeAndIdentifiers(systemClock) }
+ .addFgsToken(token)
} else {
- if (runningTaskIdentifiers[userPackageKey]?.also {
- it.removeFgsToken(token)
- }?.isEmpty() == true
+ if (
+ runningTaskIdentifiers[userPackageKey]
+ ?.also { it.removeFgsToken(token) }
+ ?.isEmpty() == true
) {
runningTaskIdentifiers.remove(userPackageKey)
}
@@ -665,20 +677,24 @@
private inner class UserVisibleJobObserver : IUserVisibleJobObserver.Stub() {
override fun onUserVisibleJobStateChanged(
- summary: UserVisibleJobSummary,
- isRunning: Boolean
+ summary: UserVisibleJobSummary,
+ isRunning: Boolean,
) {
synchronized(lock) {
- val userPackageKey = UserPackage(
- UserHandle.getUserId(summary.callingUid), summary.callingPackageName)
+ val userPackageKey =
+ UserPackage(
+ UserHandle.getUserId(summary.callingUid),
+ summary.callingPackageName,
+ )
if (isRunning) {
runningTaskIdentifiers
- .getOrPut(userPackageKey) { StartTimeAndIdentifiers(systemClock) }
- .addJobSummary(summary)
+ .getOrPut(userPackageKey) { StartTimeAndIdentifiers(systemClock) }
+ .addJobSummary(summary)
} else {
- if (runningTaskIdentifiers[userPackageKey]?.also {
- it.removeJobSummary(summary)
- }?.isEmpty() == true
+ if (
+ runningTaskIdentifiers[userPackageKey]
+ ?.also { it.removeJobSummary(summary) }
+ ?.isEmpty() == true
) {
runningTaskIdentifiers.remove(userPackageKey)
}
@@ -691,10 +707,7 @@
}
}
- private inner class UserPackage(
- val userId: Int,
- val packageName: String
- ) {
+ private inner class UserPackage(val userId: Int, val packageName: String) {
val uid by lazy { packageManager.getPackageUidAsUser(packageName, userId) }
var backgroundRestrictionExemptionReason = PowerExemptionManager.REASON_DENIED
@@ -711,30 +724,31 @@
fun updateUiControl() {
backgroundRestrictionExemptionReason =
activityManager.getBackgroundRestrictionExemptionReason(uid)
- uiControl = when (backgroundRestrictionExemptionReason) {
- PowerExemptionManager.REASON_SYSTEM_UID,
- PowerExemptionManager.REASON_DEVICE_DEMO_MODE -> UIControl.HIDE_ENTRY
+ uiControl =
+ when (backgroundRestrictionExemptionReason) {
+ PowerExemptionManager.REASON_SYSTEM_UID,
+ PowerExemptionManager.REASON_DEVICE_DEMO_MODE -> UIControl.HIDE_ENTRY
- PowerExemptionManager.REASON_SYSTEM_ALLOW_LISTED,
- PowerExemptionManager.REASON_DEVICE_OWNER,
- PowerExemptionManager.REASON_DISALLOW_APPS_CONTROL,
- PowerExemptionManager.REASON_DPO_PROTECTED_APP,
- PowerExemptionManager.REASON_PROFILE_OWNER,
- PowerExemptionManager.REASON_ACTIVE_DEVICE_ADMIN,
- PowerExemptionManager.REASON_PROC_STATE_PERSISTENT,
- PowerExemptionManager.REASON_PROC_STATE_PERSISTENT_UI,
- PowerExemptionManager.REASON_ROLE_DIALER,
- PowerExemptionManager.REASON_SYSTEM_MODULE,
- PowerExemptionManager.REASON_SYSTEM_EXEMPT_APP_OP -> UIControl.HIDE_BUTTON
+ PowerExemptionManager.REASON_SYSTEM_ALLOW_LISTED,
+ PowerExemptionManager.REASON_DEVICE_OWNER,
+ PowerExemptionManager.REASON_DISALLOW_APPS_CONTROL,
+ PowerExemptionManager.REASON_DPO_PROTECTED_APP,
+ PowerExemptionManager.REASON_PROFILE_OWNER,
+ PowerExemptionManager.REASON_ACTIVE_DEVICE_ADMIN,
+ PowerExemptionManager.REASON_PROC_STATE_PERSISTENT,
+ PowerExemptionManager.REASON_PROC_STATE_PERSISTENT_UI,
+ PowerExemptionManager.REASON_ROLE_DIALER,
+ PowerExemptionManager.REASON_SYSTEM_MODULE,
+ PowerExemptionManager.REASON_SYSTEM_EXEMPT_APP_OP -> UIControl.HIDE_BUTTON
- PowerExemptionManager.REASON_ALLOWLISTED_PACKAGE ->
- if (showStopBtnForUserAllowlistedApps) {
- UIControl.NORMAL
- } else {
- UIControl.HIDE_BUTTON
- }
- else -> UIControl.NORMAL
- }
+ PowerExemptionManager.REASON_ALLOWLISTED_PACKAGE ->
+ if (showStopBtnForUserAllowlistedApps) {
+ UIControl.NORMAL
+ } else {
+ UIControl.HIDE_BUTTON
+ }
+ else -> UIControl.NORMAL
+ }
// If the app wants to be a good citizen by being stoppable, even if the category it
// belongs to is exempted for background restriction, let it be stoppable by user.
if (Flags.stoppableFgsSystemApp()) {
@@ -747,8 +761,7 @@
}
fun isStoppableApp(packageName: String): Boolean {
- return stoppableApps.contains(packageName) ||
- vendorStoppableApps.contains(packageName)
+ return stoppableApps.contains(packageName) || vendorStoppableApps.contains(packageName)
}
override fun equals(other: Any?): Boolean {
@@ -771,9 +784,7 @@
}
}
- private data class StartTimeAndIdentifiers(
- val systemClock: SystemClock
- ) {
+ private data class StartTimeAndIdentifiers(val systemClock: SystemClock) {
val startTime = systemClock.elapsedRealtime()
val fgsTokens = mutableSetOf<IBinder>()
val jobSummaries = mutableSetOf<UserVisibleJobSummary>()
@@ -846,7 +857,7 @@
val userId: Int,
val packageName: String,
val timeStarted: Long,
- val uiControl: UIControl
+ val uiControl: UIControl,
) {
constructor(
userId: Int,
@@ -854,7 +865,7 @@
timeStarted: Long,
uiControl: UIControl,
appLabel: CharSequence,
- icon: Drawable
+ icon: Drawable,
) : this(userId, packageName, timeStarted, uiControl) {
this.appLabel = appLabel
this.icon = icon
@@ -884,7 +895,9 @@
}
private enum class UIControl {
- NORMAL, HIDE_BUTTON, HIDE_ENTRY
+ NORMAL,
+ HIDE_BUTTON,
+ HIDE_ENTRY,
}
override fun dump(printwriter: PrintWriter, args: Array<out String>) {
diff --git a/packages/SystemUI/src/com/android/systemui/qs/QSTileRevealController.java b/packages/SystemUI/src/com/android/systemui/qs/QSTileRevealController.java
index 5da4809..cb3fc07 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/QSTileRevealController.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/QSTileRevealController.java
@@ -10,6 +10,7 @@
import com.android.systemui.plugins.qs.QSTile;
import com.android.systemui.qs.customize.QSCustomizerController;
import com.android.systemui.qs.dagger.QSScope;
+import com.android.systemui.shade.ShadeDisplayAware;
import java.util.Collection;
import java.util.Collections;
@@ -96,7 +97,7 @@
private final QSCustomizerController mQsCustomizerController;
@Inject
- Factory(Context context, QSCustomizerController qsCustomizerController) {
+ Factory(@ShadeDisplayAware Context context, QSCustomizerController qsCustomizerController) {
mContext = context;
mQsCustomizerController = qsCustomizerController;
}
diff --git a/packages/SystemUI/src/com/android/systemui/qs/external/CustomTileStatePersister.kt b/packages/SystemUI/src/com/android/systemui/qs/external/CustomTileStatePersister.kt
index 6f5dea3..379b606 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/external/CustomTileStatePersister.kt
+++ b/packages/SystemUI/src/com/android/systemui/qs/external/CustomTileStatePersister.kt
@@ -22,12 +22,14 @@
import android.service.quicksettings.Tile
import android.util.Log
import com.android.internal.annotations.VisibleForTesting
+import com.android.systemui.dagger.qualifiers.Application
import javax.inject.Inject
import org.json.JSONException
import org.json.JSONObject
data class TileServiceKey(val componentName: ComponentName, val user: Int) {
private val string = "${componentName.flattenToString()}:$user"
+
override fun toString() = string
}
@@ -56,12 +58,14 @@
* Any fields that have not been saved will be set to `null`
*/
fun readState(key: TileServiceKey): Tile?
+
/**
* Persists the state into [SharedPreferences].
*
* The implementation does not store fields that are `null` or icons.
*/
fun persistState(key: TileServiceKey, tile: Tile)
+
/**
* Removes the state for a given tile, user pair.
*
@@ -71,7 +75,7 @@
}
// TODO(b/299909989) Merge this class into into CustomTileRepository
-class CustomTileStatePersisterImpl @Inject constructor(context: Context) :
+class CustomTileStatePersisterImpl @Inject constructor(@Application context: Context) :
CustomTileStatePersister {
companion object {
private const val FILE_NAME = "custom_tiles_state"
diff --git a/packages/SystemUI/src/com/android/systemui/qs/external/PackageManagerAdapter.java b/packages/SystemUI/src/com/android/systemui/qs/external/PackageManagerAdapter.java
index 28e4fd0..6fb4455 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/external/PackageManagerAdapter.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/external/PackageManagerAdapter.java
@@ -28,6 +28,8 @@
import androidx.annotation.Nullable;
+import com.android.systemui.dagger.qualifiers.Application;
+
import javax.inject.Inject;
// Adapter that wraps calls to PackageManager or IPackageManager for {@link TileLifecycleManager}.
@@ -42,7 +44,7 @@
// Uses the PackageManager for the provided context.
// When necessary, uses the IPackagemanger in AppGlobals.
@Inject
- public PackageManagerAdapter(Context context) {
+ public PackageManagerAdapter(@Application Context context) {
mPackageManager = context.getPackageManager();
mIPackageManager = AppGlobals.getPackageManager();
}
diff --git a/packages/SystemUI/src/com/android/systemui/qs/panels/data/repository/LargeTileSpanRepository.kt b/packages/SystemUI/src/com/android/systemui/qs/panels/data/repository/LargeTileSpanRepository.kt
index 5883403..eeec9b3 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/panels/data/repository/LargeTileSpanRepository.kt
+++ b/packages/SystemUI/src/com/android/systemui/qs/panels/data/repository/LargeTileSpanRepository.kt
@@ -20,8 +20,8 @@
import com.android.systemui.common.ui.data.repository.ConfigurationRepository
import com.android.systemui.dagger.SysUISingleton
import com.android.systemui.dagger.qualifiers.Application
-import com.android.systemui.dagger.qualifiers.Main
import com.android.systemui.res.R
+import com.android.systemui.shade.ShadeDisplayAware
import com.android.systemui.util.kotlin.emitOnStart
import javax.inject.Inject
import kotlinx.coroutines.CoroutineScope
@@ -38,8 +38,8 @@
@Inject
constructor(
@Application scope: CoroutineScope,
- @Main private val resources: Resources,
- configurationRepository: ConfigurationRepository,
+ @ShadeDisplayAware private val resources: Resources,
+ @ShadeDisplayAware configurationRepository: ConfigurationRepository,
) {
val span: StateFlow<Int> =
configurationRepository.onConfigurationChange
diff --git a/packages/SystemUI/src/com/android/systemui/qs/panels/data/repository/PaginatedGridRepository.kt b/packages/SystemUI/src/com/android/systemui/qs/panels/data/repository/PaginatedGridRepository.kt
index 424be90..6746efa 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/panels/data/repository/PaginatedGridRepository.kt
+++ b/packages/SystemUI/src/com/android/systemui/qs/panels/data/repository/PaginatedGridRepository.kt
@@ -19,8 +19,8 @@
import android.content.res.Resources
import com.android.systemui.common.ui.data.repository.ConfigurationRepository
import com.android.systemui.dagger.SysUISingleton
-import com.android.systemui.dagger.qualifiers.Main
import com.android.systemui.res.R
+import com.android.systemui.shade.ShadeDisplayAware
import com.android.systemui.util.kotlin.emitOnStart
import javax.inject.Inject
import kotlinx.coroutines.flow.map
@@ -33,8 +33,8 @@
class PaginatedGridRepository
@Inject
constructor(
- @Main private val resources: Resources,
- configurationRepository: ConfigurationRepository,
+ @ShadeDisplayAware private val resources: Resources,
+ @ShadeDisplayAware configurationRepository: ConfigurationRepository,
) {
val rows =
configurationRepository.onConfigurationChange.emitOnStart().map {
diff --git a/packages/SystemUI/src/com/android/systemui/qs/panels/data/repository/QSColumnsRepository.kt b/packages/SystemUI/src/com/android/systemui/qs/panels/data/repository/QSColumnsRepository.kt
index a9205c2..693681d 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/panels/data/repository/QSColumnsRepository.kt
+++ b/packages/SystemUI/src/com/android/systemui/qs/panels/data/repository/QSColumnsRepository.kt
@@ -19,8 +19,8 @@
import android.content.res.Resources
import com.android.systemui.common.ui.data.repository.ConfigurationRepository
import com.android.systemui.dagger.SysUISingleton
-import com.android.systemui.dagger.qualifiers.Main
import com.android.systemui.res.R
+import com.android.systemui.shade.ShadeDisplayAware
import com.android.systemui.util.kotlin.emitOnStart
import javax.inject.Inject
import kotlinx.coroutines.ExperimentalCoroutinesApi
@@ -33,8 +33,8 @@
class QSColumnsRepository
@Inject
constructor(
- @Main private val resources: Resources,
- configurationRepository: ConfigurationRepository,
+ @ShadeDisplayAware private val resources: Resources,
+ @ShadeDisplayAware configurationRepository: ConfigurationRepository,
) {
val splitShadeColumns: Flow<Int> =
flowOf(resources.getInteger(R.integer.quick_settings_split_shade_num_columns))
diff --git a/packages/SystemUI/src/com/android/systemui/qs/panels/data/repository/QuickQuickSettingsRowRepository.kt b/packages/SystemUI/src/com/android/systemui/qs/panels/data/repository/QuickQuickSettingsRowRepository.kt
index ee0cfb3..1def7b3 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/panels/data/repository/QuickQuickSettingsRowRepository.kt
+++ b/packages/SystemUI/src/com/android/systemui/qs/panels/data/repository/QuickQuickSettingsRowRepository.kt
@@ -21,6 +21,7 @@
import com.android.systemui.dagger.SysUISingleton
import com.android.systemui.dagger.qualifiers.Main
import com.android.systemui.res.R
+import com.android.systemui.shade.ShadeDisplayAware
import com.android.systemui.util.kotlin.emitOnStart
import javax.inject.Inject
import kotlinx.coroutines.flow.map
@@ -30,7 +31,7 @@
@Inject
constructor(
@Main private val resources: Resources,
- configurationRepository: ConfigurationRepository,
+ @ShadeDisplayAware configurationRepository: ConfigurationRepository,
) {
val rows =
configurationRepository.onConfigurationChange.emitOnStart().map {
diff --git a/packages/SystemUI/src/com/android/systemui/qs/panels/data/repository/StockTilesRepository.kt b/packages/SystemUI/src/com/android/systemui/qs/panels/data/repository/StockTilesRepository.kt
index 86a29f9..a2d892c 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/panels/data/repository/StockTilesRepository.kt
+++ b/packages/SystemUI/src/com/android/systemui/qs/panels/data/repository/StockTilesRepository.kt
@@ -19,17 +19,15 @@
import android.content.res.Resources
import com.android.server.display.feature.flags.Flags
import com.android.systemui.dagger.SysUISingleton
-import com.android.systemui.dagger.qualifiers.Main
import com.android.systemui.qs.pipeline.shared.TileSpec
import com.android.systemui.res.R
+import com.android.systemui.shade.ShadeDisplayAware
import javax.inject.Inject
@SysUISingleton
class StockTilesRepository
@Inject
-constructor(
- @Main private val resources: Resources,
-) {
+constructor(@ShadeDisplayAware private val resources: Resources) {
/**
* List of stock platform tiles. All of the specs will be of type [TileSpec.PlatformTileSpec].
*/
diff --git a/packages/SystemUI/src/com/android/systemui/qs/pipeline/data/repository/DefaultTilesRepository.kt b/packages/SystemUI/src/com/android/systemui/qs/pipeline/data/repository/DefaultTilesRepository.kt
index fe0a69b..d4ac901 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/pipeline/data/repository/DefaultTilesRepository.kt
+++ b/packages/SystemUI/src/com/android/systemui/qs/pipeline/data/repository/DefaultTilesRepository.kt
@@ -2,9 +2,9 @@
import android.content.res.Resources
import com.android.systemui.dagger.SysUISingleton
-import com.android.systemui.dagger.qualifiers.Main
import com.android.systemui.qs.QSHost
import com.android.systemui.qs.pipeline.shared.TileSpec
+import com.android.systemui.shade.ShadeDisplayAware
import javax.inject.Inject
interface DefaultTilesRepository {
@@ -14,9 +14,7 @@
@SysUISingleton
class DefaultTilesQSHostRepository
@Inject
-constructor(
- @Main private val resources: Resources,
-) : DefaultTilesRepository {
+constructor(@ShadeDisplayAware private val resources: Resources) : DefaultTilesRepository {
override val defaultTiles: List<TileSpec>
get() =
QSHost.getDefaultSpecs(resources).map(TileSpec::create).filter {
diff --git a/packages/SystemUI/src/com/android/systemui/qs/pipeline/data/repository/MinimumTilesRepository.kt b/packages/SystemUI/src/com/android/systemui/qs/pipeline/data/repository/MinimumTilesRepository.kt
index 3a005c0..40720a2 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/pipeline/data/repository/MinimumTilesRepository.kt
+++ b/packages/SystemUI/src/com/android/systemui/qs/pipeline/data/repository/MinimumTilesRepository.kt
@@ -18,8 +18,8 @@
import android.content.res.Resources
import com.android.systemui.dagger.SysUISingleton
-import com.android.systemui.dagger.qualifiers.Main
import com.android.systemui.res.R
+import com.android.systemui.shade.ShadeDisplayAware
import javax.inject.Inject
/**
@@ -35,7 +35,7 @@
* creation, as it's not expected to change.
*/
@SysUISingleton
-class MinimumTilesResourceRepository @Inject constructor(@Main resources: Resources) :
+class MinimumTilesResourceRepository @Inject constructor(@ShadeDisplayAware resources: Resources) :
MinimumTilesRepository {
override val minNumberOfTiles: Int =
resources.getInteger(R.integer.quick_settings_min_num_tiles)
diff --git a/packages/SystemUI/src/com/android/systemui/qs/pipeline/data/repository/TileSpecRepository.kt b/packages/SystemUI/src/com/android/systemui/qs/pipeline/data/repository/TileSpecRepository.kt
index d94e7cf..c6751b7 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/pipeline/data/repository/TileSpecRepository.kt
+++ b/packages/SystemUI/src/com/android/systemui/qs/pipeline/data/repository/TileSpecRepository.kt
@@ -20,12 +20,12 @@
import android.content.res.Resources
import android.util.SparseArray
import com.android.systemui.dagger.SysUISingleton
-import com.android.systemui.dagger.qualifiers.Main
import com.android.systemui.qs.pipeline.data.model.RestoreData
import com.android.systemui.qs.pipeline.shared.TileSpec
import com.android.systemui.qs.pipeline.shared.logging.QSPipelineLogger
import com.android.systemui.res.R
import com.android.systemui.retail.data.repository.RetailModeRepository
+import com.android.systemui.shade.ShadeDisplayAware
import javax.inject.Inject
import kotlinx.coroutines.ExperimentalCoroutinesApi
import kotlinx.coroutines.flow.Flow
@@ -92,7 +92,7 @@
class TileSpecSettingsRepository
@Inject
constructor(
- @Main private val resources: Resources,
+ @ShadeDisplayAware private val resources: Resources,
private val logger: QSPipelineLogger,
private val retailModeRepository: RetailModeRepository,
private val userTileSpecRepositoryFactory: UserTileSpecRepository.Factory,
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/QuickAccessWalletTile.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/QuickAccessWalletTile.java
index 3d039e6..04e72d5 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/QuickAccessWalletTile.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/QuickAccessWalletTile.java
@@ -142,8 +142,16 @@
InteractionJankMonitor.CUJ_SHADE_APP_LAUNCH_FROM_QS_TILE);
mUiHandler.post(
- () -> mController.startQuickAccessUiIntent(
- mActivityStarter, animationController, mSelectedCard != null));
+ () -> {
+ if (android.service.quickaccesswallet.Flags.launchSelectedCardFromQsTile()
+ && mSelectedCard != null) {
+ mController.startWalletCardPendingIntent(
+ mSelectedCard, mActivityStarter, animationController);
+ } else {
+ mController.startQuickAccessUiIntent(
+ mActivityStarter, animationController, mSelectedCard != null);
+ }
+ });
}
@Override
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/impl/airplane/domain/AirplaneModeMapper.kt b/packages/SystemUI/src/com/android/systemui/qs/tiles/impl/airplane/domain/AirplaneModeMapper.kt
index d67057a..34c2ec9 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/impl/airplane/domain/AirplaneModeMapper.kt
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/impl/airplane/domain/AirplaneModeMapper.kt
@@ -19,18 +19,18 @@
import android.content.res.Resources
import android.content.res.Resources.Theme
import com.android.systemui.common.shared.model.Icon
-import com.android.systemui.dagger.qualifiers.Main
import com.android.systemui.qs.tiles.base.interactor.QSTileDataToStateMapper
import com.android.systemui.qs.tiles.impl.airplane.domain.model.AirplaneModeTileModel
import com.android.systemui.qs.tiles.viewmodel.QSTileConfig
import com.android.systemui.qs.tiles.viewmodel.QSTileState
import com.android.systemui.res.R
+import com.android.systemui.shade.ShadeDisplayAware
import javax.inject.Inject
/** Maps [AirplaneModeTileModel] to [QSTileState]. */
class AirplaneModeMapper
@Inject
-constructor(@Main private val resources: Resources, val theme: Theme) :
+constructor(@ShadeDisplayAware private val resources: Resources, val theme: Theme) :
QSTileDataToStateMapper<AirplaneModeTileModel> {
override fun map(config: QSTileConfig, data: AirplaneModeTileModel): QSTileState =
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/impl/alarm/domain/AlarmTileMapper.kt b/packages/SystemUI/src/com/android/systemui/qs/tiles/impl/alarm/domain/AlarmTileMapper.kt
index 7322b8d..a72992d 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/impl/alarm/domain/AlarmTileMapper.kt
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/impl/alarm/domain/AlarmTileMapper.kt
@@ -19,12 +19,12 @@
import android.content.res.Resources
import android.content.res.Resources.Theme
import com.android.systemui.common.shared.model.Icon
-import com.android.systemui.dagger.qualifiers.Main
import com.android.systemui.qs.tiles.base.interactor.QSTileDataToStateMapper
import com.android.systemui.qs.tiles.impl.alarm.domain.model.AlarmTileModel
import com.android.systemui.qs.tiles.viewmodel.QSTileConfig
import com.android.systemui.qs.tiles.viewmodel.QSTileState
import com.android.systemui.res.R
+import com.android.systemui.shade.ShadeDisplayAware
import com.android.systemui.util.time.SystemClock
import java.time.Instant
import java.time.LocalDateTime
@@ -36,7 +36,7 @@
class AlarmTileMapper
@Inject
constructor(
- @Main private val resources: Resources,
+ @ShadeDisplayAware private val resources: Resources,
private val theme: Theme,
private val clock: SystemClock,
) : QSTileDataToStateMapper<AlarmTileModel> {
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/impl/battery/ui/BatterySaverTileMapper.kt b/packages/SystemUI/src/com/android/systemui/qs/tiles/impl/battery/ui/BatterySaverTileMapper.kt
index 5b30e8d..e116d8c 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/impl/battery/ui/BatterySaverTileMapper.kt
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/impl/battery/ui/BatterySaverTileMapper.kt
@@ -18,19 +18,21 @@
import android.content.res.Resources
import com.android.systemui.common.shared.model.Icon
-import com.android.systemui.dagger.qualifiers.Main
import com.android.systemui.qs.tiles.base.interactor.QSTileDataToStateMapper
import com.android.systemui.qs.tiles.impl.battery.domain.model.BatterySaverTileModel
import com.android.systemui.qs.tiles.viewmodel.QSTileConfig
import com.android.systemui.qs.tiles.viewmodel.QSTileState
import com.android.systemui.res.R
+import com.android.systemui.shade.ShadeDisplayAware
import javax.inject.Inject
/** Maps [BatterySaverTileModel] to [QSTileState]. */
open class BatterySaverTileMapper
@Inject
-constructor(@Main protected val resources: Resources, private val theme: Resources.Theme) :
- QSTileDataToStateMapper<BatterySaverTileModel> {
+constructor(
+ @ShadeDisplayAware protected val resources: Resources,
+ private val theme: Resources.Theme,
+) : QSTileDataToStateMapper<BatterySaverTileModel> {
override fun map(config: QSTileConfig, data: BatterySaverTileModel): QSTileState =
QSTileState.build(resources, theme, config.uiConfig) {
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/impl/colorcorrection/domain/ColorCorrectionTileMapper.kt b/packages/SystemUI/src/com/android/systemui/qs/tiles/impl/colorcorrection/domain/ColorCorrectionTileMapper.kt
index 7c90b3d..21b9f65 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/impl/colorcorrection/domain/ColorCorrectionTileMapper.kt
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/impl/colorcorrection/domain/ColorCorrectionTileMapper.kt
@@ -18,19 +18,21 @@
import android.content.res.Resources
import com.android.systemui.common.shared.model.Icon
-import com.android.systemui.dagger.qualifiers.Main
import com.android.systemui.qs.tiles.base.interactor.QSTileDataToStateMapper
import com.android.systemui.qs.tiles.impl.colorcorrection.domain.model.ColorCorrectionTileModel
import com.android.systemui.qs.tiles.viewmodel.QSTileConfig
import com.android.systemui.qs.tiles.viewmodel.QSTileState
import com.android.systemui.res.R
+import com.android.systemui.shade.ShadeDisplayAware
import javax.inject.Inject
/** Maps [ColorCorrectionTileModel] to [QSTileState]. */
class ColorCorrectionTileMapper
@Inject
-constructor(@Main private val resources: Resources, private val theme: Resources.Theme) :
- QSTileDataToStateMapper<ColorCorrectionTileModel> {
+constructor(
+ @ShadeDisplayAware private val resources: Resources,
+ private val theme: Resources.Theme,
+) : QSTileDataToStateMapper<ColorCorrectionTileModel> {
override fun map(config: QSTileConfig, data: ColorCorrectionTileModel): QSTileState =
QSTileState.build(resources, theme, config.uiConfig) {
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/impl/custom/domain/interactor/CustomTileDataInteractor.kt b/packages/SystemUI/src/com/android/systemui/qs/tiles/impl/custom/domain/interactor/CustomTileDataInteractor.kt
index 8f870d4..4806c3f 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/impl/custom/domain/interactor/CustomTileDataInteractor.kt
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/impl/custom/domain/interactor/CustomTileDataInteractor.kt
@@ -18,7 +18,7 @@
import android.os.UserHandle
import android.service.quicksettings.Tile
-import com.android.systemui.common.coroutine.ConflatedCallbackFlow
+import com.android.app.tracing.coroutines.launchTraced as launch
import com.android.systemui.qs.pipeline.shared.TileSpec
import com.android.systemui.qs.tiles.base.interactor.DataUpdateTrigger
import com.android.systemui.qs.tiles.base.interactor.QSTileDataInteractor
@@ -28,6 +28,7 @@
import com.android.systemui.qs.tiles.impl.custom.domain.entity.CustomTileDataModel
import com.android.systemui.qs.tiles.impl.di.QSTileScope
import com.android.systemui.user.data.repository.UserRepository
+import com.android.systemui.utils.coroutines.flow.conflatedCallbackFlow
import javax.inject.Inject
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.ExperimentalCoroutinesApi
@@ -44,7 +45,6 @@
import kotlinx.coroutines.flow.onEach
import kotlinx.coroutines.flow.onStart
import kotlinx.coroutines.flow.shareIn
-import com.android.app.tracing.coroutines.launchTraced as launch
@QSTileScope
@OptIn(ExperimentalCoroutinesApi::class)
@@ -64,7 +64,7 @@
private val bindingFlow =
mutableUserFlow
.flatMapLatest { user ->
- ConflatedCallbackFlow.conflatedCallbackFlow {
+ conflatedCallbackFlow {
serviceInteractor.setUser(user)
// Wait for the CustomTileInteractor to become initialized first, because
@@ -79,7 +79,7 @@
defaultsRepository.requestNewDefaults(
user,
tileSpec.componentName,
- true
+ true,
)
}
.launchIn(this)
@@ -99,7 +99,7 @@
override fun tileData(
user: UserHandle,
- triggers: Flow<DataUpdateTrigger>
+ triggers: Flow<DataUpdateTrigger>,
): Flow<CustomTileDataModel> {
tileScope.launch { mutableUserFlow.emit(user) }
return bindingFlow.combine(triggers) { _, _ -> }.flatMapLatest { dataFlow(user) }
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/impl/flashlight/domain/FlashlightMapper.kt b/packages/SystemUI/src/com/android/systemui/qs/tiles/impl/flashlight/domain/FlashlightMapper.kt
index 7e557eb..2dfb1fc 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/impl/flashlight/domain/FlashlightMapper.kt
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/impl/flashlight/domain/FlashlightMapper.kt
@@ -19,18 +19,18 @@
import android.content.res.Resources
import android.content.res.Resources.Theme
import com.android.systemui.common.shared.model.Icon
-import com.android.systemui.dagger.qualifiers.Main
import com.android.systemui.qs.tiles.base.interactor.QSTileDataToStateMapper
import com.android.systemui.qs.tiles.impl.flashlight.domain.model.FlashlightTileModel
import com.android.systemui.qs.tiles.viewmodel.QSTileConfig
import com.android.systemui.qs.tiles.viewmodel.QSTileState
import com.android.systemui.res.R
+import com.android.systemui.shade.ShadeDisplayAware
import javax.inject.Inject
/** Maps [FlashlightTileModel] to [QSTileState]. */
class FlashlightMapper
@Inject
-constructor(@Main private val resources: Resources, private val theme: Theme) :
+constructor(@ShadeDisplayAware private val resources: Resources, private val theme: Theme) :
QSTileDataToStateMapper<FlashlightTileModel> {
override fun map(config: QSTileConfig, data: FlashlightTileModel): QSTileState =
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/impl/fontscaling/domain/FontScalingTileMapper.kt b/packages/SystemUI/src/com/android/systemui/qs/tiles/impl/fontscaling/domain/FontScalingTileMapper.kt
index 9d44fc6..7f41cbd 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/impl/fontscaling/domain/FontScalingTileMapper.kt
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/impl/fontscaling/domain/FontScalingTileMapper.kt
@@ -18,19 +18,21 @@
import android.content.res.Resources
import com.android.systemui.common.shared.model.Icon
-import com.android.systemui.dagger.qualifiers.Main
import com.android.systemui.qs.tiles.base.interactor.QSTileDataToStateMapper
import com.android.systemui.qs.tiles.impl.fontscaling.domain.model.FontScalingTileModel
import com.android.systemui.qs.tiles.viewmodel.QSTileConfig
import com.android.systemui.qs.tiles.viewmodel.QSTileState
import com.android.systemui.res.R
+import com.android.systemui.shade.ShadeDisplayAware
import javax.inject.Inject
/** Maps [FontScalingTileModel] to [QSTileState]. */
class FontScalingTileMapper
@Inject
-constructor(@Main private val resources: Resources, private val theme: Resources.Theme) :
- QSTileDataToStateMapper<FontScalingTileModel> {
+constructor(
+ @ShadeDisplayAware private val resources: Resources,
+ private val theme: Resources.Theme,
+) : QSTileDataToStateMapper<FontScalingTileModel> {
override fun map(config: QSTileConfig, data: FontScalingTileModel): QSTileState =
QSTileState.build(resources, theme, config.uiConfig) {
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/impl/hearingdevices/domain/HearingDevicesTileMapper.kt b/packages/SystemUI/src/com/android/systemui/qs/tiles/impl/hearingdevices/domain/HearingDevicesTileMapper.kt
index c3ac1f8..4c302b3 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/impl/hearingdevices/domain/HearingDevicesTileMapper.kt
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/impl/hearingdevices/domain/HearingDevicesTileMapper.kt
@@ -18,19 +18,21 @@
import android.content.res.Resources
import com.android.systemui.common.shared.model.Icon
-import com.android.systemui.dagger.qualifiers.Main
import com.android.systemui.qs.tiles.base.interactor.QSTileDataToStateMapper
import com.android.systemui.qs.tiles.impl.hearingdevices.domain.model.HearingDevicesTileModel
import com.android.systemui.qs.tiles.viewmodel.QSTileConfig
import com.android.systemui.qs.tiles.viewmodel.QSTileState
import com.android.systemui.res.R
+import com.android.systemui.shade.ShadeDisplayAware
import javax.inject.Inject
/** Maps [HearingDevicesTileModel] to [QSTileState]. */
class HearingDevicesTileMapper
@Inject
-constructor(@Main private val resources: Resources, private val theme: Resources.Theme) :
- QSTileDataToStateMapper<HearingDevicesTileModel> {
+constructor(
+ @ShadeDisplayAware private val resources: Resources,
+ private val theme: Resources.Theme,
+) : QSTileDataToStateMapper<HearingDevicesTileModel> {
override fun map(config: QSTileConfig, data: HearingDevicesTileModel): QSTileState =
QSTileState.build(resources, theme, config.uiConfig) {
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/impl/inversion/domain/ColorInversionTileMapper.kt b/packages/SystemUI/src/com/android/systemui/qs/tiles/impl/inversion/domain/ColorInversionTileMapper.kt
index 3692c35..8d35b24 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/impl/inversion/domain/ColorInversionTileMapper.kt
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/impl/inversion/domain/ColorInversionTileMapper.kt
@@ -19,18 +19,18 @@
import android.content.res.Resources
import android.content.res.Resources.Theme
import com.android.systemui.common.shared.model.Icon
-import com.android.systemui.dagger.qualifiers.Main
import com.android.systemui.qs.tiles.base.interactor.QSTileDataToStateMapper
import com.android.systemui.qs.tiles.impl.inversion.domain.model.ColorInversionTileModel
import com.android.systemui.qs.tiles.viewmodel.QSTileConfig
import com.android.systemui.qs.tiles.viewmodel.QSTileState
import com.android.systemui.res.R
+import com.android.systemui.shade.ShadeDisplayAware
import javax.inject.Inject
/** Maps [ColorInversionTileModel] to [QSTileState]. */
class ColorInversionTileMapper
@Inject
-constructor(@Main private val resources: Resources, private val theme: Theme) :
+constructor(@ShadeDisplayAware private val resources: Resources, private val theme: Theme) :
QSTileDataToStateMapper<ColorInversionTileModel> {
override fun map(config: QSTileConfig, data: ColorInversionTileModel): QSTileState =
QSTileState.build(resources, theme, config.uiConfig) {
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/impl/irecording/IssueRecordingMapper.kt b/packages/SystemUI/src/com/android/systemui/qs/tiles/impl/irecording/IssueRecordingMapper.kt
index 3fe2a77..3557c1a 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/impl/irecording/IssueRecordingMapper.kt
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/impl/irecording/IssueRecordingMapper.kt
@@ -19,16 +19,16 @@
import android.content.res.Resources
import android.content.res.Resources.Theme
import com.android.systemui.common.shared.model.Icon
-import com.android.systemui.dagger.qualifiers.Main
import com.android.systemui.qs.tiles.base.interactor.QSTileDataToStateMapper
import com.android.systemui.qs.tiles.viewmodel.QSTileConfig
import com.android.systemui.qs.tiles.viewmodel.QSTileState
import com.android.systemui.res.R
+import com.android.systemui.shade.ShadeDisplayAware
import javax.inject.Inject
class IssueRecordingMapper
@Inject
-constructor(@Main private val resources: Resources, private val theme: Theme) :
+constructor(@ShadeDisplayAware private val resources: Resources, private val theme: Theme) :
QSTileDataToStateMapper<IssueRecordingModel> {
override fun map(config: QSTileConfig, data: IssueRecordingModel): QSTileState =
QSTileState.build(resources, theme, config.uiConfig) {
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/impl/location/domain/LocationTileMapper.kt b/packages/SystemUI/src/com/android/systemui/qs/tiles/impl/location/domain/LocationTileMapper.kt
index 08432f6..dfc24a1 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/impl/location/domain/LocationTileMapper.kt
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/impl/location/domain/LocationTileMapper.kt
@@ -19,18 +19,18 @@
import android.content.res.Resources
import android.content.res.Resources.Theme
import com.android.systemui.common.shared.model.Icon
-import com.android.systemui.dagger.qualifiers.Main
import com.android.systemui.qs.tiles.base.interactor.QSTileDataToStateMapper
import com.android.systemui.qs.tiles.impl.location.domain.model.LocationTileModel
import com.android.systemui.qs.tiles.viewmodel.QSTileConfig
import com.android.systemui.qs.tiles.viewmodel.QSTileState
import com.android.systemui.res.R
+import com.android.systemui.shade.ShadeDisplayAware
import javax.inject.Inject
/** Maps [LocationTileModel] to [QSTileState]. */
class LocationTileMapper
@Inject
-constructor(@Main private val resources: Resources, private val theme: Theme) :
+constructor(@ShadeDisplayAware private val resources: Resources, private val theme: Theme) :
QSTileDataToStateMapper<LocationTileModel> {
override fun map(config: QSTileConfig, data: LocationTileModel): QSTileState =
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/impl/modes/ui/ModesTileMapper.kt b/packages/SystemUI/src/com/android/systemui/qs/tiles/impl/modes/ui/ModesTileMapper.kt
index 4a64313..bac048f 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/impl/modes/ui/ModesTileMapper.kt
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/impl/modes/ui/ModesTileMapper.kt
@@ -19,18 +19,18 @@
import android.content.res.Resources
import android.icu.text.MessageFormat
import android.widget.Button
-import com.android.systemui.dagger.qualifiers.Main
import com.android.systemui.qs.tiles.base.interactor.QSTileDataToStateMapper
import com.android.systemui.qs.tiles.impl.modes.domain.model.ModesTileModel
import com.android.systemui.qs.tiles.viewmodel.QSTileConfig
import com.android.systemui.qs.tiles.viewmodel.QSTileState
import com.android.systemui.res.R
+import com.android.systemui.shade.ShadeDisplayAware
import java.util.Locale
import javax.inject.Inject
class ModesTileMapper
@Inject
-constructor(@Main private val resources: Resources, val theme: Resources.Theme) :
+constructor(@ShadeDisplayAware private val resources: Resources, val theme: Resources.Theme) :
QSTileDataToStateMapper<ModesTileModel> {
override fun map(config: QSTileConfig, data: ModesTileModel): QSTileState =
QSTileState.build(resources, theme, config.uiConfig) {
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/impl/night/domain/interactor/NightDisplayTileDataInteractor.kt b/packages/SystemUI/src/com/android/systemui/qs/tiles/impl/night/domain/interactor/NightDisplayTileDataInteractor.kt
index 88bd224..e8e43e8 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/impl/night/domain/interactor/NightDisplayTileDataInteractor.kt
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/impl/night/domain/interactor/NightDisplayTileDataInteractor.kt
@@ -20,10 +20,10 @@
import android.hardware.display.ColorDisplayManager
import android.os.UserHandle
import com.android.systemui.accessibility.data.repository.NightDisplayRepository
-import com.android.systemui.dagger.qualifiers.Application
import com.android.systemui.qs.tiles.base.interactor.DataUpdateTrigger
import com.android.systemui.qs.tiles.base.interactor.QSTileDataInteractor
import com.android.systemui.qs.tiles.impl.night.domain.model.NightDisplayTileModel
+import com.android.systemui.shade.ShadeDisplayAware
import com.android.systemui.util.time.DateFormatUtil
import java.time.LocalTime
import javax.inject.Inject
@@ -35,14 +35,14 @@
class NightDisplayTileDataInteractor
@Inject
constructor(
- @Application private val context: Context,
+ @ShadeDisplayAware private val context: Context,
private val dateFormatUtil: DateFormatUtil,
private val nightDisplayRepository: NightDisplayRepository,
) : QSTileDataInteractor<NightDisplayTileModel> {
override fun tileData(
user: UserHandle,
- triggers: Flow<DataUpdateTrigger>
+ triggers: Flow<DataUpdateTrigger>,
): Flow<NightDisplayTileModel> =
nightDisplayRepository.nightDisplayState(user).map {
generateModel(
@@ -51,7 +51,7 @@
it.startTime,
it.endTime,
it.shouldForceAutoMode,
- it.locationEnabled
+ it.locationEnabled,
)
}
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/impl/night/ui/NightDisplayTileMapper.kt b/packages/SystemUI/src/com/android/systemui/qs/tiles/impl/night/ui/NightDisplayTileMapper.kt
index 081a03c7..3569e4d 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/impl/night/ui/NightDisplayTileMapper.kt
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/impl/night/ui/NightDisplayTileMapper.kt
@@ -22,7 +22,6 @@
import androidx.annotation.StringRes
import com.android.systemui.accessibility.qs.QSAccessibilityModule
import com.android.systemui.common.shared.model.Icon
-import com.android.systemui.dagger.qualifiers.Main
import com.android.systemui.qs.pipeline.shared.TileSpec
import com.android.systemui.qs.tiles.base.interactor.QSTileDataToStateMapper
import com.android.systemui.qs.tiles.base.logging.QSTileLogger
@@ -30,6 +29,7 @@
import com.android.systemui.qs.tiles.viewmodel.QSTileConfig
import com.android.systemui.qs.tiles.viewmodel.QSTileState
import com.android.systemui.res.R
+import com.android.systemui.shade.ShadeDisplayAware
import java.time.DateTimeException
import java.time.LocalTime
import java.time.format.DateTimeFormatter
@@ -39,7 +39,7 @@
class NightDisplayTileMapper
@Inject
constructor(
- @Main private val resources: Resources,
+ @ShadeDisplayAware private val resources: Resources,
private val theme: Resources.Theme,
private val logger: QSTileLogger,
) : QSTileDataToStateMapper<NightDisplayTileModel> {
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/impl/notes/domain/NotesTileMapper.kt b/packages/SystemUI/src/com/android/systemui/qs/tiles/impl/notes/domain/NotesTileMapper.kt
index ee1b9e5..a543619 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/impl/notes/domain/NotesTileMapper.kt
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/impl/notes/domain/NotesTileMapper.kt
@@ -19,28 +19,24 @@
import android.content.res.Resources
import android.widget.Button
import com.android.systemui.common.shared.model.Icon
-import com.android.systemui.dagger.qualifiers.Main
import com.android.systemui.qs.tiles.base.interactor.QSTileDataToStateMapper
import com.android.systemui.qs.tiles.impl.notes.domain.model.NotesTileModel
import com.android.systemui.qs.tiles.viewmodel.QSTileConfig
import com.android.systemui.qs.tiles.viewmodel.QSTileState
import com.android.systemui.res.R
+import com.android.systemui.shade.ShadeDisplayAware
import javax.inject.Inject
class NotesTileMapper
@Inject
-constructor(@Main private val resources: Resources, private val theme: Resources.Theme) :
- QSTileDataToStateMapper<NotesTileModel> {
+constructor(
+ @ShadeDisplayAware private val resources: Resources,
+ private val theme: Resources.Theme,
+) : QSTileDataToStateMapper<NotesTileModel> {
override fun map(config: QSTileConfig, data: NotesTileModel): QSTileState =
QSTileState.build(resources, theme, config.uiConfig) {
iconRes = R.drawable.ic_qs_notes
- icon =
- Icon.Loaded(
- resources.getDrawable(
- iconRes!!,
- theme),
- contentDescription = null
- )
+ icon = Icon.Loaded(resources.getDrawable(iconRes!!, theme), contentDescription = null)
contentDescription = label
activationState = QSTileState.ActivationState.INACTIVE
sideViewIcon = QSTileState.SideViewIcon.Chevron
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/impl/onehanded/ui/OneHandedModeTileMapper.kt b/packages/SystemUI/src/com/android/systemui/qs/tiles/impl/onehanded/ui/OneHandedModeTileMapper.kt
index 8e5d0d4..76f1e8b 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/impl/onehanded/ui/OneHandedModeTileMapper.kt
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/impl/onehanded/ui/OneHandedModeTileMapper.kt
@@ -18,19 +18,21 @@
import android.content.res.Resources
import com.android.systemui.common.shared.model.Icon
-import com.android.systemui.dagger.qualifiers.Main
import com.android.systemui.qs.tiles.base.interactor.QSTileDataToStateMapper
import com.android.systemui.qs.tiles.impl.onehanded.domain.model.OneHandedModeTileModel
import com.android.systemui.qs.tiles.viewmodel.QSTileConfig
import com.android.systemui.qs.tiles.viewmodel.QSTileState
import com.android.systemui.res.R
+import com.android.systemui.shade.ShadeDisplayAware
import javax.inject.Inject
/** Maps [OneHandedModeTileModel] to [QSTileState]. */
class OneHandedModeTileMapper
@Inject
-constructor(@Main private val resources: Resources, private val theme: Resources.Theme) :
- QSTileDataToStateMapper<OneHandedModeTileModel> {
+constructor(
+ @ShadeDisplayAware private val resources: Resources,
+ private val theme: Resources.Theme,
+) : QSTileDataToStateMapper<OneHandedModeTileModel> {
override fun map(config: QSTileConfig, data: OneHandedModeTileModel): QSTileState =
QSTileState.build(resources, theme, config.uiConfig) {
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/impl/qr/ui/QRCodeScannerTileMapper.kt b/packages/SystemUI/src/com/android/systemui/qs/tiles/impl/qr/ui/QRCodeScannerTileMapper.kt
index 5c6351e..c546250 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/impl/qr/ui/QRCodeScannerTileMapper.kt
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/impl/qr/ui/QRCodeScannerTileMapper.kt
@@ -18,19 +18,21 @@
import android.content.res.Resources
import com.android.systemui.common.shared.model.Icon
-import com.android.systemui.dagger.qualifiers.Main
import com.android.systemui.qs.tiles.base.interactor.QSTileDataToStateMapper
import com.android.systemui.qs.tiles.impl.qr.domain.model.QRCodeScannerTileModel
import com.android.systemui.qs.tiles.viewmodel.QSTileConfig
import com.android.systemui.qs.tiles.viewmodel.QSTileState
import com.android.systemui.res.R
+import com.android.systemui.shade.ShadeDisplayAware
import javax.inject.Inject
/** Maps [QRCodeScannerTileModel] to [QSTileState]. */
class QRCodeScannerTileMapper
@Inject
-constructor(@Main private val resources: Resources, private val theme: Resources.Theme) :
- QSTileDataToStateMapper<QRCodeScannerTileModel> {
+constructor(
+ @ShadeDisplayAware private val resources: Resources,
+ private val theme: Resources.Theme,
+) : QSTileDataToStateMapper<QRCodeScannerTileModel> {
override fun map(config: QSTileConfig, data: QRCodeScannerTileModel): QSTileState =
QSTileState.build(resources, theme, config.uiConfig) {
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/impl/reducebrightness/domain/interactor/ReduceBrightColorsTileUserActionInteractor.kt b/packages/SystemUI/src/com/android/systemui/qs/tiles/impl/reducebrightness/domain/interactor/ReduceBrightColorsTileUserActionInteractor.kt
index 15c9901..eff5f8f 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/impl/reducebrightness/domain/interactor/ReduceBrightColorsTileUserActionInteractor.kt
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/impl/reducebrightness/domain/interactor/ReduceBrightColorsTileUserActionInteractor.kt
@@ -20,20 +20,20 @@
import android.content.res.Resources
import android.provider.Settings
import com.android.systemui.accessibility.extradim.ExtraDimDialogManager
-import com.android.systemui.dagger.qualifiers.Main
import com.android.systemui.qs.ReduceBrightColorsController
import com.android.systemui.qs.tiles.base.actions.QSTileIntentUserInputHandler
import com.android.systemui.qs.tiles.base.interactor.QSTileInput
import com.android.systemui.qs.tiles.base.interactor.QSTileUserActionInteractor
import com.android.systemui.qs.tiles.impl.reducebrightness.domain.model.ReduceBrightColorsTileModel
import com.android.systemui.qs.tiles.viewmodel.QSTileUserAction
+import com.android.systemui.shade.ShadeDisplayAware
import javax.inject.Inject
/** Handles reduce bright colors tile clicks. */
class ReduceBrightColorsTileUserActionInteractor
@Inject
constructor(
- @Main private val resources: Resources,
+ @ShadeDisplayAware private val resources: Resources,
private val qsTileIntentUserActionHandler: QSTileIntentUserInputHandler,
private val reduceBrightColorsController: ReduceBrightColorsController,
private val extraDimDialogManager: ExtraDimDialogManager,
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/impl/reducebrightness/ui/ReduceBrightColorsTileMapper.kt b/packages/SystemUI/src/com/android/systemui/qs/tiles/impl/reducebrightness/ui/ReduceBrightColorsTileMapper.kt
index fe77fe6..66d0f96 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/impl/reducebrightness/ui/ReduceBrightColorsTileMapper.kt
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/impl/reducebrightness/ui/ReduceBrightColorsTileMapper.kt
@@ -19,19 +19,21 @@
import android.content.res.Resources
import android.service.quicksettings.Tile
import com.android.systemui.common.shared.model.Icon
-import com.android.systemui.dagger.qualifiers.Main
import com.android.systemui.qs.tiles.base.interactor.QSTileDataToStateMapper
import com.android.systemui.qs.tiles.impl.reducebrightness.domain.model.ReduceBrightColorsTileModel
import com.android.systemui.qs.tiles.viewmodel.QSTileConfig
import com.android.systemui.qs.tiles.viewmodel.QSTileState
import com.android.systemui.res.R
+import com.android.systemui.shade.ShadeDisplayAware
import javax.inject.Inject
/** Maps [ReduceBrightColorsTileModel] to [QSTileState]. */
class ReduceBrightColorsTileMapper
@Inject
-constructor(@Main private val resources: Resources, private val theme: Resources.Theme) :
- QSTileDataToStateMapper<ReduceBrightColorsTileModel> {
+constructor(
+ @ShadeDisplayAware private val resources: Resources,
+ private val theme: Resources.Theme,
+) : QSTileDataToStateMapper<ReduceBrightColorsTileModel> {
override fun map(config: QSTileConfig, data: ReduceBrightColorsTileModel): QSTileState =
QSTileState.build(resources, theme, config.uiConfig) {
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/impl/rotation/domain/interactor/RotationLockTileDataInteractor.kt b/packages/SystemUI/src/com/android/systemui/qs/tiles/impl/rotation/domain/interactor/RotationLockTileDataInteractor.kt
index 57a60c1..7f17a3a 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/impl/rotation/domain/interactor/RotationLockTileDataInteractor.kt
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/impl/rotation/domain/interactor/RotationLockTileDataInteractor.kt
@@ -22,10 +22,10 @@
import android.os.UserHandle
import com.android.systemui.camera.data.repository.CameraAutoRotateRepository
import com.android.systemui.camera.data.repository.CameraSensorPrivacyRepository
-import com.android.systemui.dagger.qualifiers.Main
import com.android.systemui.qs.tiles.base.interactor.DataUpdateTrigger
import com.android.systemui.qs.tiles.base.interactor.QSTileDataInteractor
import com.android.systemui.qs.tiles.impl.rotation.domain.model.RotationLockTileModel
+import com.android.systemui.shade.ShadeDisplayAware
import com.android.systemui.statusbar.policy.BatteryController
import com.android.systemui.statusbar.policy.RotationLockController
import com.android.systemui.util.kotlin.isBatteryPowerSaveEnabled
@@ -44,30 +44,29 @@
private val cameraAutoRotateRepository: CameraAutoRotateRepository,
private val cameraSensorPrivacyRepository: CameraSensorPrivacyRepository,
private val packageManager: PackageManager,
- @Main private val resources: Resources,
+ @ShadeDisplayAware private val resources: Resources,
) : QSTileDataInteractor<RotationLockTileModel> {
override fun tileData(
user: UserHandle,
- triggers: Flow<DataUpdateTrigger>
+ triggers: Flow<DataUpdateTrigger>,
): Flow<RotationLockTileModel> =
combine(
rotationLockController.isRotationLockEnabled(),
cameraSensorPrivacyRepository.isEnabled(user),
batteryController.isBatteryPowerSaveEnabled(),
- cameraAutoRotateRepository.isCameraAutoRotateSettingEnabled(user)
+ cameraAutoRotateRepository.isCameraAutoRotateSettingEnabled(user),
) {
isRotationLockEnabled,
isCamPrivacySensorEnabled,
isBatteryPowerSaveEnabled,
- isCameraAutoRotateEnabled,
- ->
+ isCameraAutoRotateEnabled ->
RotationLockTileModel(
isRotationLockEnabled,
isCameraRotationEnabled(
isBatteryPowerSaveEnabled,
isCamPrivacySensorEnabled,
- isCameraAutoRotateEnabled
+ isCameraAutoRotateEnabled,
),
)
}
@@ -84,7 +83,7 @@
private fun isCameraRotationEnabled(
isBatteryPowerSaverModeOn: Boolean,
isCameraSensorPrivacyEnabled: Boolean,
- isCameraAutoRotateEnabled: Boolean
+ isCameraAutoRotateEnabled: Boolean,
): Boolean =
resources.getBoolean(com.android.internal.R.bool.config_allowRotationResolver) &&
!isBatteryPowerSaverModeOn &&
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/impl/rotation/ui/mapper/RotationLockTileMapper.kt b/packages/SystemUI/src/com/android/systemui/qs/tiles/impl/rotation/ui/mapper/RotationLockTileMapper.kt
index 9a003ff..a014422 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/impl/rotation/ui/mapper/RotationLockTileMapper.kt
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/impl/rotation/ui/mapper/RotationLockTileMapper.kt
@@ -19,12 +19,12 @@
import android.content.res.Resources
import android.hardware.devicestate.DeviceStateManager
import com.android.systemui.common.shared.model.Icon
-import com.android.systemui.dagger.qualifiers.Main
import com.android.systemui.qs.tiles.base.interactor.QSTileDataToStateMapper
import com.android.systemui.qs.tiles.impl.rotation.domain.model.RotationLockTileModel
import com.android.systemui.qs.tiles.viewmodel.QSTileConfig
import com.android.systemui.qs.tiles.viewmodel.QSTileState
import com.android.systemui.res.R
+import com.android.systemui.shade.ShadeDisplayAware
import com.android.systemui.statusbar.policy.DevicePostureController
import com.android.systemui.util.Utils.isDeviceFoldable
import javax.inject.Inject
@@ -33,7 +33,7 @@
class RotationLockTileMapper
@Inject
constructor(
- @Main private val resources: Resources,
+ @ShadeDisplayAware private val resources: Resources,
private val theme: Resources.Theme,
private val devicePostureController: DevicePostureController,
private val deviceStateManager: DeviceStateManager,
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/impl/saver/domain/DataSaverTileMapper.kt b/packages/SystemUI/src/com/android/systemui/qs/tiles/impl/saver/domain/DataSaverTileMapper.kt
index 08196bb..aea4967 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/impl/saver/domain/DataSaverTileMapper.kt
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/impl/saver/domain/DataSaverTileMapper.kt
@@ -18,19 +18,21 @@
import android.content.res.Resources
import com.android.systemui.common.shared.model.Icon
-import com.android.systemui.dagger.qualifiers.Main
import com.android.systemui.qs.tiles.base.interactor.QSTileDataToStateMapper
import com.android.systemui.qs.tiles.impl.saver.domain.model.DataSaverTileModel
import com.android.systemui.qs.tiles.viewmodel.QSTileConfig
import com.android.systemui.qs.tiles.viewmodel.QSTileState
import com.android.systemui.res.R
+import com.android.systemui.shade.ShadeDisplayAware
import javax.inject.Inject
/** Maps [DataSaverTileModel] to [QSTileState]. */
class DataSaverTileMapper
@Inject
-constructor(@Main private val resources: Resources, private val theme: Resources.Theme) :
- QSTileDataToStateMapper<DataSaverTileModel> {
+constructor(
+ @ShadeDisplayAware private val resources: Resources,
+ private val theme: Resources.Theme,
+) : QSTileDataToStateMapper<DataSaverTileModel> {
override fun map(config: QSTileConfig, data: DataSaverTileModel): QSTileState =
QSTileState.build(resources, theme, config.uiConfig) {
with(data) {
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/impl/screenrecord/domain/ui/ScreenRecordTileMapper.kt b/packages/SystemUI/src/com/android/systemui/qs/tiles/impl/screenrecord/domain/ui/ScreenRecordTileMapper.kt
index ba06de9..f3136e0 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/impl/screenrecord/domain/ui/ScreenRecordTileMapper.kt
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/impl/screenrecord/domain/ui/ScreenRecordTileMapper.kt
@@ -19,19 +19,21 @@
import android.content.res.Resources
import android.text.TextUtils
import com.android.systemui.common.shared.model.Icon
-import com.android.systemui.dagger.qualifiers.Main
import com.android.systemui.qs.tiles.base.interactor.QSTileDataToStateMapper
import com.android.systemui.qs.tiles.viewmodel.QSTileConfig
import com.android.systemui.qs.tiles.viewmodel.QSTileState
import com.android.systemui.res.R
import com.android.systemui.screenrecord.data.model.ScreenRecordModel
+import com.android.systemui.shade.ShadeDisplayAware
import javax.inject.Inject
/** Maps [ScreenRecordModel] to [QSTileState]. */
class ScreenRecordTileMapper
@Inject
-constructor(@Main private val resources: Resources, private val theme: Resources.Theme) :
- QSTileDataToStateMapper<ScreenRecordModel> {
+constructor(
+ @ShadeDisplayAware private val resources: Resources,
+ private val theme: Resources.Theme,
+) : QSTileDataToStateMapper<ScreenRecordModel> {
override fun map(config: QSTileConfig, data: ScreenRecordModel): QSTileState =
QSTileState.build(resources, theme, config.uiConfig) {
label = resources.getString(R.string.quick_settings_screen_record_label)
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/impl/sensorprivacy/ui/SensorPrivacyToggleTileMapper.kt b/packages/SystemUI/src/com/android/systemui/qs/tiles/impl/sensorprivacy/ui/SensorPrivacyToggleTileMapper.kt
index b4cfec4..73e61b7 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/impl/sensorprivacy/ui/SensorPrivacyToggleTileMapper.kt
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/impl/sensorprivacy/ui/SensorPrivacyToggleTileMapper.kt
@@ -18,12 +18,12 @@
import android.content.res.Resources
import com.android.systemui.common.shared.model.Icon
-import com.android.systemui.dagger.qualifiers.Main
import com.android.systemui.qs.tiles.base.interactor.QSTileDataToStateMapper
import com.android.systemui.qs.tiles.impl.sensorprivacy.domain.model.SensorPrivacyToggleTileModel
import com.android.systemui.qs.tiles.viewmodel.QSTileConfig
import com.android.systemui.qs.tiles.viewmodel.QSTileState
import com.android.systemui.res.R
+import com.android.systemui.shade.ShadeDisplayAware
import dagger.assisted.Assisted
import dagger.assisted.AssistedFactory
import dagger.assisted.AssistedInject
@@ -32,7 +32,7 @@
class SensorPrivacyToggleTileMapper
@AssistedInject
constructor(
- @Main private val resources: Resources,
+ @ShadeDisplayAware private val resources: Resources,
private val theme: Resources.Theme,
@Assisted private val sensorPrivacyTileResources: SensorPrivacyTileResources,
) : QSTileDataToStateMapper<SensorPrivacyToggleTileModel> {
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/impl/uimodenight/domain/UiModeNightTileMapper.kt b/packages/SystemUI/src/com/android/systemui/qs/tiles/impl/uimodenight/domain/UiModeNightTileMapper.kt
index eda8e5c..e9aa46c 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/impl/uimodenight/domain/UiModeNightTileMapper.kt
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/impl/uimodenight/domain/UiModeNightTileMapper.kt
@@ -21,12 +21,12 @@
import android.content.res.Resources.Theme
import android.text.TextUtils
import com.android.systemui.common.shared.model.Icon
-import com.android.systemui.dagger.qualifiers.Main
import com.android.systemui.qs.tiles.base.interactor.QSTileDataToStateMapper
import com.android.systemui.qs.tiles.impl.uimodenight.domain.model.UiModeNightTileModel
import com.android.systemui.qs.tiles.viewmodel.QSTileConfig
import com.android.systemui.qs.tiles.viewmodel.QSTileState
import com.android.systemui.res.R
+import com.android.systemui.shade.ShadeDisplayAware
import java.time.LocalTime
import java.time.format.DateTimeFormatter
import javax.inject.Inject
@@ -34,7 +34,7 @@
/** Maps [UiModeNightTileModel] to [QSTileState]. */
class UiModeNightTileMapper
@Inject
-constructor(@Main private val resources: Resources, private val theme: Theme) :
+constructor(@ShadeDisplayAware private val resources: Resources, private val theme: Theme) :
QSTileDataToStateMapper<UiModeNightTileModel> {
companion object {
val formatter12Hour: DateTimeFormatter = DateTimeFormatter.ofPattern("hh:mm a")
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/impl/uimodenight/domain/interactor/UiModeNightTileDataInteractor.kt b/packages/SystemUI/src/com/android/systemui/qs/tiles/impl/uimodenight/domain/interactor/UiModeNightTileDataInteractor.kt
index 7af3576..925b913 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/impl/uimodenight/domain/interactor/UiModeNightTileDataInteractor.kt
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/impl/uimodenight/domain/interactor/UiModeNightTileDataInteractor.kt
@@ -21,7 +21,6 @@
import android.content.res.Configuration
import android.os.UserHandle
import com.android.systemui.common.coroutine.ConflatedCallbackFlow
-import com.android.systemui.dagger.qualifiers.Application
import com.android.systemui.qs.tiles.base.interactor.DataUpdateTrigger
import com.android.systemui.qs.tiles.base.interactor.QSTileDataInteractor
import com.android.systemui.qs.tiles.impl.uimodenight.domain.model.UiModeNightTileModel
@@ -40,7 +39,7 @@
@Inject
constructor(
@ShadeDisplayAware private val context: Context,
- private val configurationController: ConfigurationController,
+ @ShadeDisplayAware private val configurationController: ConfigurationController,
private val uiModeManager: UiModeManager,
private val batteryController: BatteryController,
private val locationController: LocationController,
@@ -49,7 +48,7 @@
override fun tileData(
user: UserHandle,
- triggers: Flow<DataUpdateTrigger>
+ triggers: Flow<DataUpdateTrigger>,
): Flow<UiModeNightTileModel> =
ConflatedCallbackFlow.conflatedCallbackFlow {
// send initial state
@@ -106,7 +105,7 @@
nightModeCustomType,
use24HourFormat,
customNightModeEnd,
- customNightModeStart
+ customNightModeStart,
)
}
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/impl/work/ui/WorkModeTileMapper.kt b/packages/SystemUI/src/com/android/systemui/qs/tiles/impl/work/ui/WorkModeTileMapper.kt
index a1bc8a8..6a3195a 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/impl/work/ui/WorkModeTileMapper.kt
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/impl/work/ui/WorkModeTileMapper.kt
@@ -21,19 +21,19 @@
import android.content.res.Resources
import android.service.quicksettings.Tile
import com.android.systemui.common.shared.model.Icon
-import com.android.systemui.dagger.qualifiers.Main
import com.android.systemui.qs.tiles.base.interactor.QSTileDataToStateMapper
import com.android.systemui.qs.tiles.impl.work.domain.model.WorkModeTileModel
import com.android.systemui.qs.tiles.viewmodel.QSTileConfig
import com.android.systemui.qs.tiles.viewmodel.QSTileState
import com.android.systemui.res.R
+import com.android.systemui.shade.ShadeDisplayAware
import javax.inject.Inject
/** Maps [WorkModeTileModel] to [QSTileState]. */
class WorkModeTileMapper
@Inject
constructor(
- @Main private val resources: Resources,
+ @ShadeDisplayAware private val resources: Resources,
private val theme: Resources.Theme,
private val devicePolicyManager: DevicePolicyManager,
) : QSTileDataToStateMapper<WorkModeTileModel> {
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/viewmodel/QSTileViewModelAdapter.kt b/packages/SystemUI/src/com/android/systemui/qs/tiles/viewmodel/QSTileViewModelAdapter.kt
index ab3862b..f9a1ad5 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/viewmodel/QSTileViewModelAdapter.kt
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/viewmodel/QSTileViewModelAdapter.kt
@@ -25,6 +25,7 @@
import com.android.systemui.animation.Expandable
import com.android.systemui.common.shared.model.Icon
import com.android.systemui.dagger.qualifiers.Application
+import com.android.systemui.dagger.qualifiers.UiBackground
import com.android.systemui.plugins.qs.QSTile
import com.android.systemui.qs.QSHost
import com.android.systemui.qs.tileimpl.QSTileImpl.DrawableIcon
@@ -35,14 +36,17 @@
import dagger.assisted.AssistedInject
import java.io.PrintWriter
import java.util.concurrent.CopyOnWriteArraySet
+import kotlinx.coroutines.CoroutineDispatcher
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Job
import kotlinx.coroutines.flow.collectIndexed
import kotlinx.coroutines.flow.filterNotNull
+import kotlinx.coroutines.flow.flowOn
import kotlinx.coroutines.flow.launchIn
import kotlinx.coroutines.flow.map
import kotlinx.coroutines.flow.onEach
import kotlinx.coroutines.flow.takeWhile
+import kotlinx.coroutines.launch
// TODO(b/http://b/299909989): Use QSTileViewModel directly after the rollout
class QSTileViewModelAdapter
@@ -51,6 +55,7 @@
@Application private val applicationScope: CoroutineScope,
private val qsHost: QSHost,
@Assisted private val qsTileViewModel: QSTileViewModel,
+ @UiBackground private val uiBgDispatcher: CoroutineDispatcher,
) : QSTile, Dumpable {
private val context
@@ -162,19 +167,25 @@
override fun setListening(client: Any?, listening: Boolean) {
client ?: return
if (listening) {
- val clientWasNotAlreadyListening = listeningClients.add(client)
- if (clientWasNotAlreadyListening && listeningClients.size == 1) {
- stateJob =
- qsTileViewModel.state
- .filterNotNull()
- .map { mapState(context, it, qsTileViewModel.config) }
- .onEach { legacyState ->
- val changed = legacyState.copyTo(cachedState)
- if (changed) {
- callbacks.forEach { it.onStateChanged(legacyState) }
+ applicationScope.launch(uiBgDispatcher) {
+ val shouldStartMappingJob =
+ listeningClients.add(client) // new client
+ && listeningClients.size == 1 // first client
+
+ if (shouldStartMappingJob) {
+ stateJob =
+ qsTileViewModel.state
+ .filterNotNull()
+ .map { mapState(context, it, qsTileViewModel.config) }
+ .onEach { legacyState ->
+ val changed = legacyState.copyTo(cachedState)
+ if (changed) {
+ callbacks.forEach { it.onStateChanged(legacyState) }
+ }
}
- }
- .launchIn(applicationScope)
+ .flowOn(uiBgDispatcher)
+ .launchIn(applicationScope)
+ }
}
} else {
listeningClients.remove(client)
diff --git a/packages/SystemUI/src/com/android/systemui/shade/NotificationPanelViewController.java b/packages/SystemUI/src/com/android/systemui/shade/NotificationPanelViewController.java
index 88522d5..3a6c250 100644
--- a/packages/SystemUI/src/com/android/systemui/shade/NotificationPanelViewController.java
+++ b/packages/SystemUI/src/com/android/systemui/shade/NotificationPanelViewController.java
@@ -172,6 +172,7 @@
import com.android.systemui.shade.data.repository.FlingInfo;
import com.android.systemui.shade.data.repository.ShadeRepository;
import com.android.systemui.shade.domain.interactor.ShadeAnimationInteractor;
+import com.android.systemui.shade.shared.flag.ShadeWindowGoesAround;
import com.android.systemui.shared.system.QuickStepContract;
import com.android.systemui.statusbar.CommandQueue;
import com.android.systemui.statusbar.GestureRecorder;
@@ -2269,7 +2270,11 @@
}
float getDisplayDensity() {
- return mCentralSurfaces.getDisplayDensity();
+ if (ShadeWindowGoesAround.isEnabled()) {
+ return mView.getContext().getResources().getConfiguration().densityDpi;
+ } else {
+ return mCentralSurfaces.getDisplayDensity();
+ }
}
/** Return whether a touch is near the gesture handle at the bottom of screen */
@@ -3830,7 +3835,7 @@
/* screenOnFromTouch=*/ getWakefulness().isAwakeFromTapOrGesture());
// Log collapse gesture if on lock screen.
if (!expand && onKeyguard) {
- float displayDensity = mCentralSurfaces.getDisplayDensity();
+ float displayDensity = getDisplayDensity();
int heightDp = (int) Math.abs((y - mInitialExpandY) / displayDensity);
int velocityDp = (int) Math.abs(vel / displayDensity);
mLockscreenGestureLogger.write(MetricsEvent.ACTION_LS_UNLOCK, heightDp, velocityDp);
diff --git a/packages/SystemUI/src/com/android/systemui/shade/NotificationShadeWindowControllerImpl.java b/packages/SystemUI/src/com/android/systemui/shade/NotificationShadeWindowControllerImpl.java
index 41d56c5..69b3cc8 100644
--- a/packages/SystemUI/src/com/android/systemui/shade/NotificationShadeWindowControllerImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/shade/NotificationShadeWindowControllerImpl.java
@@ -38,10 +38,10 @@
import android.view.View;
import android.view.ViewGroup;
import android.view.WindowInsets;
+import android.view.WindowManager;
import android.view.WindowManager.LayoutParams;
import android.view.WindowManagerGlobal;
-import com.android.app.viewcapture.ViewCaptureAwareWindowManager;
import com.android.internal.annotations.VisibleForTesting;
import com.android.systemui.Dumpable;
import com.android.systemui.Flags;
@@ -102,11 +102,12 @@
private final Context mContext;
private final WindowRootViewComponent.Factory mWindowRootViewComponentFactory;
- private final ViewCaptureAwareWindowManager mWindowManager;
+ private final WindowManager mWindowManager;
private final IActivityManager mActivityManager;
private final DozeParameters mDozeParameters;
private final KeyguardStateController mKeyguardStateController;
private final ShadeWindowLogger mLogger;
+ private final LayoutParams mShadeWindowLayoutParams;
private final LayoutParams mLpChanged;
private final long mLockScreenDisplayTimeout;
private final float mKeyguardPreferredRefreshRate; // takes precedence over max
@@ -148,7 +149,7 @@
public NotificationShadeWindowControllerImpl(
@ShadeDisplayAware Context context,
WindowRootViewComponent.Factory windowRootViewComponentFactory,
- ViewCaptureAwareWindowManager viewCaptureAwareWindowManager,
+ @ShadeDisplayAware WindowManager windowManager,
IActivityManager activityManager,
DozeParameters dozeParameters,
StatusBarStateController statusBarStateController,
@@ -167,14 +168,16 @@
UserTracker userTracker,
NotificationShadeWindowModel notificationShadeWindowModel,
SecureSettings secureSettings,
- Lazy<CommunalInteractor> communalInteractor) {
+ Lazy<CommunalInteractor> communalInteractor,
+ @ShadeDisplayAware LayoutParams shadeWindowLayoutParams) {
mContext = context;
mWindowRootViewComponentFactory = windowRootViewComponentFactory;
- mWindowManager = viewCaptureAwareWindowManager;
+ mWindowManager = windowManager;
mActivityManager = activityManager;
mDozeParameters = dozeParameters;
mKeyguardStateController = keyguardStateController;
mLogger = logger;
+ mShadeWindowLayoutParams = shadeWindowLayoutParams;
mScreenBrightnessDoze = mDozeParameters.getScreenBrightnessDoze();
mLpChanged = new LayoutParams();
mKeyguardViewMediator = keyguardViewMediator;
@@ -271,7 +274,9 @@
// Now that the notification shade encompasses the sliding panel and its
// translucent backdrop, the entire thing is made TRANSLUCENT and is
// hardware-accelerated.
- mLp = ShadeWindowLayoutParams.INSTANCE.create(mContext);
+ // mLP is assigned here (instead of the constructor) as its null value is also used to check
+ // if the shade window has been attached.
+ mLp = mShadeWindowLayoutParams;
mWindowManager.addView(mWindowRootView, mLp);
// We use BEHAVIOR_SHOW_TRANSIENT_BARS_BY_SWIPE here, however, there is special logic in
diff --git a/packages/SystemUI/src/com/android/systemui/shade/ShadeDisplayAwareModule.kt b/packages/SystemUI/src/com/android/systemui/shade/ShadeDisplayAwareModule.kt
index 2cfce68..ff39a3d 100644
--- a/packages/SystemUI/src/com/android/systemui/shade/ShadeDisplayAwareModule.kt
+++ b/packages/SystemUI/src/com/android/systemui/shade/ShadeDisplayAwareModule.kt
@@ -20,6 +20,7 @@
import android.content.res.Resources
import android.view.LayoutInflater
import android.view.WindowManager
+import android.view.WindowManager.LayoutParams
import android.view.WindowManager.LayoutParams.TYPE_NOTIFICATION_SHADE
import com.android.systemui.CoreStartable
import com.android.systemui.common.ui.ConfigurationState
@@ -80,6 +81,13 @@
@Provides
@ShadeDisplayAware
@SysUISingleton
+ fun provideShadeWindowLayoutParams(@ShadeDisplayAware context: Context): LayoutParams {
+ return ShadeWindowLayoutParams.create(context)
+ }
+
+ @Provides
+ @ShadeDisplayAware
+ @SysUISingleton
fun provideShadeWindowManager(
defaultWindowManager: WindowManager,
@ShadeDisplayAware context: Context,
diff --git a/packages/SystemUI/src/com/android/systemui/shade/domain/interactor/ShadeDisplaysInteractor.kt b/packages/SystemUI/src/com/android/systemui/shade/domain/interactor/ShadeDisplaysInteractor.kt
index fb2cbec..3414867 100644
--- a/packages/SystemUI/src/com/android/systemui/shade/domain/interactor/ShadeDisplaysInteractor.kt
+++ b/packages/SystemUI/src/com/android/systemui/shade/domain/interactor/ShadeDisplaysInteractor.kt
@@ -19,6 +19,7 @@
import android.content.Context
import android.util.Log
import android.view.WindowManager
+import android.view.WindowManager.LayoutParams
import androidx.annotation.UiThread
import com.android.app.tracing.coroutines.launchTraced
import com.android.app.tracing.traceSection
@@ -28,7 +29,6 @@
import com.android.systemui.dagger.qualifiers.Main
import com.android.systemui.scene.ui.view.WindowRootView
import com.android.systemui.shade.ShadeDisplayAware
-import com.android.systemui.shade.ShadeWindowLayoutParams
import com.android.systemui.shade.data.repository.ShadeDisplaysRepository
import com.android.systemui.shade.shared.flag.ShadeWindowGoesAround
import com.android.systemui.util.kotlin.getOrNull
@@ -46,14 +46,12 @@
optionalShadeRootView: Optional<WindowRootView>,
private val shadePositionRepository: ShadeDisplaysRepository,
@ShadeDisplayAware private val shadeContext: Context,
+ @ShadeDisplayAware private val shadeLayoutParams: LayoutParams,
@ShadeDisplayAware private val wm: WindowManager,
@Background private val bgScope: CoroutineScope,
@Main private val mainThreadContext: CoroutineContext,
) : CoreStartable {
- private val shadeLayoutParams: WindowManager.LayoutParams =
- ShadeWindowLayoutParams.create(shadeContext)
-
private val shadeRootView =
optionalShadeRootView.getOrNull()
?: error(
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/AssistantFeedbackController.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/AssistantFeedbackController.java
index 24088d2..11ec2ed 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/AssistantFeedbackController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/AssistantFeedbackController.java
@@ -30,6 +30,7 @@
import com.android.internal.R;
import com.android.systemui.dagger.SysUISingleton;
+import com.android.systemui.dagger.qualifiers.Application;
import com.android.systemui.dagger.qualifiers.Main;
import com.android.systemui.statusbar.notification.collection.NotificationEntry;
import com.android.systemui.util.DeviceConfigProxy;
@@ -72,7 +73,7 @@
/** Injected constructor */
@Inject
public AssistantFeedbackController(@Main Handler handler,
- Context context, DeviceConfigProxy proxy) {
+ @Application Context context, DeviceConfigProxy proxy) {
mHandler = handler;
mContext = context;
mDeviceConfigProxy = proxy;
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationSectionsFeatureManager.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationSectionsFeatureManager.kt
index 0569074..91864c22 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationSectionsFeatureManager.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationSectionsFeatureManager.kt
@@ -18,13 +18,14 @@
import android.content.Context
import com.android.systemui.dagger.SysUISingleton
+import com.android.systemui.shade.ShadeDisplayAware
import com.android.systemui.util.Utils
import javax.inject.Inject
@SysUISingleton
class NotificationSectionsFeatureManager
@Inject
-constructor(val context: Context) {
+constructor(@ShadeDisplayAware val context: Context) {
fun isMediaControlsEnabled(): Boolean {
return Utils.useQsMediaPlayer(context)
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/TargetSdkResolver.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/TargetSdkResolver.kt
index 0c49713..0f08ae4 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/TargetSdkResolver.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/TargetSdkResolver.kt
@@ -23,35 +23,37 @@
import android.service.notification.StatusBarNotification
import android.util.Log
import com.android.systemui.dagger.SysUISingleton
+import com.android.systemui.dagger.qualifiers.Application
import com.android.systemui.statusbar.notification.collection.notifcollection.CommonNotifCollection
import com.android.systemui.statusbar.notification.collection.notifcollection.NotifCollectionListener
import com.android.systemui.statusbar.phone.CentralSurfaces
import javax.inject.Inject
@SysUISingleton
-class TargetSdkResolver @Inject constructor(
- private val context: Context
-) {
+class TargetSdkResolver @Inject constructor(@Application private val context: Context) {
fun initialize(collection: CommonNotifCollection) {
- collection.addCollectionListener(object : NotifCollectionListener {
- override fun onEntryBind(entry: NotificationEntry, sbn: StatusBarNotification) {
- entry.targetSdk = resolveNotificationSdk(sbn)
+ collection.addCollectionListener(
+ object : NotifCollectionListener {
+ override fun onEntryBind(entry: NotificationEntry, sbn: StatusBarNotification) {
+ entry.targetSdk = resolveNotificationSdk(sbn)
+ }
}
- })
+ )
}
private fun resolveNotificationSdk(sbn: StatusBarNotification): Int {
- val applicationInfo = getApplicationInfoFromExtras(sbn.notification)
+ val applicationInfo =
+ getApplicationInfoFromExtras(sbn.notification)
?: getApplicationInfoFromPackageManager(sbn)
return applicationInfo?.targetSdkVersion ?: 0
}
private fun getApplicationInfoFromExtras(notification: Notification): ApplicationInfo? =
- notification.extras.getParcelable(
- Notification.EXTRA_BUILDER_APPLICATION_INFO,
- ApplicationInfo::class.java
- )
+ notification.extras.getParcelable(
+ Notification.EXTRA_BUILDER_APPLICATION_INFO,
+ ApplicationInfo::class.java,
+ )
private fun getApplicationInfoFromPackageManager(sbn: StatusBarNotification): ApplicationInfo? {
val pmUser = CentralSurfaces.getPackageManagerForUser(context, sbn.user.identifier)
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/provider/SectionHeaderVisibilityProvider.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/provider/SectionHeaderVisibilityProvider.kt
index 6b70a08..03b38f9 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/provider/SectionHeaderVisibilityProvider.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/provider/SectionHeaderVisibilityProvider.kt
@@ -17,8 +17,9 @@
package com.android.systemui.statusbar.notification.collection.provider
import android.content.Context
-import com.android.systemui.res.R
import com.android.systemui.dagger.SysUISingleton
+import com.android.systemui.res.R
+import com.android.systemui.shade.ShadeDisplayAware
import javax.inject.Inject
/**
@@ -31,9 +32,7 @@
* visibility when it invalidates, and we just store that state here.)
*/
@SysUISingleton
-class SectionHeaderVisibilityProvider @Inject constructor(
- context: Context
-) {
+class SectionHeaderVisibilityProvider @Inject constructor(@ShadeDisplayAware context: Context) {
val neverShowSectionHeaders =
context.resources.getBoolean(R.bool.config_notification_never_show_section_headers)
var sectionHeadersVisible = true
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/render/MediaContainerController.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/render/MediaContainerController.kt
index 70fabc0..c731ac6 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/render/MediaContainerController.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/render/MediaContainerController.kt
@@ -19,15 +19,16 @@
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
-import com.android.systemui.res.R
import com.android.systemui.dagger.SysUISingleton
+import com.android.systemui.res.R
+import com.android.systemui.shade.ShadeDisplayAware
import com.android.systemui.statusbar.notification.stack.MediaContainerView
import javax.inject.Inject
@SysUISingleton
-class MediaContainerController @Inject constructor(
- private val layoutInflater: LayoutInflater
-) : NodeController {
+class MediaContainerController
+@Inject
+constructor(@ShadeDisplayAware private val layoutInflater: LayoutInflater) : NodeController {
override val nodeLabel = "MediaContainer"
var mediaContainerView: MediaContainerView? = null
@@ -42,11 +43,12 @@
parent.removeView(_view)
}
}
- val inflated = layoutInflater.inflate(
+ val inflated =
+ layoutInflater.inflate(
R.layout.keyguard_media_container,
parent,
- false /* attachToRoot */)
- as MediaContainerView
+ false, /* attachToRoot */
+ ) as MediaContainerView
if (oldPos != -1) {
parent.addView(inflated, oldPos)
}
@@ -57,6 +59,8 @@
get() = mediaContainerView!!
override fun offerToKeepInParentForAnimation(): Boolean = false
+
override fun removeFromParentIfKeptForAnimation(): Boolean = false
+
override fun resetKeepInParentForAnimation() {}
-}
\ No newline at end of file
+}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/render/SectionHeaderController.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/render/SectionHeaderController.kt
index 5464d08..37005c1 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/render/SectionHeaderController.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/render/SectionHeaderController.kt
@@ -21,8 +21,9 @@
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
-import com.android.systemui.res.R
import com.android.systemui.plugins.ActivityStarter
+import com.android.systemui.res.R
+import com.android.systemui.shade.ShadeDisplayAware
import com.android.systemui.statusbar.notification.dagger.HeaderClickAction
import com.android.systemui.statusbar.notification.dagger.HeaderText
import com.android.systemui.statusbar.notification.dagger.NodeLabel
@@ -32,30 +33,37 @@
interface SectionHeaderController {
fun reinflateView(parent: ViewGroup)
+
val headerView: SectionHeaderView?
+
fun setClearSectionEnabled(enabled: Boolean)
+
fun setOnClearSectionClickListener(listener: View.OnClickListener)
}
@SectionHeaderScope
-class SectionHeaderNodeControllerImpl @Inject constructor(
+class SectionHeaderNodeControllerImpl
+@Inject
+constructor(
@NodeLabel override val nodeLabel: String,
- private val layoutInflater: LayoutInflater,
+ @ShadeDisplayAware private val layoutInflater: LayoutInflater,
@HeaderText @StringRes private val headerTextResId: Int,
private val activityStarter: ActivityStarter,
- @HeaderClickAction private val clickIntentAction: String
+ @HeaderClickAction private val clickIntentAction: String,
) : NodeController, SectionHeaderController {
private var _view: SectionHeaderView? = null
private var clearAllButtonEnabled = false
private var clearAllClickListener: View.OnClickListener? = null
- private val onHeaderClickListener = View.OnClickListener {
- activityStarter.startActivity(
+ private val onHeaderClickListener =
+ View.OnClickListener {
+ activityStarter.startActivity(
Intent(clickIntentAction),
true /* onlyProvisioned */,
true /* dismissShade */,
- Intent.FLAG_ACTIVITY_SINGLE_TOP)
- }
+ Intent.FLAG_ACTIVITY_SINGLE_TOP,
+ )
+ }
override fun reinflateView(parent: ViewGroup) {
var oldPos = -1
@@ -66,11 +74,12 @@
parent.removeView(_view)
}
}
- val inflated = layoutInflater.inflate(
+ val inflated =
+ layoutInflater.inflate(
R.layout.status_bar_notification_section_header,
parent,
- false /* attachToRoot */)
- as SectionHeaderView
+ false, /* attachToRoot */
+ ) as SectionHeaderView
inflated.setHeaderText(headerTextResId)
inflated.setOnHeaderClickListener(onHeaderClickListener)
clearAllClickListener?.let { inflated.setOnClearAllClickListener(it) }
@@ -100,7 +109,10 @@
override val view: View
get() = _view!!
+
override fun offerToKeepInParentForAnimation(): Boolean = false
+
override fun removeFromParentIfKeptForAnimation(): Boolean = false
+
override fun resetKeepInParentForAnimation() {}
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/headsup/HeadsUpManagerImpl.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/headsup/HeadsUpManagerImpl.java
index 99df9f4..e13baf8 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/headsup/HeadsUpManagerImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/headsup/HeadsUpManagerImpl.java
@@ -42,6 +42,7 @@
import com.android.systemui.plugins.statusbar.StatusBarStateController;
import com.android.systemui.res.R;
import com.android.systemui.scene.shared.flag.SceneContainerFlag;
+import com.android.systemui.shade.ShadeDisplayAware;
import com.android.systemui.shade.domain.interactor.ShadeInteractor;
import com.android.systemui.statusbar.StatusBarState;
import com.android.systemui.statusbar.notification.collection.NotificationEntry;
@@ -189,7 +190,7 @@
KeyguardBypassController bypassController,
GroupMembershipManager groupMembershipManager,
VisualStabilityProvider visualStabilityProvider,
- ConfigurationController configurationController,
+ @ShadeDisplayAware ConfigurationController configurationController,
@Main Handler handler,
GlobalSettings globalSettings,
SystemClock systemClock,
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/icon/ui/viewmodel/NotificationIconContainerAlwaysOnDisplayViewModel.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/icon/ui/viewmodel/NotificationIconContainerAlwaysOnDisplayViewModel.kt
index 8768ea2..f86ae68 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/icon/ui/viewmodel/NotificationIconContainerAlwaysOnDisplayViewModel.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/icon/ui/viewmodel/NotificationIconContainerAlwaysOnDisplayViewModel.kt
@@ -18,11 +18,11 @@
import android.content.res.Resources
import com.android.systemui.dagger.SysUISingleton
import com.android.systemui.dagger.qualifiers.Background
-import com.android.systemui.dagger.qualifiers.Main
import com.android.systemui.keyguard.domain.interactor.KeyguardInteractor
import com.android.systemui.keyguard.domain.interactor.KeyguardTransitionInteractor
import com.android.systemui.keyguard.shared.model.KeyguardState
import com.android.systemui.res.R
+import com.android.systemui.shade.ShadeDisplayAware
import com.android.systemui.shade.domain.interactor.ShadeInteractor
import com.android.systemui.statusbar.notification.icon.domain.interactor.AlwaysOnDisplayNotificationIconsInteractor
import javax.inject.Inject
@@ -44,17 +44,16 @@
iconsInteractor: AlwaysOnDisplayNotificationIconsInteractor,
keyguardInteractor: KeyguardInteractor,
keyguardTransitionInteractor: KeyguardTransitionInteractor,
- @Main resources: Resources,
+ @ShadeDisplayAware resources: Resources,
shadeInteractor: ShadeInteractor,
) {
private val maxIcons = resources.getInteger(R.integer.max_notif_icons_on_aod)
/** Are changes to the icon container animated? */
val areContainerChangesAnimated: Flow<Boolean> =
- combine(
- shadeInteractor.isShadeTouchable,
- keyguardInteractor.isKeyguardVisible,
- ) { panelTouchesEnabled, isKeyguardVisible ->
+ combine(shadeInteractor.isShadeTouchable, keyguardInteractor.isKeyguardVisible) {
+ panelTouchesEnabled,
+ isKeyguardVisible ->
panelTouchesEnabled && isKeyguardVisible
}
.flowOn(bgContext)
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/promoted/PromotedNotificationContentExtractor.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/promoted/PromotedNotificationContentExtractor.kt
index f400d60..38eaf27 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/promoted/PromotedNotificationContentExtractor.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/promoted/PromotedNotificationContentExtractor.kt
@@ -27,6 +27,7 @@
import android.app.Notification.ProgressStyle
import android.content.Context
import com.android.systemui.dagger.SysUISingleton
+import com.android.systemui.shade.ShadeDisplayAware
import com.android.systemui.statusbar.notification.collection.NotificationEntry
import com.android.systemui.statusbar.notification.promoted.shared.model.PromotedNotificationContentModel
import com.android.systemui.statusbar.notification.promoted.shared.model.PromotedNotificationContentModel.Style
@@ -38,7 +39,7 @@
@Inject
constructor(
private val promotedNotificationsProvider: PromotedNotificationsProvider,
- private val context: Context,
+ @ShadeDisplayAware private val context: Context,
private val logger: PromotedNotificationLogger,
) {
fun extractContent(
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationGutsManager.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationGutsManager.java
index ea50874..9712db8 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationGutsManager.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationGutsManager.java
@@ -59,6 +59,7 @@
import com.android.systemui.scene.domain.interactor.WindowRootViewVisibilityInteractor;
import com.android.systemui.settings.UserContextProvider;
import com.android.systemui.shade.ShadeController;
+import com.android.systemui.shade.ShadeDisplayAware;
import com.android.systemui.statusbar.NotificationLockscreenUserManager;
import com.android.systemui.statusbar.NotificationPresenter;
import com.android.systemui.statusbar.StatusBarState;
@@ -134,7 +135,8 @@
private final ActivityStarter mActivityStarter;
@Inject
- public NotificationGutsManager(Context context,
+ public NotificationGutsManager(
+ @ShadeDisplayAware Context context,
@Main Handler mainHandler,
@Background Handler bgHandler,
JavaAdapter javaAdapter,
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/AmbientState.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/AmbientState.java
index ad36117..64ca815 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/AmbientState.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/AmbientState.java
@@ -30,6 +30,7 @@
import com.android.systemui.dump.DumpManager;
import com.android.systemui.res.R;
import com.android.systemui.scene.shared.flag.SceneContainerFlag;
+import com.android.systemui.shade.ShadeDisplayAware;
import com.android.systemui.shade.transition.LargeScreenShadeInterpolator;
import com.android.systemui.statusbar.NotificationShelf;
import com.android.systemui.statusbar.StatusBarState;
@@ -297,7 +298,7 @@
@Inject
public AmbientState(
- @NonNull Context context,
+ @NonNull @ShadeDisplayAware Context context,
@NonNull DumpManager dumpManager,
@NonNull SectionProvider sectionProvider,
@NonNull BypassController bypassController,
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayoutController.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayoutController.java
index e89645d..ba707a5 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayoutController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayoutController.java
@@ -86,6 +86,7 @@
import com.android.systemui.scene.ui.view.WindowRootView;
import com.android.systemui.shade.QSHeaderBoundsProvider;
import com.android.systemui.shade.ShadeController;
+import com.android.systemui.shade.ShadeDisplayAware;
import com.android.systemui.shade.ShadeViewController;
import com.android.systemui.statusbar.CommandQueue;
import com.android.systemui.statusbar.LockscreenShadeTransitionController;
@@ -734,7 +735,7 @@
TunerService tunerService,
DeviceProvisionedController deviceProvisionedController,
DynamicPrivacyController dynamicPrivacyController,
- ConfigurationController configurationController,
+ @ShadeDisplayAware ConfigurationController configurationController,
SysuiStatusBarStateController statusBarStateController,
KeyguardMediaController keyguardMediaController,
KeyguardBypassController keyguardBypassController,
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationStackSizeCalculator.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationStackSizeCalculator.kt
index 5dff812..a96d972 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationStackSizeCalculator.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationStackSizeCalculator.kt
@@ -22,9 +22,9 @@
import androidx.annotation.VisibleForTesting
import com.android.systemui.dagger.SysUISingleton
import com.android.systemui.dagger.qualifiers.Application
-import com.android.systemui.dagger.qualifiers.Main
import com.android.systemui.media.controls.domain.pipeline.MediaDataManager
import com.android.systemui.res.R
+import com.android.systemui.shade.ShadeDisplayAware
import com.android.systemui.statusbar.LockscreenShadeTransitionController
import com.android.systemui.statusbar.StatusBarState.KEYGUARD
import com.android.systemui.statusbar.SysuiStatusBarStateController
@@ -60,7 +60,7 @@
private val statusBarStateController: SysuiStatusBarStateController,
private val lockscreenShadeTransitionController: LockscreenShadeTransitionController,
private val mediaDataManager: MediaDataManager,
- @Main private val resources: Resources,
+ @ShadeDisplayAware private val resources: Resources,
private val splitShadeStateController: SplitShadeStateController,
private val seenNotificationsInteractor: SeenNotificationsInteractor,
@Application private val scope: CoroutineScope,
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationSwipeHelper.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationSwipeHelper.java
index 0e94ca35..5045744 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationSwipeHelper.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationSwipeHelper.java
@@ -40,6 +40,7 @@
import com.android.systemui.plugins.FalsingManager;
import com.android.systemui.plugins.statusbar.NotificationMenuRowPlugin;
import com.android.systemui.plugins.statusbar.NotificationSwipeActionHelper;
+import com.android.systemui.shade.ShadeDisplayAware;
import com.android.systemui.statusbar.NotificationShelf;
import com.android.systemui.statusbar.notification.SourceType;
import com.android.systemui.statusbar.notification.row.ExpandableNotificationRow;
@@ -560,7 +561,7 @@
private NotificationRoundnessManager mNotificationRoundnessManager;
@Inject
- Builder(@Main Resources resources, ViewConfiguration viewConfiguration,
+ Builder(@ShadeDisplayAware Resources resources, ViewConfiguration viewConfiguration,
DumpManager dumpManager,
FalsingManager falsingManager, FeatureFlags featureFlags,
NotificationRoundnessManager notificationRoundnessManager) {
diff --git a/packages/SystemUI/src/com/android/systemui/theme/ThemeOverlayController.java b/packages/SystemUI/src/com/android/systemui/theme/ThemeOverlayController.java
index 1c3fece..28cf78f 100644
--- a/packages/SystemUI/src/com/android/systemui/theme/ThemeOverlayController.java
+++ b/packages/SystemUI/src/com/android/systemui/theme/ThemeOverlayController.java
@@ -149,7 +149,8 @@
private double mContrast = 0.0;
// Theme variant: Vibrant, Tonal, Expressive, etc
@VisibleForTesting
- protected Style mThemeStyle = Style.TONAL_SPOT;
+ @Style.Type
+ protected int mThemeStyle = Style.TONAL_SPOT;
// Accent colors overlay
private FabricatedOverlay mSecondaryOverlay;
// Neutral system colors overlay
@@ -826,15 +827,16 @@
}
- private Style fetchThemeStyleFromSetting() {
+ @Style.Type
+ private int fetchThemeStyleFromSetting() {
// Allow-list of Style objects that can be created from a setting string, i.e. can be
// used as a system-wide theme.
// - Content intentionally excluded, intended for media player, not system-wide
- List<Style> validStyles = new ArrayList<>(Arrays.asList(Style.EXPRESSIVE, Style.SPRITZ,
- Style.TONAL_SPOT, Style.FRUIT_SALAD, Style.RAINBOW, Style.VIBRANT,
+ @Style.Type List<Integer> validStyles = new ArrayList<>(Arrays.asList(Style.EXPRESSIVE,
+ Style.SPRITZ, Style.TONAL_SPOT, Style.FRUIT_SALAD, Style.RAINBOW, Style.VIBRANT,
Style.MONOCHROMATIC));
- Style style = mThemeStyle;
+ @Style.Type int style = mThemeStyle;
final String overlayPackageJson = mSecureSettings.getStringForUser(
Settings.Secure.THEME_CUSTOMIZATION_OVERLAY_PACKAGES,
mUserTracker.getUserId());
diff --git a/packages/SystemUI/src/com/android/systemui/wallet/controller/QuickAccessWalletController.java b/packages/SystemUI/src/com/android/systemui/wallet/controller/QuickAccessWalletController.java
index 1d32a4f..389b6fb 100644
--- a/packages/SystemUI/src/com/android/systemui/wallet/controller/QuickAccessWalletController.java
+++ b/packages/SystemUI/src/com/android/systemui/wallet/controller/QuickAccessWalletController.java
@@ -32,6 +32,7 @@
import android.service.quickaccesswallet.GetWalletCardsRequest;
import android.service.quickaccesswallet.QuickAccessWalletClient;
import android.service.quickaccesswallet.QuickAccessWalletClientImpl;
+import android.service.quickaccesswallet.WalletCard;
import android.util.Log;
import com.android.systemui.animation.ActivityTransitionAnimator;
@@ -268,6 +269,23 @@
});
}
+ /**
+ * Starts the {@link android.app.PendingIntent} for a {@link WalletCard}.
+ *
+ * This should be used to open a selected card from the QuickAccessWallet UI or
+ * the settings tile.
+ *
+ * @param activityStarter an {@link ActivityStarter} to launch the Intent or PendingIntent.
+ * @param animationController an {@link ActivityTransitionAnimator.Controller} to provide a
+ * smooth animation for the activity launch.
+ */
+ public void startWalletCardPendingIntent(WalletCard card,
+ ActivityStarter activityStarter,
+ ActivityTransitionAnimator.Controller animationController) {
+ activityStarter.postStartActivityDismissingKeyguard(
+ card.getPendingIntent(), animationController);
+ }
+
private Intent getSysUiWalletIntent() {
return new Intent(mContext, WalletActivity.class)
.setAction(Intent.ACTION_VIEW);
diff --git a/packages/SystemUI/tests/src/com/android/systemui/communal/data/backup/CommunalBackupHelperTest.kt b/packages/SystemUI/tests/src/com/android/systemui/communal/data/backup/CommunalBackupHelperTest.kt
index 4ca84c58..50fad3b 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/communal/data/backup/CommunalBackupHelperTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/communal/data/backup/CommunalBackupHelperTest.kt
@@ -32,6 +32,7 @@
import com.android.systemui.communal.data.db.CommunalDatabase
import com.android.systemui.communal.data.db.CommunalWidgetDao
import com.android.systemui.communal.proto.toCommunalHubState
+import com.android.systemui.communal.shared.model.SpanValue
import com.android.systemui.lifecycle.InstantTaskExecutorRule
import com.google.common.truth.Truth.assertThat
import java.io.File
@@ -120,21 +121,32 @@
componentName = "com.android.fakePackage1/fakeWidget1",
rank = 0,
userSerialNumber = 0,
+ spanY = SpanValue.Responsive(1),
),
FakeWidgetMetadata(
widgetId = 12,
componentName = "com.android.fakePackage2/fakeWidget2",
rank = 1,
userSerialNumber = 0,
+ spanY = SpanValue.Responsive(2),
),
FakeWidgetMetadata(
widgetId = 13,
componentName = "com.android.fakePackage3/fakeWidget3",
rank = 2,
userSerialNumber = 10,
+ spanY = SpanValue.Responsive(3),
),
)
- .onEach { dao.addWidget(it.widgetId, it.componentName, it.rank, it.userSerialNumber) }
+ .onEach {
+ dao.addWidget(
+ widgetId = it.widgetId,
+ componentName = it.componentName,
+ rank = it.rank,
+ userSerialNumber = it.userSerialNumber,
+ spanY = it.spanY,
+ )
+ }
}
private fun getBackupDataInputStream(): BackupDataInputStream {
diff --git a/packages/SystemUI/tests/src/com/android/systemui/communal/data/backup/CommunalBackupUtilsTest.kt b/packages/SystemUI/tests/src/com/android/systemui/communal/data/backup/CommunalBackupUtilsTest.kt
index edc8c83..d31e466 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/communal/data/backup/CommunalBackupUtilsTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/communal/data/backup/CommunalBackupUtilsTest.kt
@@ -23,6 +23,9 @@
import com.android.systemui.communal.data.db.CommunalDatabase
import com.android.systemui.communal.data.db.CommunalWidgetDao
import com.android.systemui.communal.nano.CommunalHubState
+import com.android.systemui.communal.shared.model.SpanValue
+import com.android.systemui.communal.shared.model.toFixed
+import com.android.systemui.communal.shared.model.toResponsive
import com.android.systemui.lifecycle.InstantTaskExecutorRule
import com.google.common.truth.Correspondence
import com.google.common.truth.Truth.assertThat
@@ -71,22 +74,25 @@
componentName = "com.android.fakePackage1/fakeWidget1",
rank = 0,
userSerialNumber = 0,
+ spanY = SpanValue.Responsive(1),
),
FakeWidgetMetadata(
widgetId = 12,
componentName = "com.android.fakePackage2/fakeWidget2",
rank = 1,
userSerialNumber = 0,
+ spanY = SpanValue.Responsive(2),
),
FakeWidgetMetadata(
widgetId = 13,
componentName = "com.android.fakePackage3/fakeWidget3",
rank = 2,
userSerialNumber = 10,
+ spanY = SpanValue.Responsive(3),
),
)
expectedWidgets.forEach {
- dao.addWidget(it.widgetId, it.componentName, it.rank, it.userSerialNumber)
+ dao.addWidget(it.widgetId, it.componentName, it.rank, it.userSerialNumber, it.spanY)
}
// Get communal hub state
@@ -150,6 +156,7 @@
val componentName: String,
val rank: Int,
val userSerialNumber: Int,
+ val spanY: SpanValue,
)
companion object {
@@ -163,7 +170,9 @@
actual?.widgetId == expected?.widgetId &&
actual?.componentName == expected?.componentName &&
actual?.rank == expected?.rank &&
- actual?.userSerialNumber == expected?.userSerialNumber
+ actual?.userSerialNumber == expected?.userSerialNumber &&
+ actual?.spanY == expected?.spanY?.toFixed()?.value &&
+ actual?.spanYNew == expected?.spanY?.toResponsive()?.value
},
"represents",
)
diff --git a/packages/SystemUI/tests/src/com/android/systemui/communal/data/db/CommunalDatabaseMigrationsTest.kt b/packages/SystemUI/tests/src/com/android/systemui/communal/data/db/CommunalDatabaseMigrationsTest.kt
index 7d5a334..1466e32 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/communal/data/db/CommunalDatabaseMigrationsTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/communal/data/db/CommunalDatabaseMigrationsTest.kt
@@ -22,6 +22,8 @@
import androidx.test.filters.SmallTest
import androidx.test.platform.app.InstrumentationRegistry
import com.android.systemui.SysuiTestCase
+import com.android.systemui.communal.shared.model.SpanValue
+import com.android.systemui.communal.shared.model.toResponsive
import com.android.systemui.lifecycle.InstantTaskExecutorRule
import com.google.common.truth.Truth.assertThat
import org.junit.Rule
@@ -173,6 +175,49 @@
databaseV4.verifyWidgetsV4(fakeWidgetsV3.map { it.getV4() })
}
+ @Test
+ fun migrate4To5_addNewSpanYColumn() {
+ val databaseV4 = migrationTestHelper.createDatabase(DATABASE_NAME, version = 4)
+
+ val fakeWidgetsV4 =
+ listOf(
+ FakeCommunalWidgetItemV4(
+ widgetId = 1,
+ componentName = "test_widget_1",
+ itemId = 11,
+ userSerialNumber = 0,
+ spanY = 3,
+ ),
+ FakeCommunalWidgetItemV4(
+ widgetId = 2,
+ componentName = "test_widget_2",
+ itemId = 12,
+ userSerialNumber = 10,
+ spanY = 6,
+ ),
+ FakeCommunalWidgetItemV4(
+ widgetId = 3,
+ componentName = "test_widget_3",
+ itemId = 13,
+ userSerialNumber = 0,
+ spanY = 0,
+ ),
+ )
+ databaseV4.insertWidgetsV4(fakeWidgetsV4)
+
+ databaseV4.verifyWidgetsV4(fakeWidgetsV4)
+
+ val databaseV5 =
+ migrationTestHelper.runMigrationsAndValidate(
+ name = DATABASE_NAME,
+ version = 5,
+ validateDroppedTables = false,
+ CommunalDatabase.MIGRATION_4_5,
+ )
+
+ databaseV5.verifyWidgetsV5(fakeWidgetsV4.map { it.getV5() })
+ }
+
private fun SupportSQLiteDatabase.insertWidgetsV1(widgets: List<FakeCommunalWidgetItemV1>) {
widgets.forEach { widget ->
execSQL(
@@ -198,6 +243,24 @@
}
}
+ private fun SupportSQLiteDatabase.insertWidgetsV4(widgets: List<FakeCommunalWidgetItemV4>) {
+ widgets.forEach { widget ->
+ execSQL(
+ "INSERT INTO communal_widget_table(" +
+ "widget_id, " +
+ "component_name, " +
+ "item_id, " +
+ "user_serial_number, " +
+ "span_y) " +
+ "VALUES(${widget.widgetId}, " +
+ "'${widget.componentName}', " +
+ "${widget.itemId}, " +
+ "${widget.userSerialNumber}," +
+ "${widget.spanY})"
+ )
+ }
+ }
+
private fun SupportSQLiteDatabase.verifyWidgetsV1(widgets: List<FakeCommunalWidgetItemV1>) {
val cursor = query("SELECT * FROM communal_widget_table")
assertThat(cursor.moveToFirst()).isTrue()
@@ -270,6 +333,27 @@
assertThat(cursor.isAfterLast).isTrue()
}
+ private fun SupportSQLiteDatabase.verifyWidgetsV5(widgets: List<FakeCommunalWidgetItemV5>) {
+ val cursor = query("SELECT * FROM communal_widget_table")
+ assertThat(cursor.moveToFirst()).isTrue()
+
+ widgets.forEach { widget ->
+ assertThat(cursor.getInt(cursor.getColumnIndex("widget_id"))).isEqualTo(widget.widgetId)
+ assertThat(cursor.getString(cursor.getColumnIndex("component_name")))
+ .isEqualTo(widget.componentName)
+ assertThat(cursor.getInt(cursor.getColumnIndex("item_id"))).isEqualTo(widget.itemId)
+ assertThat(cursor.getInt(cursor.getColumnIndex("user_serial_number")))
+ .isEqualTo(widget.userSerialNumber)
+ assertThat(cursor.getInt(cursor.getColumnIndex("span_y"))).isEqualTo(widget.spanY)
+ assertThat(cursor.getInt(cursor.getColumnIndex("span_y_new")))
+ .isEqualTo(widget.spanYNew)
+
+ cursor.moveToNext()
+ }
+
+ assertThat(cursor.isAfterLast).isTrue()
+ }
+
private fun SupportSQLiteDatabase.insertRanks(ranks: List<FakeCommunalItemRank>) {
ranks.forEach { rank ->
execSQL("INSERT INTO communal_item_rank_table(rank) VALUES(${rank.rank})")
@@ -334,6 +418,27 @@
val spanY: Int,
)
+ private fun FakeCommunalWidgetItemV4.getV5(): FakeCommunalWidgetItemV5 {
+ val spanYFixed = SpanValue.Fixed(spanY)
+ return FakeCommunalWidgetItemV5(
+ widgetId = widgetId,
+ componentName = componentName,
+ itemId = itemId,
+ userSerialNumber = userSerialNumber,
+ spanY = spanYFixed.value,
+ spanYNew = spanYFixed.toResponsive().value,
+ )
+ }
+
+ private data class FakeCommunalWidgetItemV5(
+ val widgetId: Int,
+ val componentName: String,
+ val itemId: Int,
+ val userSerialNumber: Int,
+ val spanY: Int,
+ val spanYNew: Int,
+ )
+
private data class FakeCommunalItemRank(val rank: Int)
companion object {
diff --git a/packages/SystemUI/tests/src/com/android/systemui/communal/data/db/CommunalWidgetDaoTest.kt b/packages/SystemUI/tests/src/com/android/systemui/communal/data/db/CommunalWidgetDaoTest.kt
index 2312bbd..2acb775 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/communal/data/db/CommunalWidgetDaoTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/communal/data/db/CommunalWidgetDaoTest.kt
@@ -22,7 +22,7 @@
import androidx.test.filters.SmallTest
import com.android.systemui.SysuiTestCase
import com.android.systemui.communal.nano.CommunalHubState
-import com.android.systemui.communal.shared.model.CommunalContentSize
+import com.android.systemui.communal.shared.model.SpanValue
import com.android.systemui.coroutines.collectLastValue
import com.android.systemui.lifecycle.InstantTaskExecutorRule
import com.google.common.truth.Truth.assertThat
@@ -68,12 +68,13 @@
@Test
fun addWidget_readValueInDb() =
testScope.runTest {
- val (widgetId, provider, rank, userSerialNumber) = widgetInfo1
+ val (widgetId, provider, rank, userSerialNumber, spanY) = widgetInfo1
communalWidgetDao.addWidget(
widgetId = widgetId,
provider = provider,
rank = rank,
userSerialNumber = userSerialNumber,
+ spanY = spanY,
)
val entry = communalWidgetDao.getWidgetByIdNow(id = 1)
assertThat(entry).isEqualTo(communalWidgetItemEntry1)
@@ -82,12 +83,13 @@
@Test
fun deleteWidget_notInDb_returnsFalse() =
testScope.runTest {
- val (widgetId, provider, rank, userSerialNumber) = widgetInfo1
+ val (widgetId, provider, rank, userSerialNumber, spanY) = widgetInfo1
communalWidgetDao.addWidget(
widgetId = widgetId,
provider = provider,
rank = rank,
userSerialNumber = userSerialNumber,
+ spanY = spanY,
)
assertThat(communalWidgetDao.deleteWidgetById(widgetId = 123)).isFalse()
}
@@ -98,12 +100,13 @@
val widgetsToAdd = listOf(widgetInfo1, widgetInfo2)
val widgets = collectLastValue(communalWidgetDao.getWidgets())
widgetsToAdd.forEach {
- val (widgetId, provider, rank, userSerialNumber) = it
+ val (widgetId, provider, rank, userSerialNumber, spanY) = it
communalWidgetDao.addWidget(
widgetId = widgetId,
provider = provider,
rank = rank,
userSerialNumber = userSerialNumber,
+ spanY = spanY,
)
}
assertThat(widgets())
@@ -126,11 +129,12 @@
// Add widgets one by one without specifying rank
val widgetsToAdd = listOf(widgetInfo1, widgetInfo2, widgetInfo3)
widgetsToAdd.forEach {
- val (widgetId, provider, _, userSerialNumber) = it
+ val (widgetId, provider, _, userSerialNumber, spanY) = it
communalWidgetDao.addWidget(
widgetId = widgetId,
provider = provider,
userSerialNumber = userSerialNumber,
+ spanY = spanY,
)
}
@@ -153,12 +157,13 @@
val widgets = collectLastValue(communalWidgetDao.getWidgets())
widgetsToAdd.forEach {
- val (widgetId, provider, rank, userSerialNumber) = it
+ val (widgetId, provider, rank, userSerialNumber, spanY) = it
communalWidgetDao.addWidget(
widgetId = widgetId,
provider = provider,
rank = rank,
userSerialNumber = userSerialNumber,
+ spanY = spanY,
)
}
assertThat(widgets())
@@ -180,12 +185,13 @@
val widgets = collectLastValue(communalWidgetDao.getWidgets())
widgetsToAdd.forEach {
- val (widgetId, provider, rank, userSerialNumber) = it
+ val (widgetId, provider, rank, userSerialNumber, spanY) = it
communalWidgetDao.addWidget(
widgetId = widgetId,
provider = provider,
rank = rank,
userSerialNumber = userSerialNumber,
+ spanY = spanY,
)
}
assertThat(widgets())
@@ -217,12 +223,13 @@
val widgets = collectLastValue(communalWidgetDao.getWidgets())
existingWidgets.forEach {
- val (widgetId, provider, rank, userSerialNumber) = it
+ val (widgetId, provider, rank, userSerialNumber, spanY) = it
communalWidgetDao.addWidget(
widgetId = widgetId,
provider = provider,
rank = rank,
userSerialNumber = userSerialNumber,
+ spanY = spanY,
)
}
assertThat(widgets())
@@ -242,6 +249,7 @@
provider = ComponentName("pk_name", "cls_name_4"),
rank = 1,
userSerialNumber = 0,
+ spanY = SpanValue.Responsive(1),
)
val newRankEntry = CommunalItemRank(uid = 4L, rank = 1)
@@ -253,6 +261,7 @@
itemId = 4L,
userSerialNumber = 0,
spanY = 3,
+ spanYNew = 1,
)
assertThat(widgets())
.containsExactly(
@@ -279,21 +288,21 @@
provider = ComponentName("pkg_name", "cls_name_1"),
rank = 0,
userSerialNumber = 0,
- spanY = CommunalContentSize.FULL.span,
+ spanY = SpanValue.Responsive(1),
)
communalWidgetDao.addWidget(
widgetId = 2,
provider = ComponentName("pkg_name", "cls_name_2"),
rank = 1,
userSerialNumber = 0,
- spanY = CommunalContentSize.HALF.span,
+ spanY = SpanValue.Responsive(2),
)
communalWidgetDao.addWidget(
widgetId = 3,
provider = ComponentName("pkg_name", "cls_name_3"),
rank = 2,
userSerialNumber = 0,
- spanY = CommunalContentSize.THIRD.span,
+ spanY = SpanValue.Fixed(3),
)
// Verify that the widgets have the correct spanY values
@@ -306,7 +315,8 @@
componentName = "pkg_name/cls_name_1",
itemId = 1L,
userSerialNumber = 0,
- spanY = CommunalContentSize.FULL.span,
+ spanY = 3,
+ spanYNew = 1,
),
CommunalItemRank(uid = 2L, rank = 1),
CommunalWidgetItem(
@@ -315,7 +325,8 @@
componentName = "pkg_name/cls_name_2",
itemId = 2L,
userSerialNumber = 0,
- spanY = CommunalContentSize.HALF.span,
+ spanY = 6,
+ spanYNew = 2,
),
CommunalItemRank(uid = 3L, rank = 2),
CommunalWidgetItem(
@@ -324,7 +335,8 @@
componentName = "pkg_name/cls_name_3",
itemId = 3L,
userSerialNumber = 0,
- spanY = CommunalContentSize.THIRD.span,
+ spanY = 3,
+ spanYNew = 1,
),
)
.inOrder()
@@ -352,7 +364,8 @@
componentName = fakeWidget.componentName,
itemId = rank.uid,
userSerialNumber = fakeWidget.userSerialNumber,
- spanY = 3,
+ spanY = fakeWidget.spanY.coerceAtLeast(3),
+ spanYNew = fakeWidget.spanYNew.coerceAtLeast(1),
)
expected[rank] = widget
}
@@ -366,6 +379,7 @@
provider = metadata.provider,
rank = rank ?: metadata.rank,
userSerialNumber = metadata.userSerialNumber,
+ spanY = metadata.spanY,
)
}
@@ -374,6 +388,7 @@
val provider: ComponentName,
val rank: Int,
val userSerialNumber: Int,
+ val spanY: SpanValue,
)
companion object {
@@ -383,6 +398,7 @@
provider = ComponentName("pk_name", "cls_name_1"),
rank = 0,
userSerialNumber = 0,
+ spanY = SpanValue.Responsive(1),
)
val widgetInfo2 =
FakeWidgetMetadata(
@@ -390,6 +406,7 @@
provider = ComponentName("pk_name", "cls_name_2"),
rank = 1,
userSerialNumber = 0,
+ spanY = SpanValue.Responsive(1),
)
val widgetInfo3 =
FakeWidgetMetadata(
@@ -397,6 +414,7 @@
provider = ComponentName("pk_name", "cls_name_3"),
rank = 2,
userSerialNumber = 10,
+ spanY = SpanValue.Responsive(1),
)
val communalItemRankEntry1 = CommunalItemRank(uid = 1L, rank = widgetInfo1.rank)
val communalItemRankEntry2 = CommunalItemRank(uid = 2L, rank = widgetInfo2.rank)
@@ -409,6 +427,7 @@
itemId = communalItemRankEntry1.uid,
userSerialNumber = widgetInfo1.userSerialNumber,
spanY = 3,
+ spanYNew = 1,
)
val communalWidgetItemEntry2 =
CommunalWidgetItem(
@@ -418,6 +437,7 @@
itemId = communalItemRankEntry2.uid,
userSerialNumber = widgetInfo2.userSerialNumber,
spanY = 3,
+ spanYNew = 1,
)
val communalWidgetItemEntry3 =
CommunalWidgetItem(
@@ -427,6 +447,7 @@
itemId = communalItemRankEntry3.uid,
userSerialNumber = widgetInfo3.userSerialNumber,
spanY = 3,
+ spanYNew = 1,
)
val fakeState =
CommunalHubState().apply {
@@ -437,12 +458,14 @@
componentName = "pk_name/fake_widget_1"
rank = 1
userSerialNumber = 0
+ spanY = 3
},
CommunalHubState.CommunalWidgetItem().apply {
widgetId = 2
componentName = "pk_name/fake_widget_2"
rank = 2
userSerialNumber = 10
+ spanYNew = 1
},
)
.toTypedArray()
diff --git a/packages/SystemUI/tests/src/com/android/systemui/keyguard/KeyguardViewMediatorTest.java b/packages/SystemUI/tests/src/com/android/systemui/keyguard/KeyguardViewMediatorTest.java
index 492d5f3..194f456 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/keyguard/KeyguardViewMediatorTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/keyguard/KeyguardViewMediatorTest.java
@@ -278,7 +278,8 @@
mUserTracker,
mKosmos.getNotificationShadeWindowModel(),
mSecureSettings,
- mKosmos::getCommunalInteractor);
+ mKosmos::getCommunalInteractor,
+ mKosmos.getShadeLayoutParams());
mFeatureFlags = new FakeFeatureFlags();
mSetFlagsRule.disableFlags(FLAG_KEYGUARD_WM_STATE_REFACTOR);
diff --git a/packages/SystemUI/tests/src/com/android/systemui/wmshell/BubblesTest.java b/packages/SystemUI/tests/src/com/android/systemui/wmshell/BubblesTest.java
index eb91b1e..df561ab 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/wmshell/BubblesTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/wmshell/BubblesTest.java
@@ -444,7 +444,8 @@
mUserTracker,
mNotificationShadeWindowModel,
new FakeSettings(),
- mKosmos::getCommunalInteractor
+ mKosmos::getCommunalInteractor,
+ mKosmos.getShadeLayoutParams()
);
mNotificationShadeWindowController.fetchWindowRootView();
mNotificationShadeWindowController.attach();
diff --git a/packages/SystemUI/tests/utils/src/android/content/res/ResourcesKosmos.kt b/packages/SystemUI/tests/utils/src/android/content/res/ResourcesKosmos.kt
index 5686764..74330c1 100644
--- a/packages/SystemUI/tests/utils/src/android/content/res/ResourcesKosmos.kt
+++ b/packages/SystemUI/tests/utils/src/android/content/res/ResourcesKosmos.kt
@@ -18,5 +18,8 @@
import android.content.applicationContext
import com.android.systemui.kosmos.Kosmos
+import org.mockito.Mockito.mock
var Kosmos.mainResources: Resources by Kosmos.Fixture { applicationContext.resources }
+
+var Kosmos.mockResources: Resources by Kosmos.Fixture { mock(Resources::class.java) }
diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/SysuiTestCase.java b/packages/SystemUI/tests/utils/src/com/android/systemui/SysuiTestCase.java
index 153a8be..3e44364 100644
--- a/packages/SystemUI/tests/utils/src/com/android/systemui/SysuiTestCase.java
+++ b/packages/SystemUI/tests/utils/src/com/android/systemui/SysuiTestCase.java
@@ -118,6 +118,7 @@
android.net.platform.flags.Flags.class,
android.os.Flags.class,
android.service.controls.flags.Flags.class,
+ android.service.quickaccesswallet.Flags.class,
com.android.internal.telephony.flags.Flags.class,
com.android.server.notification.Flags.class,
com.android.systemui.Flags.class);
diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/communal/data/repository/FakeCommunalWidgetRepository.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/communal/data/repository/FakeCommunalWidgetRepository.kt
index 3b175853de7..1f7f3bc 100644
--- a/packages/SystemUI/tests/utils/src/com/android/systemui/communal/data/repository/FakeCommunalWidgetRepository.kt
+++ b/packages/SystemUI/tests/utils/src/com/android/systemui/communal/data/repository/FakeCommunalWidgetRepository.kt
@@ -55,7 +55,7 @@
rank: Int = 0,
category: Int = AppWidgetProviderInfo.WIDGET_CATEGORY_KEYGUARD,
userId: Int = 0,
- spanY: Int = CommunalContentSize.HALF.span,
+ spanY: Int = CommunalContentSize.FixedSize.HALF.span,
) {
fakeDatabase[appWidgetId] =
CommunalWidgetContentModel.Available(
@@ -87,7 +87,7 @@
componentName = ComponentName.unflattenFromString(componentName)!!,
icon = icon,
user = UserHandle(userId),
- spanY = CommunalContentSize.HALF.span,
+ spanY = CommunalContentSize.FixedSize.HALF.span,
)
updateListFromDatabase()
}
@@ -143,7 +143,7 @@
appWidgetId = id,
providerInfo = providerInfo,
rank = rank,
- spanY = CommunalContentSize.HALF.span,
+ spanY = CommunalContentSize.FixedSize.HALF.span,
)
updateListFromDatabase()
}
diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/kosmos/KosmosJavaAdapter.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/kosmos/KosmosJavaAdapter.kt
index 5b2c8dd..41cfcea 100644
--- a/packages/SystemUI/tests/utils/src/com/android/systemui/kosmos/KosmosJavaAdapter.kt
+++ b/packages/SystemUI/tests/utils/src/com/android/systemui/kosmos/KosmosJavaAdapter.kt
@@ -66,6 +66,7 @@
import com.android.systemui.settings.brightness.domain.interactor.brightnessMirrorShowingInteractor
import com.android.systemui.shade.data.repository.shadeRepository
import com.android.systemui.shade.domain.interactor.shadeInteractor
+import com.android.systemui.shade.domain.interactor.shadeLayoutParams
import com.android.systemui.shade.domain.interactor.shadeModeInteractor
import com.android.systemui.shade.shadeController
import com.android.systemui.shade.ui.viewmodel.notificationShadeWindowModel
@@ -133,6 +134,7 @@
val simBouncerInteractor by lazy { kosmos.simBouncerInteractor }
val statusBarStateController by lazy { kosmos.statusBarStateController }
val statusBarModePerDisplayRepository by lazy { kosmos.fakeStatusBarModePerDisplayRepository }
+ val shadeLayoutParams by lazy { kosmos.shadeLayoutParams }
val autoHideControllerStore by lazy { kosmos.fakeAutoHideControllerStore }
val interactionJankMonitor by lazy { kosmos.interactionJankMonitor }
val fakeSceneContainerConfig by lazy { kosmos.sceneContainerConfig }
diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/qs/tiles/viewmodel/QSTileViewModelAdapterKosmos.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/qs/tiles/viewmodel/QSTileViewModelAdapterKosmos.kt
index a908765..de9f629 100644
--- a/packages/SystemUI/tests/utils/src/com/android/systemui/qs/tiles/viewmodel/QSTileViewModelAdapterKosmos.kt
+++ b/packages/SystemUI/tests/utils/src/com/android/systemui/qs/tiles/viewmodel/QSTileViewModelAdapterKosmos.kt
@@ -18,6 +18,7 @@
import com.android.systemui.kosmos.Kosmos
import com.android.systemui.kosmos.applicationCoroutineScope
+import com.android.systemui.kosmos.testDispatcher
import com.android.systemui.util.mockito.mock
val Kosmos.qsTileViewModelAdaperFactory by
@@ -28,6 +29,7 @@
applicationCoroutineScope,
mock(),
qsTileViewModel,
+ testDispatcher,
)
}
}
diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/scene/ui/view/WindowRootViewKosmos.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/scene/ui/view/WindowRootViewKosmos.kt
new file mode 100644
index 0000000..5c91dc8
--- /dev/null
+++ b/packages/SystemUI/tests/utils/src/com/android/systemui/scene/ui/view/WindowRootViewKosmos.kt
@@ -0,0 +1,22 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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.scene.ui.view
+
+import com.android.systemui.kosmos.Kosmos
+import org.mockito.kotlin.mock
+
+val Kosmos.mockShadeRootView by Kosmos.Fixture { mock<WindowRootView>() }
diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/shade/data/repository/ShadeDisplaysRepositoryKosmos.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/shade/data/repository/ShadeDisplaysRepositoryKosmos.kt
index dbaa0b1..7488397d 100644
--- a/packages/SystemUI/tests/utils/src/com/android/systemui/shade/data/repository/ShadeDisplaysRepositoryKosmos.kt
+++ b/packages/SystemUI/tests/utils/src/com/android/systemui/shade/data/repository/ShadeDisplaysRepositoryKosmos.kt
@@ -32,3 +32,6 @@
bgScope = testScope.backgroundScope,
)
}
+
+val Kosmos.fakeShadeDisplaysRepository: FakeShadeDisplayRepository by
+ Kosmos.Fixture { FakeShadeDisplayRepository() }
diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/shade/domain/interactor/ShadeDisplaysInteractorKosmos.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/shade/domain/interactor/ShadeDisplaysInteractorKosmos.kt
new file mode 100644
index 0000000..db4df38
--- /dev/null
+++ b/packages/SystemUI/tests/utils/src/com/android/systemui/shade/domain/interactor/ShadeDisplaysInteractorKosmos.kt
@@ -0,0 +1,42 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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.shade.domain.interactor
+
+import android.content.mockedContext
+import android.view.mockWindowManager
+import com.android.systemui.kosmos.Kosmos
+import com.android.systemui.kosmos.testScope
+import com.android.systemui.scene.ui.view.mockShadeRootView
+import com.android.systemui.shade.ShadeWindowLayoutParams
+import com.android.systemui.shade.data.repository.fakeShadeDisplaysRepository
+import java.util.Optional
+
+val Kosmos.shadeLayoutParams by Kosmos.Fixture {
+ ShadeWindowLayoutParams.create(mockedContext)
+}
+val Kosmos.shadeDisplaysInteractor by
+ Kosmos.Fixture {
+ ShadeDisplaysInteractor(
+ Optional.of(mockShadeRootView),
+ fakeShadeDisplaysRepository,
+ mockedContext,
+ shadeLayoutParams,
+ mockWindowManager,
+ testScope.backgroundScope,
+ testScope.backgroundScope.coroutineContext,
+ )
+ }
diff --git a/services/core/java/android/content/pm/PackageManagerInternal.java b/services/core/java/android/content/pm/PackageManagerInternal.java
index 43774bb..b0dae6a 100644
--- a/services/core/java/android/content/pm/PackageManagerInternal.java
+++ b/services/core/java/android/content/pm/PackageManagerInternal.java
@@ -90,6 +90,7 @@
*/
public static final int RESOLVE_NON_RESOLVER_ONLY = 0x00000002;
+ @Deprecated
@IntDef(value = {
INTEGRITY_VERIFICATION_ALLOW,
INTEGRITY_VERIFICATION_REJECT,
@@ -97,18 +98,10 @@
@Retention(RetentionPolicy.SOURCE)
public @interface IntegrityVerificationResult {}
- /**
- * Used as the {@code verificationCode} argument for
- * {@link PackageManagerInternal#setIntegrityVerificationResult(int, int)} to indicate that the
- * integrity component allows the install to proceed.
- */
+ @Deprecated
public static final int INTEGRITY_VERIFICATION_ALLOW = 1;
- /**
- * Used as the {@code verificationCode} argument for
- * {@link PackageManagerInternal#setIntegrityVerificationResult(int, int)} to indicate that the
- * integrity component does not allow install to proceed.
- */
+ @Deprecated
public static final int INTEGRITY_VERIFICATION_REJECT = 0;
/**
@@ -1131,17 +1124,13 @@
public abstract boolean isPermissionUpgradeNeeded(@UserIdInt int userId);
/**
- * Allows the integrity component to respond to the
- * {@link Intent#ACTION_PACKAGE_NEEDS_INTEGRITY_VERIFICATION package verification
- * broadcast} to respond to the package manager. The response must include
- * the {@code verificationCode} which is one of
- * {@link #INTEGRITY_VERIFICATION_ALLOW} and {@link #INTEGRITY_VERIFICATION_REJECT}.
+ * Used to allow the integrity component to respond to the
+ * ACTION_PACKAGE_NEEDS_INTEGRITY_VERIFICATION package verification
+ * broadcast to respond to the package manager.
*
- * @param verificationId pending package identifier as passed via the
- * {@link PackageManager#EXTRA_VERIFICATION_ID} Intent extra.
- * @param verificationResult either {@link #INTEGRITY_VERIFICATION_ALLOW}
- * or {@link #INTEGRITY_VERIFICATION_REJECT}.
+ * Deprecated.
*/
+ @Deprecated
public abstract void setIntegrityVerificationResult(int verificationId,
@IntegrityVerificationResult int verificationResult);
diff --git a/services/core/java/com/android/server/display/brightness/clamper/BrightnessClamperController.java b/services/core/java/com/android/server/display/brightness/clamper/BrightnessClamperController.java
index ceade37..440a271 100644
--- a/services/core/java/com/android/server/display/brightness/clamper/BrightnessClamperController.java
+++ b/services/core/java/com/android/server/display/brightness/clamper/BrightnessClamperController.java
@@ -81,6 +81,8 @@
}
};
+ private volatile boolean mStarted = false;
+
public BrightnessClamperController(Handler handler,
ClamperChangeListener clamperChangeListener, DisplayDeviceData data, Context context,
DisplayManagerFlags flags, SensorManager sensorManager, float currentBrightness) {
@@ -100,10 +102,10 @@
mClamperChangeListenerExternal = clamperChangeListener;
mExecutor = new HandlerExecutor(handler);
- Runnable clamperChangeRunnableInternal = this::recalculateBrightnessCap;
+ Runnable modifiersChangeRunnableInternal = this::recalculateModifiersState;
ClamperChangeListener clamperChangeListenerInternal = () -> {
- if (!mHandler.hasCallbacks(clamperChangeRunnableInternal)) {
- mHandler.post(clamperChangeRunnableInternal);
+ if (mStarted && !mHandler.hasCallbacks(modifiersChangeRunnableInternal)) {
+ mHandler.post(modifiersChangeRunnableInternal);
}
};
@@ -187,6 +189,7 @@
* Called in DisplayControllerHandler
*/
public void stop() {
+ mStarted = false;
mDeviceConfigParameterProvider.removeOnPropertiesChangedListener(
mOnPropertiesChangedListener);
mLightSensorController.stop();
@@ -195,9 +198,9 @@
// Called in DisplayControllerHandler
- private void recalculateBrightnessCap() {
+ private void recalculateModifiersState() {
ModifiersAggregatedState newAggregatedState = new ModifiersAggregatedState();
- mStatefulModifiers.forEach((clamper) -> clamper.applyStateChange(newAggregatedState));
+ mStatefulModifiers.forEach((modifier) -> modifier.applyStateChange(newAggregatedState));
if (needToNotifyExternalListener(mModifiersAggregatedState, newAggregatedState)) {
mClamperChangeListenerExternal.onChanged();
@@ -223,6 +226,7 @@
mExecutor, mOnPropertiesChangedListener);
}
adjustLightSensorSubscription();
+ mStarted = true;
}
private void adjustLightSensorSubscription() {
diff --git a/services/core/java/com/android/server/integrity/AppIntegrityManagerServiceImpl.java b/services/core/java/com/android/server/integrity/AppIntegrityManagerServiceImpl.java
index a132876b..0914b7e 100644
--- a/services/core/java/com/android/server/integrity/AppIntegrityManagerServiceImpl.java
+++ b/services/core/java/com/android/server/integrity/AppIntegrityManagerServiceImpl.java
@@ -93,29 +93,6 @@
mContext = context;
mPackageManagerInternal = packageManagerInternal;
mHandler = handler;
-
- IntentFilter integrityVerificationFilter = new IntentFilter();
- integrityVerificationFilter.addAction(ACTION_PACKAGE_NEEDS_INTEGRITY_VERIFICATION);
- try {
- integrityVerificationFilter.addDataType(PACKAGE_MIME_TYPE);
- } catch (IntentFilter.MalformedMimeTypeException e) {
- throw new RuntimeException("Mime type malformed: should never happen.", e);
- }
-
- mContext.registerReceiver(
- new BroadcastReceiver() {
- @Override
- public void onReceive(Context context, Intent intent) {
- if (!ACTION_PACKAGE_NEEDS_INTEGRITY_VERIFICATION.equals(
- intent.getAction())) {
- return;
- }
- mHandler.post(() -> handleIntegrityVerification(intent));
- }
- },
- integrityVerificationFilter,
- /* broadcastPermission= */ null,
- mHandler);
}
@Override
@@ -157,10 +134,4 @@
public List<String> getWhitelistedRuleProviders() {
return Collections.emptyList();
}
-
- private void handleIntegrityVerification(Intent intent) {
- int verificationId = intent.getIntExtra(EXTRA_VERIFICATION_ID, -1);
- mPackageManagerInternal.setIntegrityVerificationResult(
- verificationId, PackageManagerInternal.INTEGRITY_VERIFICATION_ALLOW);
- }
}
diff --git a/services/core/java/com/android/server/pm/PackageHandler.java b/services/core/java/com/android/server/pm/PackageHandler.java
index 0a0882d..4ea4054 100644
--- a/services/core/java/com/android/server/pm/PackageHandler.java
+++ b/services/core/java/com/android/server/pm/PackageHandler.java
@@ -18,7 +18,6 @@
import static android.os.Trace.TRACE_TAG_PACKAGE_MANAGER;
-import static com.android.server.pm.PackageManagerService.CHECK_PENDING_INTEGRITY_VERIFICATION;
import static com.android.server.pm.PackageManagerService.CHECK_PENDING_VERIFICATION;
import static com.android.server.pm.PackageManagerService.DEBUG_INSTALL;
import static com.android.server.pm.PackageManagerService.DEFAULT_UNUSED_STATIC_SHARED_LIB_MIN_CACHE_PERIOD;
@@ -29,7 +28,6 @@
import static com.android.server.pm.PackageManagerService.ENABLE_ROLLBACK_STATUS;
import static com.android.server.pm.PackageManagerService.ENABLE_ROLLBACK_TIMEOUT;
import static com.android.server.pm.PackageManagerService.INSTANT_APP_RESOLUTION_PHASE_TWO;
-import static com.android.server.pm.PackageManagerService.INTEGRITY_VERIFICATION_COMPLETE;
import static com.android.server.pm.PackageManagerService.PACKAGE_VERIFIED;
import static com.android.server.pm.PackageManagerService.POST_INSTALL;
import static com.android.server.pm.PackageManagerService.PRUNE_UNUSED_STATIC_SHARED_LIBRARIES;
@@ -149,42 +147,6 @@
break;
}
- case CHECK_PENDING_INTEGRITY_VERIFICATION: {
- final int verificationId = msg.arg1;
- final PackageVerificationState state = mPm.mPendingVerification.get(verificationId);
-
- if (state != null && !state.isIntegrityVerificationComplete()) {
- final VerifyingSession verifyingSession = state.getVerifyingSession();
- final Uri originUri = Uri.fromFile(verifyingSession.mOriginInfo.mResolvedFile);
-
- String errorMsg = "Integrity verification timed out for " + originUri;
- Slog.i(TAG, errorMsg);
-
- state.setIntegrityVerificationResult(
- getDefaultIntegrityVerificationResponse());
-
- if (getDefaultIntegrityVerificationResponse()
- == PackageManagerInternal.INTEGRITY_VERIFICATION_ALLOW) {
- Slog.i(TAG, "Integrity check times out, continuing with " + originUri);
- } else {
- verifyingSession.setReturnCode(
- PackageManager.INSTALL_FAILED_VERIFICATION_FAILURE,
- errorMsg);
- }
-
- if (state.areAllVerificationsComplete()) {
- mPm.mPendingVerification.remove(verificationId);
- }
-
- Trace.asyncTraceEnd(
- TRACE_TAG_PACKAGE_MANAGER,
- "integrity_verification",
- verificationId);
-
- verifyingSession.handleIntegrityVerificationFinished();
- }
- break;
- }
case PACKAGE_VERIFIED: {
final int verificationId = msg.arg1;
@@ -205,42 +167,6 @@
break;
}
- case INTEGRITY_VERIFICATION_COMPLETE: {
- final int verificationId = msg.arg1;
-
- final PackageVerificationState state = mPm.mPendingVerification.get(verificationId);
- if (state == null) {
- Slog.w(TAG, "Integrity verification with id " + verificationId
- + " not found. It may be invalid or overridden by verifier");
- break;
- }
-
- final int response = (Integer) msg.obj;
- final VerifyingSession verifyingSession = state.getVerifyingSession();
- final Uri originUri = Uri.fromFile(verifyingSession.mOriginInfo.mResolvedFile);
-
- state.setIntegrityVerificationResult(response);
-
- if (response == PackageManagerInternal.INTEGRITY_VERIFICATION_ALLOW) {
- Slog.i(TAG, "Integrity check passed for " + originUri);
- } else {
- verifyingSession.setReturnCode(
- PackageManager.INSTALL_FAILED_VERIFICATION_FAILURE,
- "Integrity check failed for " + originUri);
- }
-
- if (state.areAllVerificationsComplete()) {
- mPm.mPendingVerification.remove(verificationId);
- }
-
- Trace.asyncTraceEnd(
- TRACE_TAG_PACKAGE_MANAGER,
- "integrity_verification",
- verificationId);
-
- verifyingSession.handleIntegrityVerificationFinished();
- break;
- }
case INSTANT_APP_RESOLUTION_PHASE_TWO: {
InstantAppResolver.doInstantAppResolutionPhaseTwo(mPm.mContext,
mPm.snapshotComputer(),
diff --git a/services/core/java/com/android/server/pm/PackageManagerService.java b/services/core/java/com/android/server/pm/PackageManagerService.java
index ab26f02..65bb701 100644
--- a/services/core/java/com/android/server/pm/PackageManagerService.java
+++ b/services/core/java/com/android/server/pm/PackageManagerService.java
@@ -923,8 +923,8 @@
static final int ENABLE_ROLLBACK_TIMEOUT = 22;
static final int DEFERRED_NO_KILL_POST_DELETE = 23;
static final int DEFERRED_NO_KILL_INSTALL_OBSERVER = 24;
- static final int INTEGRITY_VERIFICATION_COMPLETE = 25;
- static final int CHECK_PENDING_INTEGRITY_VERIFICATION = 26;
+ // static final int UNUSED = 25;
+ // static final int UNUSED = 26;
static final int DOMAIN_VERIFICATION = 27;
static final int PRUNE_UNUSED_STATIC_SHARED_LIBRARIES = 28;
static final int DEFERRED_PENDING_KILL_INSTALL_OBSERVER = 29;
@@ -7124,12 +7124,10 @@
return mSettings.isPermissionUpgradeNeeded(userId);
}
+ @Deprecated
@Override
public void setIntegrityVerificationResult(int verificationId, int verificationResult) {
- final Message msg = mHandler.obtainMessage(INTEGRITY_VERIFICATION_COMPLETE);
- msg.arg1 = verificationId;
- msg.obj = verificationResult;
- mHandler.sendMessage(msg);
+ // Do nothing.
}
@Override
diff --git a/services/core/java/com/android/server/pm/PackageVerificationState.java b/services/core/java/com/android/server/pm/PackageVerificationState.java
index 0b6ccc4..63c2ee2 100644
--- a/services/core/java/com/android/server/pm/PackageVerificationState.java
+++ b/services/core/java/com/android/server/pm/PackageVerificationState.java
@@ -43,8 +43,6 @@
private boolean mRequiredVerificationPassed;
- private boolean mIntegrityVerificationComplete;
-
/**
* Create a new package verification state where {@code requiredVerifierUid} is the user ID for
* the package that must reply affirmative before things can continue.
@@ -213,15 +211,7 @@
return mExtendedTimeoutUids.get(uid, false);
}
- void setIntegrityVerificationResult(int code) {
- mIntegrityVerificationComplete = true;
- }
-
- boolean isIntegrityVerificationComplete() {
- return mIntegrityVerificationComplete;
- }
-
boolean areAllVerificationsComplete() {
- return mIntegrityVerificationComplete && isVerificationComplete();
+ return isVerificationComplete();
}
}
diff --git a/services/core/java/com/android/server/pm/VerifyingSession.java b/services/core/java/com/android/server/pm/VerifyingSession.java
index f7eb29f..542ae8e 100644
--- a/services/core/java/com/android/server/pm/VerifyingSession.java
+++ b/services/core/java/com/android/server/pm/VerifyingSession.java
@@ -28,7 +28,6 @@
import static android.os.PowerWhitelistManager.TEMPORARY_ALLOWLIST_TYPE_FOREGROUND_SERVICE_ALLOWED;
import static android.os.Trace.TRACE_TAG_PACKAGE_MANAGER;
-import static com.android.server.pm.PackageManagerService.CHECK_PENDING_INTEGRITY_VERIFICATION;
import static com.android.server.pm.PackageManagerService.CHECK_PENDING_VERIFICATION;
import static com.android.server.pm.PackageManagerService.DEBUG_INSTALL;
import static com.android.server.pm.PackageManagerService.DEBUG_VERIFY;
@@ -87,11 +86,6 @@
* Whether verification is enabled by default.
*/
private static final boolean DEFAULT_VERIFY_ENABLE = true;
-
- /**
- * Whether integrity verification is enabled by default.
- */
- private static final boolean DEFAULT_INTEGRITY_VERIFY_ENABLE = true;
/**
* The default maximum time to wait for the integrity verification to return in
* milliseconds.
@@ -129,7 +123,6 @@
private final boolean mUserActionRequired;
private final int mUserActionRequiredType;
private boolean mWaitForVerificationToComplete;
- private boolean mWaitForIntegrityVerificationToComplete;
private boolean mWaitForEnableRollbackToComplete;
private int mRet = PackageManager.INSTALL_SUCCEEDED;
private String mErrorMessage = null;
@@ -217,7 +210,6 @@
new PackageVerificationState(this);
mPm.mPendingVerification.append(verificationId, verificationState);
- sendIntegrityVerificationRequest(verificationId, pkgLite, verificationState);
sendPackageVerificationRequest(
verificationId, pkgLite, verificationState);
@@ -270,89 +262,6 @@
mPm.mHandler.sendMessageDelayed(msg, rollbackTimeout);
}
- /**
- * Send a request to check the integrity of the package.
- */
- void sendIntegrityVerificationRequest(
- int verificationId,
- PackageInfoLite pkgLite,
- PackageVerificationState verificationState) {
- if (!isIntegrityVerificationEnabled()) {
- // Consider the integrity check as passed.
- verificationState.setIntegrityVerificationResult(
- PackageManagerInternal.INTEGRITY_VERIFICATION_ALLOW);
- return;
- }
-
- final Intent integrityVerification =
- new Intent(Intent.ACTION_PACKAGE_NEEDS_INTEGRITY_VERIFICATION);
-
- integrityVerification.setDataAndType(Uri.fromFile(new File(mOriginInfo.mResolvedPath)),
- PACKAGE_MIME_TYPE);
-
- final int flags = Intent.FLAG_GRANT_READ_URI_PERMISSION
- | Intent.FLAG_RECEIVER_REGISTERED_ONLY
- | Intent.FLAG_RECEIVER_FOREGROUND;
- integrityVerification.addFlags(flags);
-
- integrityVerification.putExtra(EXTRA_VERIFICATION_ID, verificationId);
- integrityVerification.putExtra(EXTRA_PACKAGE_NAME, pkgLite.packageName);
- integrityVerification.putExtra(EXTRA_VERSION_CODE, pkgLite.versionCode);
- integrityVerification.putExtra(EXTRA_LONG_VERSION_CODE, pkgLite.getLongVersionCode());
- populateInstallerExtras(integrityVerification);
-
- // send to integrity component only.
- integrityVerification.setPackage("android");
-
- final BroadcastOptions options = BroadcastOptions.makeBasic();
-
- mPm.mContext.sendOrderedBroadcastAsUser(integrityVerification, UserHandle.SYSTEM,
- /* receiverPermission= */ null,
- /* appOp= */ AppOpsManager.OP_NONE,
- /* options= */ options.toBundle(),
- new BroadcastReceiver() {
- @Override
- public void onReceive(Context context, Intent intent) {
- final Message msg =
- mPm.mHandler.obtainMessage(CHECK_PENDING_INTEGRITY_VERIFICATION);
- msg.arg1 = verificationId;
- mPm.mHandler.sendMessageDelayed(msg, getIntegrityVerificationTimeout());
- }
- }, /* scheduler= */ null,
- /* initialCode= */ 0,
- /* initialData= */ null,
- /* initialExtras= */ null);
-
- Trace.asyncTraceBegin(
- TRACE_TAG_PACKAGE_MANAGER, "integrity_verification", verificationId);
-
- // stop the copy until verification succeeds.
- mWaitForIntegrityVerificationToComplete = true;
- }
-
-
- /**
- * Get the integrity verification timeout.
- *
- * @return verification timeout in milliseconds
- */
- private long getIntegrityVerificationTimeout() {
- long timeout = Settings.Global.getLong(mPm.mContext.getContentResolver(),
- Settings.Global.APP_INTEGRITY_VERIFICATION_TIMEOUT,
- DEFAULT_INTEGRITY_VERIFICATION_TIMEOUT);
- // The setting can be used to increase the timeout but not decrease it, since that is
- // equivalent to disabling the integrity component.
- return Math.max(timeout, DEFAULT_INTEGRITY_VERIFICATION_TIMEOUT);
- }
-
- /**
- * Check whether or not integrity verification has been enabled.
- */
- private boolean isIntegrityVerificationEnabled() {
- // We are not exposing this as a user-configurable setting because we don't want to provide
- // an easy way to get around the integrity check.
- return DEFAULT_INTEGRITY_VERIFY_ENABLE;
- }
/**
* Send a request to verifier(s) to verify the package if necessary.
@@ -827,11 +736,6 @@
handleReturnCode();
}
- void handleIntegrityVerificationFinished() {
- mWaitForIntegrityVerificationToComplete = false;
- handleReturnCode();
- }
-
void handleRollbackEnabled() {
// TODO(b/112431924): Consider halting the install if we
// couldn't enable rollback.
@@ -840,7 +744,7 @@
}
void handleReturnCode() {
- if (mWaitForVerificationToComplete || mWaitForIntegrityVerificationToComplete
+ if (mWaitForVerificationToComplete
|| mWaitForEnableRollbackToComplete) {
return;
}
diff --git a/services/core/java/com/android/server/wm/WindowManagerService.java b/services/core/java/com/android/server/wm/WindowManagerService.java
index 9e1509c..7e70e75 100644
--- a/services/core/java/com/android/server/wm/WindowManagerService.java
+++ b/services/core/java/com/android/server/wm/WindowManagerService.java
@@ -69,6 +69,7 @@
import static android.view.WindowManager.LayoutParams.FLAG_SHOW_WHEN_LOCKED;
import static android.view.WindowManager.LayoutParams.FLAG_SLIPPERY;
import static android.view.WindowManager.LayoutParams.INPUT_FEATURE_NO_INPUT_CHANNEL;
+import static android.view.WindowManager.LayoutParams.INPUT_FEATURE_RECEIVE_POWER_KEY_DOUBLE_PRESS;
import static android.view.WindowManager.LayoutParams.INPUT_FEATURE_SENSITIVE_FOR_PRIVACY;
import static android.view.WindowManager.LayoutParams.INPUT_FEATURE_SPY;
import static android.view.WindowManager.LayoutParams.INVALID_WINDOW_TYPE;
@@ -101,6 +102,7 @@
import static android.view.flags.Flags.sensitiveContentAppProtection;
import static android.window.WindowProviderService.isWindowProviderService;
+import static com.android.hardware.input.Flags.overridePowerKeyBehaviorInFocusedWindow;
import static com.android.internal.protolog.WmProtoLogGroups.WM_DEBUG_ADD_REMOVE;
import static com.android.internal.protolog.WmProtoLogGroups.WM_DEBUG_ANIM;
import static com.android.internal.protolog.WmProtoLogGroups.WM_DEBUG_BOOT;
@@ -157,9 +159,9 @@
import static com.android.server.wm.WindowManagerServiceDumpProto.POLICY;
import static com.android.server.wm.WindowManagerServiceDumpProto.ROOT_WINDOW_CONTAINER;
import static com.android.server.wm.WindowManagerServiceDumpProto.WINDOW_FRAMES_VALID;
+import static com.android.window.flags.Flags.enableDisplayFocusInShellTransitions;
import static com.android.window.flags.Flags.multiCrop;
import static com.android.window.flags.Flags.setScPropertiesInClient;
-import static com.android.window.flags.Flags.enableDisplayFocusInShellTransitions;
import android.Manifest;
import android.Manifest.permission;
@@ -9221,6 +9223,25 @@
+ "' because it isn't a trusted overlay");
return inputFeatures & ~INPUT_FEATURE_SENSITIVE_FOR_PRIVACY;
}
+
+ // You need OVERRIDE_SYSTEM_KEY_BEHAVIOR_IN_FOCUSED_WINDOW permission to be able
+ // to set INPUT_FEATURE_RECEIVE_POWER_KEY_DOUBLE_PRESS.
+ if (overridePowerKeyBehaviorInFocusedWindow()
+ && (inputFeatures
+ & INPUT_FEATURE_RECEIVE_POWER_KEY_DOUBLE_PRESS)
+ != 0) {
+ final int powerPermissionResult =
+ mContext.checkPermission(
+ permission.OVERRIDE_SYSTEM_KEY_BEHAVIOR_IN_FOCUSED_WINDOW,
+ callingPid,
+ callingUid);
+ if (powerPermissionResult != PackageManager.PERMISSION_GRANTED) {
+ throw new IllegalArgumentException(
+ "Cannot use INPUT_FEATURE_RECEIVE_POWER_KEY_DOUBLE_PRESS from" + windowName
+ + " because it doesn't have the"
+ + " OVERRIDE_SYSTEM_KEY_BEHAVIOR_IN_FOCUSED_WINDOW permission");
+ }
+ }
return inputFeatures;
}
diff --git a/services/tests/PackageManagerServiceTests/server/src/com/android/server/pm/PackageVerificationStateTest.java b/services/tests/PackageManagerServiceTests/server/src/com/android/server/pm/PackageVerificationStateTest.java
index a93e8ad..97f1bd4 100644
--- a/services/tests/PackageManagerServiceTests/server/src/com/android/server/pm/PackageVerificationStateTest.java
+++ b/services/tests/PackageManagerServiceTests/server/src/com/android/server/pm/PackageVerificationStateTest.java
@@ -574,57 +574,16 @@
assertTrue(state.isInstallAllowed());
}
- public void testAreAllVerificationsComplete_onlyVerificationPasses() {
+ public void testAreAllVerificationsComplete() {
PackageVerificationState state = new PackageVerificationState(null);
state.addRequiredVerifierUid(REQUIRED_UID_1);
assertFalse(state.areAllVerificationsComplete());
state.setVerifierResponse(REQUIRED_UID_1, PackageManager.VERIFICATION_ALLOW);
- assertFalse(state.areAllVerificationsComplete());
- }
-
- public void testAreAllVerificationsComplete_onlyIntegrityCheckPasses() {
- PackageVerificationState state = new PackageVerificationState(null);
- state.addRequiredVerifierUid(REQUIRED_UID_1);
- assertFalse(state.areAllVerificationsComplete());
-
- state.setIntegrityVerificationResult(PackageManagerInternal.INTEGRITY_VERIFICATION_ALLOW);
-
- assertFalse(state.areAllVerificationsComplete());
- }
-
- public void testAreAllVerificationsComplete_bothPasses() {
- PackageVerificationState state = new PackageVerificationState(null);
- state.addRequiredVerifierUid(REQUIRED_UID_1);
- assertFalse(state.areAllVerificationsComplete());
-
- state.setIntegrityVerificationResult(PackageManagerInternal.INTEGRITY_VERIFICATION_ALLOW);
- state.setVerifierResponse(REQUIRED_UID_1, PackageManager.VERIFICATION_ALLOW);
-
assertTrue(state.areAllVerificationsComplete());
}
- public void testAreAllVerificationsComplete_onlyVerificationFails() {
- PackageVerificationState state = new PackageVerificationState(null);
- state.addRequiredVerifierUid(REQUIRED_UID_1);
- assertFalse(state.areAllVerificationsComplete());
-
- state.setVerifierResponse(REQUIRED_UID_1, PackageManager.VERIFICATION_REJECT);
-
- assertFalse(state.areAllVerificationsComplete());
- }
-
- public void testAreAllVerificationsComplete_onlyIntegrityCheckFails() {
- PackageVerificationState state = new PackageVerificationState(null);
- state.addRequiredVerifierUid(REQUIRED_UID_1);
- assertFalse(state.areAllVerificationsComplete());
-
- state.setIntegrityVerificationResult(PackageManagerInternal.INTEGRITY_VERIFICATION_REJECT);
-
- assertFalse(state.areAllVerificationsComplete());
- }
-
private void processOnTimeout(PackageVerificationState state, int code, int uid) {
// CHECK_PENDING_VERIFICATION handler.
assertFalse("Verification should not be marked as complete yet",
diff --git a/services/tests/displayservicetests/src/com/android/server/display/brightness/clamper/BrightnessClamperControllerTest.java b/services/tests/displayservicetests/src/com/android/server/display/brightness/clamper/BrightnessClamperControllerTest.java
index 5490a22..66e9c98 100644
--- a/services/tests/displayservicetests/src/com/android/server/display/brightness/clamper/BrightnessClamperControllerTest.java
+++ b/services/tests/displayservicetests/src/com/android/server/display/brightness/clamper/BrightnessClamperControllerTest.java
@@ -19,6 +19,8 @@
import static android.view.Display.STATE_OFF;
import static android.view.Display.STATE_ON;
+import static com.google.common.truth.Truth.assertThat;
+
import static org.junit.Assert.assertEquals;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.eq;
@@ -269,6 +271,24 @@
verify(mMockExternalListener).onChanged();
}
+ @Test
+ public void test_doesNotScheduleRecalculateBeforeStart() {
+ mTestInjector = new TestInjector(List.of()) {
+ @Override
+ List<BrightnessStateModifier> getModifiers(DisplayManagerFlags flags, Context context,
+ Handler handler, BrightnessClamperController.ClamperChangeListener listener,
+ BrightnessClamperController.DisplayDeviceData displayDeviceData,
+ float currentBrightness) {
+ listener.onChanged();
+ return super.getModifiers(flags, context, handler, listener, displayDeviceData,
+ currentBrightness);
+ }
+ };
+ mClamperController = createBrightnessClamperController();
+
+ assertThat(mTestHandler.getPendingMessages()).isEmpty();
+ }
+
private BrightnessClamperController createBrightnessClamperController() {
return new BrightnessClamperController(mTestInjector, mTestHandler, mMockExternalListener,
mMockDisplayDeviceData, mMockContext, mFlags, mSensorManager, 0);
diff --git a/services/tests/servicestests/src/com/android/server/biometrics/AuthServiceTest.java b/services/tests/servicestests/src/com/android/server/biometrics/AuthServiceTest.java
index 9cd3186..605fed0 100644
--- a/services/tests/servicestests/src/com/android/server/biometrics/AuthServiceTest.java
+++ b/services/tests/servicestests/src/com/android/server/biometrics/AuthServiceTest.java
@@ -38,6 +38,7 @@
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
+import android.annotation.UserIdInt;
import android.app.AppOpsManager;
import android.content.Context;
import android.content.pm.PackageManager;
@@ -92,6 +93,8 @@
private static final String TEST_OP_PACKAGE_NAME = "test_package";
+ private final @UserIdInt int mUserId = UserHandle.getCallingUserId();
+
private AuthService mAuthService;
@Rule
@@ -257,12 +260,11 @@
final Binder token = new Binder();
final PromptInfo promptInfo = new PromptInfo();
final long sessionId = 0;
- final int userId = 0;
mAuthService.mImpl.authenticate(
token,
sessionId,
- userId,
+ mUserId,
mReceiver,
TEST_OP_PACKAGE_NAME,
promptInfo);
@@ -270,7 +272,7 @@
verify(mBiometricService).authenticate(
eq(token),
eq(sessionId),
- eq(userId),
+ eq(mUserId),
eq(mReceiver),
eq(TEST_OP_PACKAGE_NAME),
eq(promptInfo));
@@ -286,12 +288,11 @@
final Binder token = new Binder();
final PromptInfo promptInfo = new PromptInfo();
final long sessionId = 0;
- final int userId = 0;
mAuthService.mImpl.authenticate(
token,
sessionId,
- userId,
+ mUserId,
mReceiver,
TEST_OP_PACKAGE_NAME,
promptInfo);
@@ -299,7 +300,7 @@
verify(mBiometricService, never()).authenticate(
eq(token),
eq(sessionId),
- eq(userId),
+ eq(mUserId),
eq(mReceiver),
eq(TEST_OP_PACKAGE_NAME),
eq(promptInfo));
@@ -313,12 +314,11 @@
final PromptInfo promptInfo = new PromptInfo();
final long sessionId = 0;
- final int userId = 0;
mAuthService.mImpl.authenticate(
null /* token */,
sessionId,
- userId,
+ mUserId,
mReceiver,
TEST_OP_PACKAGE_NAME,
promptInfo);
@@ -338,7 +338,7 @@
mAuthService.mImpl.authenticate(
token,
0, /* sessionId */
- 0, /* userId */
+ mUserId,
mReceiver,
TEST_OP_PACKAGE_NAME,
new PromptInfo());
@@ -356,7 +356,7 @@
mAuthService.mImpl.authenticate(
token,
0, /* sessionId */
- 0, /* userId */
+ mUserId,
mReceiver,
TEST_OP_PACKAGE_NAME,
new PromptInfo());
@@ -414,20 +414,19 @@
mAuthService = new AuthService(mContext, mInjector);
mAuthService.onStart();
- final int userId = 0;
final int expectedResult = BIOMETRIC_SUCCESS;
final int authenticators = 0;
when(mBiometricService.canAuthenticate(anyString(), anyInt(), anyInt(), anyInt()))
.thenReturn(expectedResult);
final int result = mAuthService.mImpl
- .canAuthenticate(TEST_OP_PACKAGE_NAME, userId, authenticators);
+ .canAuthenticate(TEST_OP_PACKAGE_NAME, mUserId, authenticators);
assertEquals(expectedResult, result);
waitForIdle();
verify(mBiometricService).canAuthenticate(
eq(TEST_OP_PACKAGE_NAME),
- eq(userId),
+ eq(mUserId),
eq(UserHandle.getCallingUserId()),
eq(authenticators));
}
@@ -440,18 +439,17 @@
mAuthService = new AuthService(mContext, mInjector);
mAuthService.onStart();
- final int userId = 0;
final boolean expectedResult = true;
when(mBiometricService.hasEnrolledBiometrics(anyInt(), anyString())).thenReturn(
expectedResult);
- final boolean result = mAuthService.mImpl.hasEnrolledBiometrics(userId,
+ final boolean result = mAuthService.mImpl.hasEnrolledBiometrics(mUserId,
TEST_OP_PACKAGE_NAME);
assertEquals(expectedResult, result);
waitForIdle();
verify(mBiometricService).hasEnrolledBiometrics(
- eq(userId),
+ eq(mUserId),
eq(TEST_OP_PACKAGE_NAME));
}
@@ -528,13 +526,12 @@
mAuthService = new AuthService(mContext, mInjector);
mAuthService.onStart();
- final int userId = 0;
final int authenticators = BiometricManager.Authenticators.BIOMETRIC_STRONG;
- mAuthService.mImpl.getLastAuthenticationTime(userId, authenticators);
+ mAuthService.mImpl.getLastAuthenticationTime(mUserId, authenticators);
waitForIdle();
- verify(mBiometricService).getLastAuthenticationTime(eq(userId), eq(authenticators));
+ verify(mBiometricService).getLastAuthenticationTime(eq(mUserId), eq(authenticators));
}
private static void setInternalAndTestBiometricPermissions(
diff --git a/services/tests/servicestests/src/com/android/server/integrity/AppIntegrityManagerServiceImplTest.java b/services/tests/servicestests/src/com/android/server/integrity/AppIntegrityManagerServiceImplTest.java
deleted file mode 100644
index fd22118..0000000
--- a/services/tests/servicestests/src/com/android/server/integrity/AppIntegrityManagerServiceImplTest.java
+++ /dev/null
@@ -1,295 +0,0 @@
-/*
- * Copyright (C) 2019 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.server.integrity;
-
-import static android.content.integrity.AppIntegrityManager.EXTRA_STATUS;
-import static android.content.integrity.AppIntegrityManager.STATUS_FAILURE;
-import static android.content.integrity.AppIntegrityManager.STATUS_SUCCESS;
-import static android.content.integrity.InstallerAllowedByManifestFormula.INSTALLER_CERTIFICATE_NOT_EVALUATED;
-import static android.content.pm.PackageManager.EXTRA_VERIFICATION_ID;
-import static android.content.pm.PackageManager.EXTRA_VERIFICATION_INSTALLER_PACKAGE;
-import static android.content.pm.PackageManager.EXTRA_VERIFICATION_INSTALLER_UID;
-
-import static com.google.common.truth.Truth.assertThat;
-
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertFalse;
-import static org.junit.Assert.assertNull;
-import static org.junit.Assert.assertTrue;
-import static org.mockito.ArgumentMatchers.any;
-import static org.mockito.ArgumentMatchers.anyInt;
-import static org.mockito.ArgumentMatchers.anyLong;
-import static org.mockito.ArgumentMatchers.eq;
-import static org.mockito.Mockito.atLeastOnce;
-import static org.mockito.Mockito.doReturn;
-import static org.mockito.Mockito.doThrow;
-import static org.mockito.Mockito.mock;
-import static org.mockito.Mockito.spy;
-import static org.mockito.Mockito.verify;
-import static org.mockito.Mockito.when;
-
-import static java.nio.file.StandardCopyOption.REPLACE_EXISTING;
-
-import android.content.BroadcastReceiver;
-import android.content.Context;
-import android.content.Intent;
-import android.content.IntentFilter;
-import android.content.IntentSender;
-import android.content.integrity.AppInstallMetadata;
-import android.content.integrity.AtomicFormula;
-import android.content.integrity.IntegrityFormula;
-import android.content.integrity.Rule;
-import android.content.pm.ApplicationInfo;
-import android.content.pm.PackageInfo;
-import android.content.pm.PackageManager;
-import android.content.pm.PackageManagerInternal;
-import android.content.pm.ParceledListSlice;
-import android.content.res.Resources;
-import android.net.Uri;
-import android.os.Handler;
-import android.os.Message;
-import android.provider.Settings;
-
-import androidx.test.InstrumentationRegistry;
-
-import com.android.internal.R;
-import com.android.server.compat.PlatformCompat;
-import com.android.server.testutils.TestUtils;
-
-import org.junit.After;
-import org.junit.Before;
-import org.junit.Test;
-import org.junit.runner.RunWith;
-import org.junit.runners.JUnit4;
-import org.mockito.ArgumentCaptor;
-import org.mockito.Mock;
-import org.mockito.junit.MockitoJUnit;
-import org.mockito.junit.MockitoRule;
-
-import java.io.File;
-import java.io.IOException;
-import java.io.InputStream;
-import java.nio.file.Files;
-import java.util.Arrays;
-import java.util.List;
-import java.util.Map;
-import java.util.function.Supplier;
-
-/** Unit test for {@link com.android.server.integrity.AppIntegrityManagerServiceImpl} */
-@RunWith(JUnit4.class)
-public class AppIntegrityManagerServiceImplTest {
- private static final String TEST_APP_PATH =
- "AppIntegrityManagerServiceImplTest/AppIntegrityManagerServiceTestApp.apk";
-
- private static final String TEST_APP_TWO_CERT_PATH =
- "AppIntegrityManagerServiceImplTest/DummyAppTwoCerts.apk";
-
- private static final String TEST_APP_SOURCE_STAMP_PATH =
- "AppIntegrityManagerServiceImplTest/SourceStampTestApk.apk";
-
- private static final String PACKAGE_MIME_TYPE = "application/vnd.android.package-archive";
- private static final String VERSION = "version";
- private static final String TEST_FRAMEWORK_PACKAGE = "com.android.frameworks.servicestests";
-
- private static final String PACKAGE_NAME = "com.test.app";
-
- private static final long VERSION_CODE = 100;
- private static final String INSTALLER = "com.long.random.test.installer.name";
-
- // These are obtained by running the test and checking logcat.
- private static final String APP_CERT =
- "F14CFECF5070874C05D3D2FA98E046BE20BDE02A0DC74BAF6B59C6A0E4C06850";
- // We use SHA256 for package names longer than 32 characters.
- private static final String INSTALLER_SHA256 =
- "30F41A7CBF96EE736A54DD6DF759B50ED3CC126ABCEF694E167C324F5976C227";
- private static final String SOURCE_STAMP_CERTIFICATE_HASH =
- "C6E737809CEF2B08CC6694892215F82A5E8FBC3C2A0F6212770310B90622D2D9";
-
- private static final String DUMMY_APP_TWO_CERTS_CERT_1 =
- "C0369C2A1096632429DFA8433068AECEAD00BAC337CA92A175036D39CC9AFE94";
- private static final String DUMMY_APP_TWO_CERTS_CERT_2 =
- "94366E0A80F3A3F0D8171A15760B88E228CD6E1101F0414C98878724FBE70147";
-
- private static final String PLAY_STORE_PKG = "com.android.vending";
- private static final String ADB_INSTALLER = "adb";
- private static final String PLAY_STORE_CERT = "play_store_cert";
-
- @org.junit.Rule public MockitoRule mMockitoRule = MockitoJUnit.rule();
-
- @Mock PackageManagerInternal mPackageManagerInternal;
- @Mock PlatformCompat mPlatformCompat;
- @Mock Context mMockContext;
- @Mock Resources mMockResources;
- @Mock Handler mHandler;
-
- private final Context mRealContext = InstrumentationRegistry.getTargetContext();
-
- private PackageManager mSpyPackageManager;
- private File mTestApk;
- private File mTestApkTwoCerts;
- private File mTestApkSourceStamp;
-
- // under test
- private AppIntegrityManagerServiceImpl mService;
-
- @Before
- public void setup() throws Exception {
- mTestApk = File.createTempFile("AppIntegrity", ".apk");
- try (InputStream inputStream = mRealContext.getAssets().open(TEST_APP_PATH)) {
- Files.copy(inputStream, mTestApk.toPath(), REPLACE_EXISTING);
- }
-
- mTestApkTwoCerts = File.createTempFile("AppIntegrityTwoCerts", ".apk");
- try (InputStream inputStream = mRealContext.getAssets().open(TEST_APP_TWO_CERT_PATH)) {
- Files.copy(inputStream, mTestApkTwoCerts.toPath(), REPLACE_EXISTING);
- }
-
- mTestApkSourceStamp = File.createTempFile("AppIntegritySourceStamp", ".apk");
- try (InputStream inputStream = mRealContext.getAssets().open(TEST_APP_SOURCE_STAMP_PATH)) {
- Files.copy(inputStream, mTestApkSourceStamp.toPath(), REPLACE_EXISTING);
- }
-
- mService =
- new AppIntegrityManagerServiceImpl(
- mMockContext,
- mPackageManagerInternal,
- mHandler);
-
- mSpyPackageManager = spy(mRealContext.getPackageManager());
- // setup mocks to prevent NPE
- when(mMockContext.getPackageManager()).thenReturn(mSpyPackageManager);
- when(mMockContext.getResources()).thenReturn(mMockResources);
- when(mMockResources.getStringArray(anyInt())).thenReturn(new String[] {});
- // These are needed to override the Settings.Global.get result.
- when(mMockContext.getContentResolver()).thenReturn(mRealContext.getContentResolver());
- setIntegrityCheckIncludesRuleProvider(true);
- }
-
- @After
- public void tearDown() throws Exception {
- mTestApk.delete();
- mTestApkTwoCerts.delete();
- mTestApkSourceStamp.delete();
- }
-
- @Test
- public void broadcastReceiverRegistration() throws Exception {
- allowlistUsAsRuleProvider();
- makeUsSystemApp();
- ArgumentCaptor<IntentFilter> intentFilterCaptor =
- ArgumentCaptor.forClass(IntentFilter.class);
-
- verify(mMockContext).registerReceiver(any(), intentFilterCaptor.capture(), any(), any());
- assertEquals(1, intentFilterCaptor.getValue().countActions());
- assertEquals(
- Intent.ACTION_PACKAGE_NEEDS_INTEGRITY_VERIFICATION,
- intentFilterCaptor.getValue().getAction(0));
- assertEquals(1, intentFilterCaptor.getValue().countDataTypes());
- assertEquals(PACKAGE_MIME_TYPE, intentFilterCaptor.getValue().getDataType(0));
- }
-
- @Test
- public void handleBroadcast_allow() throws Exception {
- allowlistUsAsRuleProvider();
- makeUsSystemApp();
- ArgumentCaptor<BroadcastReceiver> broadcastReceiverCaptor =
- ArgumentCaptor.forClass(BroadcastReceiver.class);
- verify(mMockContext)
- .registerReceiver(broadcastReceiverCaptor.capture(), any(), any(), any());
- Intent intent = makeVerificationIntent();
-
- broadcastReceiverCaptor.getValue().onReceive(mMockContext, intent);
- runJobInHandler();
-
- verify(mPackageManagerInternal)
- .setIntegrityVerificationResult(
- 1, PackageManagerInternal.INTEGRITY_VERIFICATION_ALLOW);
- }
-
- private void allowlistUsAsRuleProvider() {
- Resources mockResources = mock(Resources.class);
- when(mockResources.getStringArray(R.array.config_integrityRuleProviderPackages))
- .thenReturn(new String[] {TEST_FRAMEWORK_PACKAGE});
- when(mMockContext.getResources()).thenReturn(mockResources);
- }
-
- private void runJobInHandler() {
- ArgumentCaptor<Message> messageCaptor = ArgumentCaptor.forClass(Message.class);
- // sendMessageAtTime is the first non-final method in the call chain when "post" is invoked.
- verify(mHandler).sendMessageAtTime(messageCaptor.capture(), anyLong());
- messageCaptor.getValue().getCallback().run();
- }
-
- private void makeUsSystemApp() throws Exception {
- makeUsSystemApp(true);
- }
-
- private void makeUsSystemApp(boolean isSystemApp) throws Exception {
- PackageInfo packageInfo =
- mRealContext.getPackageManager().getPackageInfo(TEST_FRAMEWORK_PACKAGE, 0);
- if (isSystemApp) {
- packageInfo.applicationInfo.flags |= ApplicationInfo.FLAG_SYSTEM;
- } else {
- packageInfo.applicationInfo.flags &= ~ApplicationInfo.FLAG_SYSTEM;
- }
- doReturn(packageInfo)
- .when(mSpyPackageManager)
- .getPackageInfo(eq(TEST_FRAMEWORK_PACKAGE), anyInt());
- when(mMockContext.getPackageManager()).thenReturn(mSpyPackageManager);
- }
-
- private Intent makeVerificationIntent() throws Exception {
- PackageInfo packageInfo =
- mRealContext
- .getPackageManager()
- .getPackageInfo(
- TEST_FRAMEWORK_PACKAGE, PackageManager.GET_SIGNING_CERTIFICATES);
- doReturn(packageInfo).when(mSpyPackageManager).getPackageInfo(eq(INSTALLER), anyInt());
- doReturn(1).when(mSpyPackageManager).getPackageUid(eq(INSTALLER), anyInt());
- doReturn(new String[]{INSTALLER}).when(mSpyPackageManager).getPackagesForUid(anyInt());
- return makeVerificationIntent(INSTALLER);
- }
-
- private Intent makeVerificationIntent(String installer) throws Exception {
- Intent intent = new Intent();
- intent.setDataAndType(Uri.fromFile(mTestApk), PACKAGE_MIME_TYPE);
- intent.setAction(Intent.ACTION_PACKAGE_NEEDS_INTEGRITY_VERIFICATION);
- intent.putExtra(EXTRA_VERIFICATION_ID, 1);
- intent.putExtra(Intent.EXTRA_PACKAGE_NAME, PACKAGE_NAME);
- intent.putExtra(EXTRA_VERIFICATION_INSTALLER_PACKAGE, installer);
- intent.putExtra(
- EXTRA_VERIFICATION_INSTALLER_UID,
- mMockContext.getPackageManager().getPackageUid(installer, /* flags= */ 0));
- intent.putExtra(Intent.EXTRA_LONG_VERSION_CODE, VERSION_CODE);
- return intent;
- }
-
- private void setIntegrityCheckIncludesRuleProvider(boolean shouldInclude) throws Exception {
- int value = shouldInclude ? 1 : 0;
- Settings.Global.putInt(
- mRealContext.getContentResolver(),
- Settings.Global.INTEGRITY_CHECK_INCLUDES_RULE_PROVIDER,
- value);
- assertThat(
- Settings.Global.getInt(
- mRealContext.getContentResolver(),
- Settings.Global.INTEGRITY_CHECK_INCLUDES_RULE_PROVIDER,
- -1)
- == 1)
- .isEqualTo(shouldInclude);
- }
-}
diff --git a/services/tests/wmtests/src/com/android/server/wm/WindowManagerServiceTests.java b/services/tests/wmtests/src/com/android/server/wm/WindowManagerServiceTests.java
index a425401..bfa6cb8 100644
--- a/services/tests/wmtests/src/com/android/server/wm/WindowManagerServiceTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/WindowManagerServiceTests.java
@@ -29,6 +29,7 @@
import static android.view.Display.INVALID_DISPLAY;
import static android.view.WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE;
import static android.view.WindowManager.LayoutParams.FLAG_SECURE;
+import static android.view.WindowManager.LayoutParams.INPUT_FEATURE_RECEIVE_POWER_KEY_DOUBLE_PRESS;
import static android.view.WindowManager.LayoutParams.INPUT_FEATURE_SENSITIVE_FOR_PRIVACY;
import static android.view.WindowManager.LayoutParams.INPUT_FEATURE_SPY;
import static android.view.WindowManager.LayoutParams.INVALID_WINDOW_TYPE;
@@ -46,6 +47,7 @@
import static com.android.dx.mockito.inline.extended.ExtendedMockito.doReturn;
import static com.android.dx.mockito.inline.extended.ExtendedMockito.never;
import static com.android.dx.mockito.inline.extended.ExtendedMockito.spyOn;
+import static com.android.hardware.input.Flags.FLAG_OVERRIDE_POWER_KEY_BEHAVIOR_IN_FOCUSED_WINDOW;
import static com.android.server.wm.AppCompatConfiguration.LETTERBOX_BACKGROUND_APP_COLOR_BACKGROUND;
import static com.android.server.wm.AppCompatConfiguration.LETTERBOX_BACKGROUND_APP_COLOR_BACKGROUND_FLOATING;
import static com.android.server.wm.AppCompatConfiguration.LETTERBOX_BACKGROUND_SOLID_COLOR;
@@ -75,6 +77,7 @@
import android.app.ActivityThread;
import android.app.IApplicationThread;
import android.content.pm.ActivityInfo;
+import android.content.pm.PackageManager;
import android.graphics.Rect;
import android.os.Binder;
import android.os.IBinder;
@@ -1136,6 +1139,53 @@
}
@Test
+ @RequiresFlagsEnabled(FLAG_OVERRIDE_POWER_KEY_BEHAVIOR_IN_FOCUSED_WINDOW)
+ public void testUpdateInputChannel_sanitizeWithoutPermission_ThrowsError() {
+ final Session session = mock(Session.class);
+ final int callingUid = Process.FIRST_APPLICATION_UID;
+ final int callingPid = 1234;
+ final SurfaceControl surfaceControl = mock(SurfaceControl.class);
+ final IBinder window = new Binder();
+ final InputTransferToken inputTransferToken = mock(InputTransferToken.class);
+
+
+ final InputChannel inputChannel = new InputChannel();
+
+ assertThrows(IllegalArgumentException.class, () ->
+ mWm.grantInputChannel(session, callingUid, callingPid, DEFAULT_DISPLAY,
+ surfaceControl, window, null /* hostInputToken */, FLAG_NOT_FOCUSABLE,
+ 0 /* privateFlags */,
+ INPUT_FEATURE_RECEIVE_POWER_KEY_DOUBLE_PRESS,
+ TYPE_APPLICATION, null /* windowToken */, inputTransferToken,
+ "TestInputChannel", inputChannel));
+ }
+
+
+ @Test
+ @RequiresFlagsEnabled(FLAG_OVERRIDE_POWER_KEY_BEHAVIOR_IN_FOCUSED_WINDOW)
+ public void testUpdateInputChannel_sanitizeWithPermission_doesNotThrowError() {
+ final Session session = mock(Session.class);
+ final int callingUid = Process.FIRST_APPLICATION_UID;
+ final int callingPid = 1234;
+ final SurfaceControl surfaceControl = mock(SurfaceControl.class);
+ final IBinder window = new Binder();
+ final InputTransferToken inputTransferToken = mock(InputTransferToken.class);
+
+ doReturn(PackageManager.PERMISSION_GRANTED).when(mWm.mContext).checkPermission(
+ android.Manifest.permission.OVERRIDE_SYSTEM_KEY_BEHAVIOR_IN_FOCUSED_WINDOW,
+ callingPid,
+ callingUid);
+
+ final InputChannel inputChannel = new InputChannel();
+
+ mWm.grantInputChannel(session, callingUid, callingPid, DEFAULT_DISPLAY, surfaceControl,
+ window, null /* hostInputToken */, FLAG_NOT_FOCUSABLE, 0 /* privateFlags */,
+ INPUT_FEATURE_RECEIVE_POWER_KEY_DOUBLE_PRESS,
+ TYPE_APPLICATION, null /* windowToken */, inputTransferToken, "TestInputChannel",
+ inputChannel);
+ }
+
+ @Test
public void testUpdateInputChannel_allowSpyWindowForInputMonitorPermission() {
final Session session = mock(Session.class);
final int callingUid = Process.SYSTEM_UID;