Merge "Convert ShadeTouchHandlerTest to Kotlin" into main
diff --git a/core/java/android/app/Activity.java b/core/java/android/app/Activity.java
index 0947e33..5a3a8d5 100644
--- a/core/java/android/app/Activity.java
+++ b/core/java/android/app/Activity.java
@@ -21,6 +21,7 @@
import static android.Manifest.permission.INTERACT_ACROSS_USERS;
import static android.Manifest.permission.INTERACT_ACROSS_USERS_FULL;
import static android.Manifest.permission.INTERNAL_SYSTEM_WINDOW;
+import static android.app.Instrumentation.DEBUG_FINISH_ACTIVITY;
import static android.app.WindowConfiguration.WINDOWING_MODE_PINNED;
import static android.app.WindowConfiguration.inMultiWindowMode;
import static android.os.Process.myUid;
@@ -7297,6 +7298,9 @@
*/
@UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
private void finish(int finishTask) {
+ if (DEBUG_FINISH_ACTIVITY) {
+ Log.d("Instrumentation", "finishActivity: finishTask=" + finishTask, new Throwable());
+ }
if (mParent == null) {
int resultCode;
Intent resultData;
diff --git a/core/java/android/app/Instrumentation.java b/core/java/android/app/Instrumentation.java
index db216b1..be27046 100644
--- a/core/java/android/app/Instrumentation.java
+++ b/core/java/android/app/Instrumentation.java
@@ -107,6 +107,8 @@
// If set, will print the stack trace for activity starts within the process
static final boolean DEBUG_START_ACTIVITY = Build.IS_DEBUGGABLE &&
SystemProperties.getBoolean("persist.wm.debug.start_activity", false);
+ static final boolean DEBUG_FINISH_ACTIVITY = Build.IS_DEBUGGABLE &&
+ SystemProperties.getBoolean("persist.wm.debug.finish_activity", false);
/**
* @hide
diff --git a/core/java/android/database/CursorWindow.java b/core/java/android/database/CursorWindow.java
index ba356bb..6514872 100644
--- a/core/java/android/database/CursorWindow.java
+++ b/core/java/android/database/CursorWindow.java
@@ -16,6 +16,8 @@
package android.database;
+import static java.util.Objects.requireNonNull;
+
import android.annotation.BytesLong;
import android.annotation.IntRange;
import android.compat.annotation.UnsupportedAppUsage;
@@ -640,6 +642,7 @@
*/
public boolean putBlob(byte[] value,
@IntRange(from = 0) int row, @IntRange(from = 0) int column) {
+ requireNonNull(value);
acquireReference();
try {
return nativePutBlob(mWindowPtr, value, row - mStartPos, column);
@@ -658,6 +661,7 @@
*/
public boolean putString(String value,
@IntRange(from = 0) int row, @IntRange(from = 0) int column) {
+ requireNonNull(value);
acquireReference();
try {
return nativePutString(mWindowPtr, value, row - mStartPos, column);
diff --git a/core/java/android/hardware/Camera.java b/core/java/android/hardware/Camera.java
index cbac912..ca3e3d2 100644
--- a/core/java/android/hardware/Camera.java
+++ b/core/java/android/hardware/Camera.java
@@ -569,7 +569,6 @@
return native_setup(
new WeakReference<>(this),
cameraId,
- ActivityThread.currentOpPackageName(),
rotationOverride,
forceSlowJpegMode,
clientAttribution.getParcel(),
@@ -660,7 +659,6 @@
private native int native_setup(
Object cameraThis,
int cameraId,
- String packageName,
int rotationOverride,
boolean forceSlowJpegMode,
Parcel clientAttributionParcel,
diff --git a/core/java/android/hardware/camera2/CameraManager.java b/core/java/android/hardware/camera2/CameraManager.java
index 2dbd4b8..6201359 100644
--- a/core/java/android/hardware/camera2/CameraManager.java
+++ b/core/java/android/hardware/camera2/CameraManager.java
@@ -980,6 +980,8 @@
clientAttribution.uid = USE_CALLING_UID;
clientAttribution.pid = USE_CALLING_PID;
clientAttribution.deviceId = contextAttribution.deviceId;
+ clientAttribution.packageName = mContext.getOpPackageName();
+ clientAttribution.attributionTag = mContext.getAttributionTag();
clientAttribution.next = new AttributionSourceState[0];
return clientAttribution;
}
@@ -1041,8 +1043,6 @@
cameraService.connectDevice(
callbacks,
cameraId,
- mContext.getOpPackageName(),
- mContext.getAttributionTag(),
oomScoreOffset,
mContext.getApplicationInfo().targetSdkVersion,
rotationOverride,
diff --git a/core/jni/android_hardware_Camera.cpp b/core/jni/android_hardware_Camera.cpp
index b8fd3d0..3f74fac 100644
--- a/core/jni/android_hardware_Camera.cpp
+++ b/core/jni/android_hardware_Camera.cpp
@@ -582,8 +582,8 @@
// connect to camera service
static jint android_hardware_Camera_native_setup(JNIEnv *env, jobject thiz, jobject weak_this,
- jint cameraId, jstring clientPackageName,
- jint rotationOverride, jboolean forceSlowJpegMode,
+ jint cameraId, jint rotationOverride,
+ jboolean forceSlowJpegMode,
jobject jClientAttributionParcel,
jint devicePolicy) {
AttributionSourceState clientAttribution;
@@ -591,16 +591,8 @@
return -EACCES;
}
- // Convert jstring to String16
- const char16_t *rawClientName = reinterpret_cast<const char16_t*>(
- env->GetStringChars(clientPackageName, NULL));
- jsize rawClientNameLen = env->GetStringLength(clientPackageName);
- std::string clientName = toStdString(rawClientName, rawClientNameLen);
- env->ReleaseStringChars(clientPackageName,
- reinterpret_cast<const jchar*>(rawClientName));
-
int targetSdkVersion = android_get_application_target_sdk_version();
- sp<Camera> camera = Camera::connect(cameraId, clientName, targetSdkVersion, rotationOverride,
+ sp<Camera> camera = Camera::connect(cameraId, targetSdkVersion, rotationOverride,
forceSlowJpegMode, clientAttribution, devicePolicy);
if (camera == NULL) {
return -EACCES;
@@ -1089,7 +1081,7 @@
(void *)android_hardware_Camera_getNumberOfCameras},
{"_getCameraInfo", "(IILandroid/os/Parcel;ILandroid/hardware/Camera$CameraInfo;)V",
(void *)android_hardware_Camera_getCameraInfo},
- {"native_setup", "(Ljava/lang/Object;ILjava/lang/String;IZLandroid/os/Parcel;I)I",
+ {"native_setup", "(Ljava/lang/Object;IIZLandroid/os/Parcel;I)I",
(void *)android_hardware_Camera_native_setup},
{"native_release", "()V", (void *)android_hardware_Camera_release},
{"setPreviewSurface", "(Landroid/view/Surface;)V",
diff --git a/libs/WindowManager/Jetpack/src/androidx/window/extensions/embedding/DividerPresenter.java b/libs/WindowManager/Jetpack/src/androidx/window/extensions/embedding/DividerPresenter.java
index 822a07c..544f0f3 100644
--- a/libs/WindowManager/Jetpack/src/androidx/window/extensions/embedding/DividerPresenter.java
+++ b/libs/WindowManager/Jetpack/src/androidx/window/extensions/embedding/DividerPresenter.java
@@ -894,9 +894,7 @@
private static boolean isDraggingToFullscreenAllowed(
@NonNull DividerAttributes dividerAttributes) {
- // TODO(b/293654166) Use DividerAttributes.isDraggingToFullscreenAllowed when extension is
- // updated to v7.
- return false;
+ return dividerAttributes.isDraggingToFullscreenAllowed();
}
/**
diff --git a/libs/WindowManager/Shell/shared/src/com/android/wm/shell/shared/desktopmode/DesktopModeFlags.kt b/libs/WindowManager/Shell/shared/src/com/android/wm/shell/shared/desktopmode/DesktopModeFlags.kt
index 5983168..8c2cfd1e 100644
--- a/libs/WindowManager/Shell/shared/src/com/android/wm/shell/shared/desktopmode/DesktopModeFlags.kt
+++ b/libs/WindowManager/Shell/shared/src/com/android/wm/shell/shared/desktopmode/DesktopModeFlags.kt
@@ -37,10 +37,6 @@
DESKTOP_WINDOWING_MODE(Flags::enableDesktopWindowingMode, true),
WALLPAPER_ACTIVITY(Flags::enableDesktopWindowingWallpaperActivity, true);
- // Local cache for toggle override, which is initialized once on its first access. It needs to be
- // refreshed only on reboots as overridden state takes effect on reboots.
- private var cachedToggleOverride: ToggleOverride? = null
-
/**
* Determines state of flag based on the actual flag and desktop mode developer option overrides.
*
@@ -138,13 +134,19 @@
}
}
- private companion object {
- const val TAG = "DesktopModeFlags"
+ companion object {
+ private const val TAG = "DesktopModeFlags"
/**
* Key for non-persistent System Property which is used to store desktop windowing developer
* option overrides.
*/
- const val SYSTEM_PROPERTY_OVERRIDE_KEY = "sys.wmshell.desktopmode.dev_toggle_override"
+ private const val SYSTEM_PROPERTY_OVERRIDE_KEY = "sys.wmshell.desktopmode.dev_toggle_override"
+
+ /**
+ * Local cache for toggle override, which is initialized once on its first access. It needs to
+ * be refreshed only on reboots as overridden state takes effect on reboots.
+ */
+ private var cachedToggleOverride: ToggleOverride? = null
}
}
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/docs/debugging.md b/libs/WindowManager/Shell/src/com/android/wm/shell/docs/debugging.md
index b1cbe8d..3572d16 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/docs/debugging.md
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/docs/debugging.md
@@ -97,7 +97,7 @@
adb logcat -s "SurfaceControlRegistry"
```
-## Tracing activity starts in the app process
+## Tracing activity starts & finishes in the app process
It's sometimes useful to know when to see a stack trace of when an activity starts in the app code
(ie. if you are repro'ing a bug related to activity starts). You can enable this system property to
@@ -113,6 +113,19 @@
adb reboot
```
+Likewise, to trace where a finish() call may be made in the app process, you can enable this system
+property:
+```shell
+# Enabling
+adb shell setprop persist.wm.debug.finish_activity true
+adb reboot
+adb logcat -s "Instrumentation"
+
+# Disabling
+adb shell setprop persist.wm.debug.finish_activity \"\"
+adb reboot
+```
+
## Dumps
Because the Shell library is built as a part of SystemUI, dumping the state is currently done as a
diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/shared/desktopmode/DesktopModeFlagsTest.kt b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/shared/desktopmode/DesktopModeFlagsTest.kt
index 4661042..00f37da 100644
--- a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/shared/desktopmode/DesktopModeFlagsTest.kt
+++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/shared/desktopmode/DesktopModeFlagsTest.kt
@@ -427,15 +427,10 @@
}
private fun resetCache() {
- val cachedToggleOverrideDesktopMode =
- DESKTOP_WINDOWING_MODE::class.java.getDeclaredField("cachedToggleOverride")
- cachedToggleOverrideDesktopMode.isAccessible = true
- cachedToggleOverrideDesktopMode.set(DESKTOP_WINDOWING_MODE, null)
-
- val cachedToggleOverrideWallpaperActivity =
- WALLPAPER_ACTIVITY::class.java.getDeclaredField("cachedToggleOverride")
- cachedToggleOverrideWallpaperActivity.isAccessible = true
- cachedToggleOverrideWallpaperActivity.set(WALLPAPER_ACTIVITY, null)
+ val cachedToggleOverride =
+ DesktopModeFlags::class.java.getDeclaredField("cachedToggleOverride")
+ cachedToggleOverride.isAccessible = true
+ cachedToggleOverride.set(null, null)
// Clear override cache stored in System property
System.clearProperty(SYSTEM_PROPERTY_OVERRIDE_KEY)
diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/windowdecor/DesktopModeWindowDecorViewModelTests.kt b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/windowdecor/DesktopModeWindowDecorViewModelTests.kt
index 316cefa1..b1803e9 100644
--- a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/windowdecor/DesktopModeWindowDecorViewModelTests.kt
+++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/windowdecor/DesktopModeWindowDecorViewModelTests.kt
@@ -360,7 +360,7 @@
isTopActivityStyleFloating = true
numActivities = 1
}
- doReturn(true).`when` { DesktopModeStatus.isDesktopModeSupported(any()) }
+ doReturn(true).`when` { DesktopModeStatus.canEnterDesktopMode(any()) }
setUpMockDecorationsForTasks(task)
onTaskOpening(task)
diff --git a/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/helpers/CameraTestUtils.java b/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/helpers/CameraTestUtils.java
index 102d21a..43acbb1 100644
--- a/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/helpers/CameraTestUtils.java
+++ b/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/helpers/CameraTestUtils.java
@@ -2246,6 +2246,8 @@
clientAttribution.uid = -1; // USE_CALLING_UID
clientAttribution.pid = -1; // USE_CALLING_PID
clientAttribution.deviceId = contextAttribution.deviceId;
+ clientAttribution.packageName = context.getOpPackageName();
+ clientAttribution.attributionTag = context.getAttributionTag();
clientAttribution.next = new AttributionSourceState[0];
return clientAttribution;
}
diff --git a/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/integration/CameraBinderTest.java b/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/integration/CameraBinderTest.java
index ad3374a..ac85ab7 100644
--- a/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/integration/CameraBinderTest.java
+++ b/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/integration/CameraBinderTest.java
@@ -169,10 +169,8 @@
ICameraClient dummyCallbacks = new DummyCameraClient();
- String clientPackageName = getContext().getPackageName();
-
ICamera cameraUser = mUtils.getCameraService()
- .connect(dummyCallbacks, cameraId, clientPackageName,
+ .connect(dummyCallbacks, cameraId,
getContext().getApplicationInfo().targetSdkVersion,
ICameraService.ROTATION_OVERRIDE_NONE,
/*forceSlowJpegMode*/false,
@@ -267,8 +265,6 @@
ICameraDeviceCallbacks dummyCallbacks = new DummyCameraDeviceCallbacks();
- String clientPackageName = getContext().getPackageName();
- String clientAttributionTag = getContext().getAttributionTag();
AttributionSourceState clientAttribution =
CameraTestUtils.getClientAttribution(mContext);
clientAttribution.deviceId = DEVICE_ID_DEFAULT;
@@ -277,7 +273,6 @@
ICameraDeviceUser cameraUser =
mUtils.getCameraService().connectDevice(
dummyCallbacks, String.valueOf(cameraId),
- clientPackageName, clientAttributionTag,
0 /*oomScoreOffset*/,
getContext().getApplicationInfo().targetSdkVersion,
ICameraService.ROTATION_OVERRIDE_NONE, clientAttribution,
diff --git a/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/integration/CameraDeviceBinderTest.java b/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/integration/CameraDeviceBinderTest.java
index 0ab1ee9..35ad924 100644
--- a/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/integration/CameraDeviceBinderTest.java
+++ b/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/integration/CameraDeviceBinderTest.java
@@ -242,9 +242,6 @@
ICameraDeviceCallbacks.Stub dummyCallbacks = new DummyCameraDeviceCallbacks();
- String clientPackageName = getContext().getPackageName();
- String clientAttributionTag = getContext().getAttributionTag();
-
mMockCb = spy(dummyCallbacks);
AttributionSourceState clientAttribution = CameraTestUtils.getClientAttribution(mContext);
@@ -252,7 +249,6 @@
clientAttribution.uid = ICameraService.USE_CALLING_UID;
mCameraUser = mUtils.getCameraService().connectDevice(mMockCb, mCameraId,
- clientPackageName, clientAttributionTag,
/*oomScoreOffset*/0, getContext().getApplicationInfo().targetSdkVersion,
ICameraService.ROTATION_OVERRIDE_NONE, clientAttribution, DEVICE_POLICY_DEFAULT);
assertNotNull(String.format("Camera %s was null", mCameraId), mCameraUser);
diff --git a/packages/SettingsProvider/src/com/android/providers/settings/SettingsState.java b/packages/SettingsProvider/src/com/android/providers/settings/SettingsState.java
index 861c405..fd4fc20 100644
--- a/packages/SettingsProvider/src/com/android/providers/settings/SettingsState.java
+++ b/packages/SettingsProvider/src/com/android/providers/settings/SettingsState.java
@@ -740,8 +740,6 @@
// The settings provider must hold its lock when calling here.
@GuardedBy("mLock")
public void removeSettingsForPackageLocked(String packageName) {
- boolean removedSomething = false;
-
final int settingCount = mSettings.size();
for (int i = settingCount - 1; i >= 0; i--) {
String name = mSettings.keyAt(i);
@@ -752,14 +750,9 @@
}
Setting setting = mSettings.valueAt(i);
if (packageName.equals(setting.packageName)) {
- mSettings.removeAt(i);
- removedSomething = true;
+ deleteSettingLocked(setting.name);
}
}
-
- if (removedSomething) {
- scheduleWriteIfNeededLocked();
- }
}
// The settings provider must hold its lock when calling here.
diff --git a/packages/SettingsProvider/test/src/com/android/providers/settings/SettingsStateTest.java b/packages/SettingsProvider/test/src/com/android/providers/settings/SettingsStateTest.java
index 4b4ced3..48ce49d 100644
--- a/packages/SettingsProvider/test/src/com/android/providers/settings/SettingsStateTest.java
+++ b/packages/SettingsProvider/test/src/com/android/providers/settings/SettingsStateTest.java
@@ -988,7 +988,40 @@
}
@Test
- public void testGetFlagOverrideToSync() {
+ public void testMemoryUsagePerPackage_StatsUpdatedOnAppDataCleared() {
+ SettingsState settingsState =
+ new SettingsState(
+ InstrumentationRegistry.getContext(), mLock, mSettingsFile, 1,
+ SettingsState.MAX_BYTES_PER_APP_PACKAGE_LIMITED, Looper.getMainLooper());
+ final String testKey1 = SETTING_NAME;
+ final String testKey2 = SETTING_NAME + "_2";
+ final String testValue1 = Strings.repeat("A", 9000);
+ final String testValue2 = Strings.repeat("A", 9001);
+ final String packageName = "p";
+ // Inserting the first setting should be okay
+ settingsState.insertSettingLocked(testKey1, testValue1, null, true, packageName);
+ int expectedMemUsageForPackage = (testKey1.length() + testValue1.length()
+ + testValue1.length() /* size for default */) * Character.BYTES;
+ assertEquals(expectedMemUsageForPackage, settingsState.getMemoryUsage(packageName));
+ // Inserting the second setting should fail
+ try {
+ settingsState.insertSettingLocked(testKey2, testValue2, null, true, packageName);
+ fail("Should throw because it exceeded max memory usage per package");
+ } catch (IllegalStateException ex) {
+ assertTrue(ex.getMessage().startsWith("You are adding too many system settings."));
+ }
+ // Now clear app data and check that the memory usage is cleared
+ settingsState.removeSettingsForPackageLocked(packageName);
+ assertEquals(0, settingsState.getMemoryUsage(packageName));
+ // Try inserting the second setting again and it should go through
+ settingsState.insertSettingLocked(testKey2, testValue2, null, true, packageName);
+ expectedMemUsageForPackage = (testKey2.length() + testValue2.length()
+ + testValue2.length() /* size for default */) * Character.BYTES;
+ assertEquals(expectedMemUsageForPackage, settingsState.getMemoryUsage(packageName));
+ }
+
+ @Test
+ public void testGetFlagOverrideToSync() {
int configKey = SettingsState.makeKey(SettingsState.SETTINGS_TYPE_CONFIG, 0);
Object lock = new Object();
SettingsState settingsState =
diff --git a/packages/SystemUI/compose/features/src/com/android/systemui/keyguard/ui/composable/LockscreenContent.kt b/packages/SystemUI/compose/features/src/com/android/systemui/keyguard/ui/composable/LockscreenContent.kt
index 887e349..25e91be 100644
--- a/packages/SystemUI/compose/features/src/com/android/systemui/keyguard/ui/composable/LockscreenContent.kt
+++ b/packages/SystemUI/compose/features/src/com/android/systemui/keyguard/ui/composable/LockscreenContent.kt
@@ -16,6 +16,7 @@
package com.android.systemui.keyguard.ui.composable
+import androidx.compose.foundation.layout.Box
import androidx.compose.runtime.Composable
import androidx.compose.runtime.DisposableEffect
import androidx.compose.runtime.getValue
@@ -48,6 +49,16 @@
fun SceneScope.Content(
modifier: Modifier = Modifier,
) {
+ val isContentVisible: Boolean by viewModel.isContentVisible.collectAsStateWithLifecycle()
+ if (!isContentVisible) {
+ // If the content isn't supposed to be visible, show a large empty box as it's needed
+ // for scene transition animations (can't just skip rendering everything or shared
+ // elements won't have correct final/initial bounds from animating in and out of the
+ // lockscreen scene).
+ Box(modifier)
+ return
+ }
+
val coroutineScope = rememberCoroutineScope()
val blueprintId by viewModel.blueprintId(coroutineScope).collectAsStateWithLifecycle()
val view = LocalView.current
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/ui/viewmodel/LockscreenContentViewModelTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/ui/viewmodel/LockscreenContentViewModelTest.kt
index de4b999..875e9e0 100644
--- a/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/ui/viewmodel/LockscreenContentViewModelTest.kt
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/ui/viewmodel/LockscreenContentViewModelTest.kt
@@ -14,6 +14,8 @@
* limitations under the License.
*/
+@file:OptIn(ExperimentalCoroutinesApi::class)
+
package com.android.systemui.keyguard.ui.viewmodel
import android.platform.test.flag.junit.FlagsParameterization
@@ -27,10 +29,13 @@
import com.android.systemui.flags.andSceneContainer
import com.android.systemui.flags.fakeFeatureFlagsClassic
import com.android.systemui.keyguard.data.repository.fakeKeyguardClockRepository
+import com.android.systemui.keyguard.data.repository.keyguardOcclusionRepository
import com.android.systemui.keyguard.shared.model.ClockSize
import com.android.systemui.kosmos.Kosmos
import com.android.systemui.kosmos.testScope
import com.android.systemui.res.R
+import com.android.systemui.scene.domain.interactor.sceneInteractor
+import com.android.systemui.scene.shared.model.Scenes
import com.android.systemui.shade.data.repository.shadeRepository
import com.android.systemui.shade.shared.model.ShadeMode
import com.android.systemui.testKosmos
@@ -38,6 +43,8 @@
import com.android.systemui.util.mockito.whenever
import com.google.common.truth.Truth.assertThat
import java.util.Locale
+import kotlinx.coroutines.ExperimentalCoroutinesApi
+import kotlinx.coroutines.test.runCurrent
import kotlinx.coroutines.test.runTest
import org.junit.Before
import org.junit.Test
@@ -201,6 +208,44 @@
}
}
+ @Test
+ fun isContentVisible_whenNotOccluded_visible() =
+ with(kosmos) {
+ testScope.runTest {
+ val isContentVisible by collectLastValue(underTest.isContentVisible)
+
+ keyguardOcclusionRepository.setShowWhenLockedActivityInfo(false, null)
+ runCurrent()
+ assertThat(isContentVisible).isTrue()
+ }
+ }
+
+ @Test
+ fun isContentVisible_whenOccluded_notVisible() =
+ with(kosmos) {
+ testScope.runTest {
+ val isContentVisible by collectLastValue(underTest.isContentVisible)
+
+ keyguardOcclusionRepository.setShowWhenLockedActivityInfo(true, null)
+ runCurrent()
+ assertThat(isContentVisible).isFalse()
+ }
+ }
+
+ @Test
+ fun isContentVisible_whenOccluded_notVisible_evenIfShadeShown() =
+ with(kosmos) {
+ testScope.runTest {
+ val isContentVisible by collectLastValue(underTest.isContentVisible)
+ keyguardOcclusionRepository.setShowWhenLockedActivityInfo(true, null)
+ runCurrent()
+
+ sceneInteractor.snapToScene(Scenes.Shade, "")
+ runCurrent()
+ assertThat(isContentVisible).isFalse()
+ }
+ }
+
private fun prepareConfiguration(): Int {
val configuration = context.resources.configuration
configuration.setLayoutDirection(Locale.US)
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/LockscreenContentViewModel.kt b/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/LockscreenContentViewModel.kt
index 1de0abe..8a29f96 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/LockscreenContentViewModel.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/LockscreenContentViewModel.kt
@@ -25,6 +25,7 @@
import com.android.systemui.keyguard.domain.interactor.KeyguardClockInteractor
import com.android.systemui.keyguard.shared.model.ClockSize
import com.android.systemui.res.R
+import com.android.systemui.scene.domain.interactor.SceneContainerOcclusionInteractor
import com.android.systemui.shade.domain.interactor.ShadeInteractor
import com.android.systemui.shade.shared.model.ShadeMode
import com.android.systemui.unfold.domain.interactor.UnfoldTransitionInteractor
@@ -48,6 +49,7 @@
val shadeInteractor: ShadeInteractor,
@Application private val applicationScope: CoroutineScope,
unfoldTransitionInteractor: UnfoldTransitionInteractor,
+ occlusionInteractor: SceneContainerOcclusionInteractor,
) {
@VisibleForTesting val clockSize = clockInteractor.clockSize
@@ -93,6 +95,16 @@
initialValue = UnfoldTranslations(),
)
+ /** Whether the content of the scene UI should be shown. */
+ val isContentVisible: StateFlow<Boolean> =
+ occlusionInteractor.isOccludingActivityShown
+ .map { !it }
+ .stateIn(
+ scope = applicationScope,
+ started = SharingStarted.WhileSubscribed(),
+ initialValue = true,
+ )
+
fun getSmartSpacePaddingTop(resources: Resources): Int {
return if (clockSize.value == ClockSize.LARGE) {
resources.getDimensionPixelSize(R.dimen.keyguard_smartspace_top_offset) +
diff --git a/packages/SystemUI/src/com/android/systemui/scene/domain/interactor/SceneContainerOcclusionInteractor.kt b/packages/SystemUI/src/com/android/systemui/scene/domain/interactor/SceneContainerOcclusionInteractor.kt
index 233e9b5..2d510e1 100644
--- a/packages/SystemUI/src/com/android/systemui/scene/domain/interactor/SceneContainerOcclusionInteractor.kt
+++ b/packages/SystemUI/src/com/android/systemui/scene/domain/interactor/SceneContainerOcclusionInteractor.kt
@@ -43,8 +43,14 @@
sceneInteractor: SceneInteractor,
keyguardTransitionInteractor: KeyguardTransitionInteractor,
) {
- /** Whether a show-when-locked activity is at the top of the current activity stack. */
- private val isOccludingActivityShown: StateFlow<Boolean> =
+ /**
+ * Whether a show-when-locked activity is at the top of the current activity stack.
+ *
+ * Note: this isn't enough to figure out whether the scene container UI should be invisible as
+ * that also depends on the things like the state of AOD and the current scene. If the code
+ * needs that, [invisibleDueToOcclusion] should be collected instead.
+ */
+ val isOccludingActivityShown: StateFlow<Boolean> =
keyguardOcclusionInteractor.isShowWhenLockedActivityOnTop.stateIn(
scope = applicationScope,
started = SharingStarted.WhileSubscribed(),
@@ -69,6 +75,9 @@
/**
* Whether the scene container should become invisible due to "occlusion" by an in-foreground
* "show when locked" activity.
+ *
+ * Note: this returns `false` when an overlaid scene (like shade or QS) is shown above the
+ * occluding activity.
*/
val invisibleDueToOcclusion: StateFlow<Boolean> =
combine(
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/KeyguardCoordinator.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/KeyguardCoordinator.kt
index 5a1146d..1434dc0 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/KeyguardCoordinator.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/KeyguardCoordinator.kt
@@ -14,8 +14,6 @@
* limitations under the License.
*/
-@file:OptIn(ExperimentalCoroutinesApi::class)
-
package com.android.systemui.statusbar.notification.collection.coordinator
import android.app.NotificationManager
@@ -27,9 +25,10 @@
import com.android.systemui.dagger.qualifiers.Background
import com.android.systemui.dump.DumpManager
import com.android.systemui.keyguard.data.repository.KeyguardRepository
-import com.android.systemui.keyguard.data.repository.KeyguardTransitionRepository
+import com.android.systemui.keyguard.domain.interactor.KeyguardTransitionInteractor
import com.android.systemui.keyguard.shared.model.KeyguardState
import com.android.systemui.plugins.statusbar.StatusBarStateController
+import com.android.systemui.scene.shared.model.Scenes
import com.android.systemui.statusbar.StatusBarState
import com.android.systemui.statusbar.expansionChanges
import com.android.systemui.statusbar.notification.collection.GroupEntry
@@ -58,7 +57,6 @@
import kotlin.time.Duration.Companion.seconds
import kotlinx.coroutines.CoroutineDispatcher
import kotlinx.coroutines.CoroutineScope
-import kotlinx.coroutines.ExperimentalCoroutinesApi
import kotlinx.coroutines.Job
import kotlinx.coroutines.coroutineScope
import kotlinx.coroutines.delay
@@ -89,7 +87,7 @@
private val headsUpManager: HeadsUpManager,
private val keyguardNotificationVisibilityProvider: KeyguardNotificationVisibilityProvider,
private val keyguardRepository: KeyguardRepository,
- private val keyguardTransitionRepository: KeyguardTransitionRepository,
+ private val keyguardTransitionInteractor: KeyguardTransitionInteractor,
private val logger: KeyguardCoordinatorLogger,
@Application private val scope: CoroutineScope,
private val sectionHeaderVisibilityProvider: SectionHeaderVisibilityProvider,
@@ -126,8 +124,9 @@
private suspend fun trackSeenNotifications() {
// Whether or not keyguard is visible (or occluded).
val isKeyguardPresent: Flow<Boolean> =
- keyguardTransitionRepository.transitions
- .map { step -> step.to != KeyguardState.GONE }
+ keyguardTransitionInteractor
+ .transitionValue(Scenes.Gone, stateWithoutSceneContainer = KeyguardState.GONE)
+ .map { it == 0f }
.distinctUntilChanged()
.onEach { trackingUnseen -> logger.logTrackingUnseen(trackingUnseen) }
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/ui/viewmodel/SharedNotificationContainerViewModel.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/ui/viewmodel/SharedNotificationContainerViewModel.kt
index 534d9d2..900201f 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/ui/viewmodel/SharedNotificationContainerViewModel.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/ui/viewmodel/SharedNotificationContainerViewModel.kt
@@ -186,6 +186,7 @@
interactor.configurationBasedDimensions
.map {
when {
+ !it.useSplitShade -> 0
it.useLargeScreenHeader -> it.marginTopLargeScreen
else -> it.marginTop
}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/biometrics/ui/viewmodel/PromptViewModelTest.kt b/packages/SystemUI/tests/src/com/android/systemui/biometrics/ui/viewmodel/PromptViewModelTest.kt
index 97f5efc..677d1fd 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/biometrics/ui/viewmodel/PromptViewModelTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/biometrics/ui/viewmodel/PromptViewModelTest.kt
@@ -1799,8 +1799,10 @@
when {
fingerprint != null && face != null -> "coex"
fingerprint != null && fingerprint.isAnySidefpsType -> "fingerprint only, sideFps"
- fingerprint != null && !fingerprint.isAnySidefpsType ->
- "fingerprint only, non-sideFps"
+ fingerprint != null && fingerprint.isAnyUdfpsType -> "fingerprint only, udfps"
+ fingerprint != null &&
+ fingerprint.sensorType == FingerprintSensorProperties.TYPE_REAR ->
+ "fingerprint only, rearFps"
face != null -> "face only"
else -> "?"
}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/coordinator/KeyguardCoordinatorTest.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/coordinator/KeyguardCoordinatorTest.kt
index 25533d8..d87b3e2 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/coordinator/KeyguardCoordinatorTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/coordinator/KeyguardCoordinatorTest.kt
@@ -19,16 +19,23 @@
import android.app.Notification
import android.os.UserHandle
+import android.platform.test.flag.junit.FlagsParameterization
import android.provider.Settings
-import androidx.test.ext.junit.runners.AndroidJUnit4
import androidx.test.filters.SmallTest
import com.android.systemui.SysuiTestCase
import com.android.systemui.dump.DumpManager
-import com.android.systemui.log.logcatLogBuffer
+import com.android.systemui.flags.andSceneContainer
import com.android.systemui.keyguard.data.repository.FakeKeyguardRepository
-import com.android.systemui.keyguard.data.repository.FakeKeyguardTransitionRepository
+import com.android.systemui.keyguard.data.repository.fakeKeyguardTransitionRepository
+import com.android.systemui.keyguard.domain.interactor.keyguardTransitionInteractor
import com.android.systemui.keyguard.shared.model.KeyguardState
+import com.android.systemui.keyguard.shared.model.TransitionStep
+import com.android.systemui.kosmos.Kosmos
+import com.android.systemui.log.logcatLogBuffer
import com.android.systemui.plugins.statusbar.StatusBarStateController
+import com.android.systemui.scene.data.repository.Idle
+import com.android.systemui.scene.data.repository.setTransition
+import com.android.systemui.scene.shared.model.Scenes
import com.android.systemui.statusbar.StatusBarState
import com.android.systemui.statusbar.notification.collection.GroupEntryBuilder
import com.android.systemui.statusbar.notification.collection.NotifPipeline
@@ -49,6 +56,8 @@
import com.android.systemui.util.mockito.withArgCaptor
import com.android.systemui.util.settings.FakeSettings
import com.google.common.truth.Truth.assertThat
+import java.util.function.Consumer
+import kotlin.time.Duration.Companion.seconds
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.ExperimentalCoroutinesApi
import kotlinx.coroutines.test.TestCoroutineScheduler
@@ -62,22 +71,28 @@
import org.mockito.Mockito.clearInvocations
import org.mockito.Mockito.never
import org.mockito.Mockito.verify
-import java.util.function.Consumer
-import kotlin.time.Duration.Companion.seconds
import org.mockito.Mockito.`when` as whenever
+import platform.test.runner.parameterized.ParameterizedAndroidJunit4
+import platform.test.runner.parameterized.Parameters
@SmallTest
-@RunWith(AndroidJUnit4::class)
-class KeyguardCoordinatorTest : SysuiTestCase() {
+@RunWith(ParameterizedAndroidJunit4::class)
+class KeyguardCoordinatorTest(flags: FlagsParameterization) : SysuiTestCase() {
+
+ private val kosmos = Kosmos()
private val headsUpManager: HeadsUpManager = mock()
private val keyguardNotifVisibilityProvider: KeyguardNotificationVisibilityProvider = mock()
private val keyguardRepository = FakeKeyguardRepository()
- private val keyguardTransitionRepository = FakeKeyguardTransitionRepository()
+ private val keyguardTransitionRepository = kosmos.fakeKeyguardTransitionRepository
private val notifPipeline: NotifPipeline = mock()
private val sectionHeaderVisibilityProvider: SectionHeaderVisibilityProvider = mock()
private val statusBarStateController: StatusBarStateController = mock()
+ init {
+ mSetFlagsRule.setFlagsParameterization(flags)
+ }
+
@Test
fun testSetSectionHeadersVisibleInShade() = runKeyguardCoordinatorTest {
clearInvocations(sectionHeaderVisibilityProvider)
@@ -147,10 +162,9 @@
keyguardRepository.setKeyguardShowing(false)
whenever(statusBarStateController.isExpanded).thenReturn(false)
runKeyguardCoordinatorTest {
- keyguardTransitionRepository.sendTransitionSteps(
- from = KeyguardState.LOCKSCREEN,
- to = KeyguardState.GONE,
- this.testScheduler,
+ kosmos.setTransition(
+ sceneTransition = Idle(Scenes.Gone),
+ stateTransition = TransitionStep(KeyguardState.LOCKSCREEN, KeyguardState.GONE)
)
// WHEN: A notification is posted
@@ -163,24 +177,20 @@
// WHEN: The keyguard is now showing
keyguardRepository.setKeyguardShowing(true)
- keyguardTransitionRepository.sendTransitionSteps(
- from = KeyguardState.GONE,
- to = KeyguardState.AOD,
- this.testScheduler,
+ kosmos.setTransition(
+ sceneTransition = Idle(Scenes.Lockscreen),
+ stateTransition = TransitionStep(KeyguardState.GONE, KeyguardState.AOD)
)
- testScheduler.runCurrent()
// THEN: The notification is recognized as "seen" and is filtered out.
assertThat(unseenFilter.shouldFilterOut(fakeEntry, 0L)).isTrue()
// WHEN: The keyguard goes away
keyguardRepository.setKeyguardShowing(false)
- keyguardTransitionRepository.sendTransitionSteps(
- from = KeyguardState.AOD,
- to = KeyguardState.GONE,
- this.testScheduler,
+ kosmos.setTransition(
+ sceneTransition = Idle(Scenes.Gone),
+ stateTransition = TransitionStep(KeyguardState.AOD, KeyguardState.GONE)
)
- testScheduler.runCurrent()
// THEN: The notification is shown regardless
assertThat(unseenFilter.shouldFilterOut(fakeEntry, 0L)).isFalse()
@@ -344,9 +354,9 @@
val fakeEntry = NotificationEntryBuilder().build()
collectionListener.onEntryAdded(fakeEntry)
keyguardTransitionRepository.sendTransitionSteps(
- from = KeyguardState.AOD,
- to = KeyguardState.LOCKSCREEN,
- this.testScheduler,
+ from = KeyguardState.AOD,
+ to = KeyguardState.LOCKSCREEN,
+ this.testScheduler,
)
testScheduler.runCurrent()
@@ -356,21 +366,17 @@
// WHEN: Keyguard is no longer showing
keyguardRepository.setKeyguardShowing(false)
- keyguardTransitionRepository.sendTransitionSteps(
- from = KeyguardState.LOCKSCREEN,
- to = KeyguardState.GONE,
- this.testScheduler,
+ kosmos.setTransition(
+ sceneTransition = Idle(Scenes.Gone),
+ stateTransition = TransitionStep(KeyguardState.LOCKSCREEN, KeyguardState.GONE)
)
- testScheduler.runCurrent()
// WHEN: Keyguard is shown again
keyguardRepository.setKeyguardShowing(true)
- keyguardTransitionRepository.sendTransitionSteps(
- from = KeyguardState.GONE,
- to = KeyguardState.AOD,
- this.testScheduler,
+ kosmos.setTransition(
+ sceneTransition = Idle(Scenes.Lockscreen),
+ stateTransition = TransitionStep(KeyguardState.GONE, KeyguardState.AOD)
)
- testScheduler.runCurrent()
// THEN: The notification is now recognized as "seen" and is filtered out.
assertThat(unseenFilter.shouldFilterOut(fakeEntry, 0L)).isTrue()
@@ -383,9 +389,9 @@
keyguardRepository.setKeyguardShowing(true)
runKeyguardCoordinatorTest {
keyguardTransitionRepository.sendTransitionSteps(
- from = KeyguardState.GONE,
- to = KeyguardState.LOCKSCREEN,
- this.testScheduler,
+ from = KeyguardState.GONE,
+ to = KeyguardState.LOCKSCREEN,
+ this.testScheduler,
)
val fakeEntry = NotificationEntryBuilder().build()
collectionListener.onEntryAdded(fakeEntry)
@@ -393,9 +399,9 @@
// WHEN: Keyguard is no longer showing
keyguardRepository.setKeyguardShowing(false)
keyguardTransitionRepository.sendTransitionSteps(
- from = KeyguardState.LOCKSCREEN,
- to = KeyguardState.GONE,
- this.testScheduler,
+ from = KeyguardState.LOCKSCREEN,
+ to = KeyguardState.GONE,
+ this.testScheduler,
)
// WHEN: Keyguard is shown again
@@ -413,10 +419,9 @@
keyguardRepository.setKeyguardShowing(true)
keyguardRepository.setIsDozing(false)
runKeyguardCoordinatorTest {
- keyguardTransitionRepository.sendTransitionSteps(
- from = KeyguardState.GONE,
- to = KeyguardState.LOCKSCREEN,
- this.testScheduler,
+ kosmos.setTransition(
+ sceneTransition = Idle(Scenes.Lockscreen),
+ stateTransition = TransitionStep(KeyguardState.GONE, KeyguardState.LOCKSCREEN)
)
val firstEntry = NotificationEntryBuilder().setId(1).build()
collectionListener.onEntryAdded(firstEntry)
@@ -437,21 +442,17 @@
// WHEN: the keyguard is no longer showing
keyguardRepository.setKeyguardShowing(false)
- keyguardTransitionRepository.sendTransitionSteps(
- from = KeyguardState.LOCKSCREEN,
- to = KeyguardState.GONE,
- this.testScheduler,
+ kosmos.setTransition(
+ sceneTransition = Idle(Scenes.Gone),
+ stateTransition = TransitionStep(KeyguardState.LOCKSCREEN, KeyguardState.GONE)
)
- testScheduler.runCurrent()
// WHEN: Keyguard is shown again
keyguardRepository.setKeyguardShowing(true)
- keyguardTransitionRepository.sendTransitionSteps(
- from = KeyguardState.GONE,
- to = KeyguardState.LOCKSCREEN,
- this.testScheduler,
+ kosmos.setTransition(
+ sceneTransition = Idle(Scenes.Lockscreen),
+ stateTransition = TransitionStep(KeyguardState.GONE, KeyguardState.LOCKSCREEN)
)
- testScheduler.runCurrent()
// THEN: The first notification is considered seen and is filtered out.
assertThat(unseenFilter.shouldFilterOut(firstEntry, 0L)).isTrue()
@@ -468,9 +469,9 @@
keyguardRepository.setIsDozing(false)
runKeyguardCoordinatorTest {
keyguardTransitionRepository.sendTransitionSteps(
- from = KeyguardState.GONE,
- to = KeyguardState.LOCKSCREEN,
- this.testScheduler,
+ from = KeyguardState.GONE,
+ to = KeyguardState.LOCKSCREEN,
+ this.testScheduler,
)
testScheduler.runCurrent()
@@ -498,18 +499,18 @@
// WHEN: the keyguard is no longer showing
keyguardRepository.setKeyguardShowing(false)
keyguardTransitionRepository.sendTransitionSteps(
- from = KeyguardState.LOCKSCREEN,
- to = KeyguardState.GONE,
- this.testScheduler,
+ from = KeyguardState.LOCKSCREEN,
+ to = KeyguardState.GONE,
+ this.testScheduler,
)
testScheduler.runCurrent()
// WHEN: Keyguard is shown again
keyguardRepository.setKeyguardShowing(true)
keyguardTransitionRepository.sendTransitionSteps(
- from = KeyguardState.GONE,
- to = KeyguardState.LOCKSCREEN,
- this.testScheduler,
+ from = KeyguardState.GONE,
+ to = KeyguardState.LOCKSCREEN,
+ this.testScheduler,
)
testScheduler.runCurrent()
@@ -525,9 +526,9 @@
keyguardRepository.setIsDozing(false)
runKeyguardCoordinatorTest {
keyguardTransitionRepository.sendTransitionSteps(
- from = KeyguardState.GONE,
- to = KeyguardState.LOCKSCREEN,
- this.testScheduler,
+ from = KeyguardState.GONE,
+ to = KeyguardState.LOCKSCREEN,
+ this.testScheduler,
)
testScheduler.runCurrent()
@@ -555,18 +556,18 @@
// WHEN: the keyguard is no longer showing
keyguardRepository.setKeyguardShowing(false)
keyguardTransitionRepository.sendTransitionSteps(
- from = KeyguardState.LOCKSCREEN,
- to = KeyguardState.GONE,
- this.testScheduler,
+ from = KeyguardState.LOCKSCREEN,
+ to = KeyguardState.GONE,
+ this.testScheduler,
)
testScheduler.runCurrent()
// WHEN: Keyguard is shown again
keyguardRepository.setKeyguardShowing(true)
keyguardTransitionRepository.sendTransitionSteps(
- from = KeyguardState.GONE,
- to = KeyguardState.LOCKSCREEN,
- this.testScheduler,
+ from = KeyguardState.GONE,
+ to = KeyguardState.LOCKSCREEN,
+ this.testScheduler,
)
testScheduler.runCurrent()
@@ -582,9 +583,9 @@
keyguardRepository.setIsDozing(false)
runKeyguardCoordinatorTest {
keyguardTransitionRepository.sendTransitionSteps(
- from = KeyguardState.GONE,
- to = KeyguardState.LOCKSCREEN,
- this.testScheduler,
+ from = KeyguardState.GONE,
+ to = KeyguardState.LOCKSCREEN,
+ this.testScheduler,
)
testScheduler.runCurrent()
@@ -608,18 +609,18 @@
// WHEN: the keyguard is no longer showing
keyguardRepository.setKeyguardShowing(false)
keyguardTransitionRepository.sendTransitionSteps(
- from = KeyguardState.LOCKSCREEN,
- to = KeyguardState.GONE,
- this.testScheduler,
+ from = KeyguardState.LOCKSCREEN,
+ to = KeyguardState.GONE,
+ this.testScheduler,
)
testScheduler.runCurrent()
// WHEN: Keyguard is shown again
keyguardRepository.setKeyguardShowing(true)
keyguardTransitionRepository.sendTransitionSteps(
- from = KeyguardState.GONE,
- to = KeyguardState.LOCKSCREEN,
- this.testScheduler,
+ from = KeyguardState.GONE,
+ to = KeyguardState.LOCKSCREEN,
+ this.testScheduler,
)
testScheduler.runCurrent()
@@ -646,7 +647,7 @@
headsUpManager,
keyguardNotifVisibilityProvider,
keyguardRepository,
- keyguardTransitionRepository,
+ kosmos.keyguardTransitionInteractor,
KeyguardCoordinatorLogger(logcatLogBuffer()),
testScope.backgroundScope,
sectionHeaderVisibilityProvider,
@@ -706,4 +707,12 @@
)
}
}
+
+ companion object {
+ @JvmStatic
+ @Parameters(name = "{0}")
+ fun getParams(): List<FlagsParameterization> {
+ return FlagsParameterization.allCombinationsOf().andSceneContainer()
+ }
+ }
}
diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/ui/viewmodel/LockscreenContentViewModelKosmos.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/ui/viewmodel/LockscreenContentViewModelKosmos.kt
index 24e47b0..550ecb3 100644
--- a/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/ui/viewmodel/LockscreenContentViewModelKosmos.kt
+++ b/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/ui/viewmodel/LockscreenContentViewModelKosmos.kt
@@ -21,6 +21,7 @@
import com.android.systemui.keyguard.domain.interactor.keyguardClockInteractor
import com.android.systemui.kosmos.Kosmos
import com.android.systemui.kosmos.applicationCoroutineScope
+import com.android.systemui.scene.domain.interactor.sceneContainerOcclusionInteractor
import com.android.systemui.shade.domain.interactor.shadeInteractor
import com.android.systemui.unfold.domain.interactor.unfoldTransitionInteractor
@@ -34,5 +35,6 @@
shadeInteractor = shadeInteractor,
applicationScope = applicationCoroutineScope,
unfoldTransitionInteractor = unfoldTransitionInteractor,
+ occlusionInteractor = sceneContainerOcclusionInteractor,
)
}
diff --git a/services/backup/java/com/android/server/backup/utils/TarBackupReader.java b/services/backup/java/com/android/server/backup/utils/TarBackupReader.java
index 4860a27..8abbe56 100644
--- a/services/backup/java/com/android/server/backup/utils/TarBackupReader.java
+++ b/services/backup/java/com/android/server/backup/utils/TarBackupReader.java
@@ -792,10 +792,11 @@
}
private String getVToUAllowlist(Context context, int userId) {
- return Settings.Secure.getStringForUser(
+ String allowlist = Settings.Secure.getStringForUser(
context.getContentResolver(),
Settings.Secure.V_TO_U_RESTORE_ALLOWLIST,
userId);
+ return (allowlist == null) ? "" : allowlist;
}
private static long extractRadix(byte[] data, int offset, int maxChars, int radix)
diff --git a/services/core/java/com/android/server/CertBlacklister.java b/services/core/java/com/android/server/CertBlacklister.java
deleted file mode 100644
index e726c6a..0000000
--- a/services/core/java/com/android/server/CertBlacklister.java
+++ /dev/null
@@ -1,142 +0,0 @@
-/*
- * Copyright (C) 2012 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.server;
-
-import android.content.Context;
-import android.content.ContentResolver;
-import android.database.ContentObserver;
-import android.os.Binder;
-import android.os.FileUtils;
-import android.provider.Settings;
-import android.util.Slog;
-
-import java.io.File;
-import java.io.FileOutputStream;
-import java.io.IOException;
-
-import libcore.io.IoUtils;
-
-/**
- * <p>CertBlacklister provides a simple mechanism for updating the platform denylists for SSL
- * certificate public keys and serial numbers.
- */
-public class CertBlacklister extends Binder {
-
- private static final String TAG = "CertBlacklister";
-
- private static final String DENYLIST_ROOT = System.getenv("ANDROID_DATA") + "/misc/keychain/";
-
- public static final String PUBKEY_PATH = DENYLIST_ROOT + "pubkey_blacklist.txt";
- public static final String SERIAL_PATH = DENYLIST_ROOT + "serial_blacklist.txt";
-
- public static final String PUBKEY_BLACKLIST_KEY = "pubkey_blacklist";
- public static final String SERIAL_BLACKLIST_KEY = "serial_blacklist";
-
- private static class BlacklistObserver extends ContentObserver {
-
- private final String mKey;
- private final String mName;
- private final String mPath;
- private final File mTmpDir;
- private final ContentResolver mContentResolver;
-
- public BlacklistObserver(String key, String name, String path, ContentResolver cr) {
- super(null);
- mKey = key;
- mName = name;
- mPath = path;
- mTmpDir = new File(mPath).getParentFile();
- mContentResolver = cr;
- }
-
- @Override
- public void onChange(boolean selfChange) {
- super.onChange(selfChange);
- writeDenylist();
- }
-
- public String getValue() {
- return Settings.Secure.getString(mContentResolver, mKey);
- }
-
- private void writeDenylist() {
- new Thread("BlacklistUpdater") {
- public void run() {
- synchronized(mTmpDir) {
- String blacklist = getValue();
- if (blacklist != null) {
- Slog.i(TAG, "Certificate blacklist changed, updating...");
- FileOutputStream out = null;
- try {
- // create a temporary file
- File tmp = File.createTempFile("journal", "", mTmpDir);
- // mark it -rw-r--r--
- tmp.setReadable(true, false);
- // write to it
- out = new FileOutputStream(tmp);
- out.write(blacklist.getBytes());
- // sync to disk
- FileUtils.sync(out);
- // atomic rename
- tmp.renameTo(new File(mPath));
- Slog.i(TAG, "Certificate blacklist updated");
- } catch (IOException e) {
- Slog.e(TAG, "Failed to write blacklist", e);
- } finally {
- IoUtils.closeQuietly(out);
- }
- }
- }
- }
- }.start();
- }
- }
-
- public CertBlacklister(Context context) {
- registerObservers(context.getContentResolver());
- }
-
- private BlacklistObserver buildPubkeyObserver(ContentResolver cr) {
- return new BlacklistObserver(PUBKEY_BLACKLIST_KEY,
- "pubkey",
- PUBKEY_PATH,
- cr);
- }
-
- private BlacklistObserver buildSerialObserver(ContentResolver cr) {
- return new BlacklistObserver(SERIAL_BLACKLIST_KEY,
- "serial",
- SERIAL_PATH,
- cr);
- }
-
- private void registerObservers(ContentResolver cr) {
- // set up the public key denylist observer
- cr.registerContentObserver(
- Settings.Secure.getUriFor(PUBKEY_BLACKLIST_KEY),
- true,
- buildPubkeyObserver(cr)
- );
-
- // set up the serial number denylist observer
- cr.registerContentObserver(
- Settings.Secure.getUriFor(SERIAL_BLACKLIST_KEY),
- true,
- buildSerialObserver(cr)
- );
- }
-}
diff --git a/services/core/java/com/android/server/CertBlocklister.java b/services/core/java/com/android/server/CertBlocklister.java
new file mode 100644
index 0000000..9e23f88
--- /dev/null
+++ b/services/core/java/com/android/server/CertBlocklister.java
@@ -0,0 +1,146 @@
+/*
+ * Copyright (C) 2012 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server;
+
+import android.content.ContentResolver;
+import android.content.Context;
+import android.database.ContentObserver;
+import android.os.Binder;
+import android.os.FileUtils;
+import android.provider.Settings;
+import android.util.Slog;
+
+import libcore.io.IoUtils;
+
+import java.io.File;
+import java.io.FileOutputStream;
+import java.io.IOException;
+
+/**
+ * <p>CertBlocklister provides a simple mechanism for updating the platform denylists for SSL
+ * certificate public keys and serial numbers.
+ */
+public class CertBlocklister extends Binder {
+
+ private static final String TAG = "CertBlocklister";
+
+ private static final String DENYLIST_ROOT = System.getenv("ANDROID_DATA") + "/misc/keychain/";
+
+ /* For compatibility reasons, the name of these paths cannot be changed */
+ public static final String PUBKEY_PATH = DENYLIST_ROOT + "pubkey_blacklist.txt";
+ public static final String SERIAL_PATH = DENYLIST_ROOT + "serial_blacklist.txt";
+
+ /* For compatibility reasons, the name of these keys cannot be changed */
+ public static final String PUBKEY_BLOCKLIST_KEY = "pubkey_blacklist";
+ public static final String SERIAL_BLOCKLIST_KEY = "serial_blacklist";
+
+ private static class BlocklistObserver extends ContentObserver {
+
+ private final String mKey;
+ private final String mName;
+ private final String mPath;
+ private final File mTmpDir;
+ private final ContentResolver mContentResolver;
+
+ BlocklistObserver(String key, String name, String path, ContentResolver cr) {
+ super(null);
+ mKey = key;
+ mName = name;
+ mPath = path;
+ mTmpDir = new File(mPath).getParentFile();
+ mContentResolver = cr;
+ }
+
+ @Override
+ public void onChange(boolean selfChange) {
+ super.onChange(selfChange);
+ new Thread("BlocklistUpdater") {
+ public void run() {
+ writeDenylist();
+ }
+ }.start();
+ }
+
+ public String getValue() {
+ return Settings.Secure.getStringForUser(
+ mContentResolver, mKey, mContentResolver.getUserId());
+ }
+
+ private void writeDenylist() {
+ synchronized (mTmpDir) {
+ String blocklist = getValue();
+ if (blocklist == null) {
+ return;
+ }
+ if (mPath.equals(SERIAL_PATH)) {
+ Slog.w(TAG, "The certificate blocklist based on serials is deprecated. "
+ + "Please use the pubkey blocklist instead.");
+ }
+ Slog.i(TAG, "Certificate blocklist changed, updating...");
+ FileOutputStream out = null;
+ try {
+ // Create a temporary file and rename it atomically.
+ File tmp = File.createTempFile("journal", "", mTmpDir);
+ tmp.setReadable(true /* readable */, false /* ownerOnly */);
+ out = new FileOutputStream(tmp);
+ out.write(blocklist.getBytes());
+ FileUtils.sync(out);
+ tmp.renameTo(new File(mPath));
+ Slog.i(TAG, "Certificate blocklist updated");
+ } catch (IOException e) {
+ Slog.e(TAG, "Failed to write blocklist", e);
+ } finally {
+ IoUtils.closeQuietly(out);
+ }
+ }
+ }
+ }
+
+ public CertBlocklister(Context context) {
+ registerObservers(context.getContentResolver());
+ }
+
+ private BlocklistObserver buildPubkeyObserver(ContentResolver cr) {
+ return new BlocklistObserver(PUBKEY_BLOCKLIST_KEY,
+ "pubkey",
+ PUBKEY_PATH,
+ cr);
+ }
+
+ private BlocklistObserver buildSerialObserver(ContentResolver cr) {
+ return new BlocklistObserver(SERIAL_BLOCKLIST_KEY,
+ "serial",
+ SERIAL_PATH,
+ cr);
+ }
+
+ private void registerObservers(ContentResolver cr) {
+ // set up the public key denylist observer
+ cr.registerContentObserver(
+ Settings.Secure.getUriFor(PUBKEY_BLOCKLIST_KEY),
+ true,
+ buildPubkeyObserver(cr)
+ );
+
+ // set up the serial number denylist observer
+ cr.registerContentObserver(
+ Settings.Secure.getUriFor(SERIAL_BLOCKLIST_KEY),
+ true,
+ buildSerialObserver(cr)
+ );
+ }
+}
diff --git a/services/core/java/com/android/server/TelephonyRegistry.java b/services/core/java/com/android/server/TelephonyRegistry.java
index bc83a0e..bacfd8f 100644
--- a/services/core/java/com/android/server/TelephonyRegistry.java
+++ b/services/core/java/com/android/server/TelephonyRegistry.java
@@ -921,8 +921,7 @@
//helper function to determine if limit on num listeners applies to callingUid
private boolean doesLimitApplyForListeners(int callingUid, int exemptUid) {
- return (callingUid != Process.SYSTEM_UID
- && callingUid != Process.PHONE_UID
+ return (!TelephonyPermissions.isSystemOrPhone(callingUid)
&& callingUid != exemptUid);
}
diff --git a/services/core/java/com/android/server/notification/PreferencesHelper.java b/services/core/java/com/android/server/notification/PreferencesHelper.java
index 3a0c1d0..c09504f 100644
--- a/services/core/java/com/android/server/notification/PreferencesHelper.java
+++ b/services/core/java/com/android/server/notification/PreferencesHelper.java
@@ -196,9 +196,12 @@
int USER_LOCKED_BUBBLE = 0x00000002;
}
+ private final Object mLock = new Object();
// pkg|uid => PackagePreferences
+ @GuardedBy("mLock")
private final ArrayMap<String, PackagePreferences> mPackagePreferences = new ArrayMap<>();
// pkg|userId => PackagePreferences
+ @GuardedBy("mLock")
private final ArrayMap<String, PackagePreferences> mRestoredWithoutUids = new ArrayMap<>();
private final Context mContext;
@@ -270,7 +273,7 @@
Settings.Global.REVIEW_PERMISSIONS_NOTIFICATION_STATE,
NotificationManagerService.REVIEW_NOTIF_STATE_SHOULD_SHOW);
}
- synchronized (mPackagePreferences) {
+ synchronized (mLock) {
while ((type = parser.next()) != XmlPullParser.END_DOCUMENT) {
tag = parser.getName();
if (type == XmlPullParser.END_TAG && TAG_RANKING.equals(tag)) {
@@ -492,6 +495,7 @@
DEFAULT_BUBBLE_PREFERENCE, mClock.millis());
}
+ @GuardedBy("mLock")
private PackagePreferences getOrCreatePackagePreferencesLocked(String pkg,
@UserIdInt int userId, int uid, int importance, int priority, int visibility,
boolean showBadge, int bubblePreference, long creationTime) {
@@ -661,7 +665,7 @@
notifPermissions = mPermissionHelper.getNotificationPermissionValues(userId);
}
- synchronized (mPackagePreferences) {
+ synchronized (mLock) {
final int N = mPackagePreferences.size();
for (int i = 0; i < N; i++) {
final PackagePreferences r = mPackagePreferences.valueAt(i);
@@ -670,11 +674,10 @@
}
writePackageXml(r, out, notifPermissions, forBackup);
}
- }
- if (Flags.persistIncompleteRestoreData() && !forBackup) {
- synchronized (mRestoredWithoutUids) {
- final int N = mRestoredWithoutUids.size();
- for (int i = 0; i < N; i++) {
+
+ if (Flags.persistIncompleteRestoreData() && !forBackup) {
+ final int M = mRestoredWithoutUids.size();
+ for (int i = 0; i < M; i++) {
final PackagePreferences r = mRestoredWithoutUids.valueAt(i);
writePackageXml(r, out, notifPermissions, false);
}
@@ -777,7 +780,7 @@
*/
public void setBubblesAllowed(String pkg, int uid, int bubblePreference) {
boolean changed;
- synchronized (mPackagePreferences) {
+ synchronized (mLock) {
PackagePreferences p = getOrCreatePackagePreferencesLocked(pkg, uid);
changed = p.bubblePreference != bubblePreference;
p.bubblePreference = bubblePreference;
@@ -797,20 +800,20 @@
*/
@Override
public int getBubblePreference(String pkg, int uid) {
- synchronized (mPackagePreferences) {
+ synchronized (mLock) {
return getOrCreatePackagePreferencesLocked(pkg, uid).bubblePreference;
}
}
public int getAppLockedFields(String pkg, int uid) {
- synchronized (mPackagePreferences) {
+ synchronized (mLock) {
return getOrCreatePackagePreferencesLocked(pkg, uid).lockedAppFields;
}
}
@Override
public boolean canShowBadge(String packageName, int uid) {
- synchronized (mPackagePreferences) {
+ synchronized (mLock) {
return getOrCreatePackagePreferencesLocked(packageName, uid).showBadge;
}
}
@@ -818,7 +821,7 @@
@Override
public void setShowBadge(String packageName, int uid, boolean showBadge) {
boolean changed = false;
- synchronized (mPackagePreferences) {
+ synchronized (mLock) {
PackagePreferences pkgPrefs = getOrCreatePackagePreferencesLocked(packageName, uid);
if (pkgPrefs.showBadge != showBadge) {
pkgPrefs.showBadge = showBadge;
@@ -831,28 +834,28 @@
}
public boolean isInInvalidMsgState(String packageName, int uid) {
- synchronized (mPackagePreferences) {
+ synchronized (mLock) {
PackagePreferences r = getOrCreatePackagePreferencesLocked(packageName, uid);
return r.hasSentInvalidMessage && !r.hasSentValidMessage;
}
}
public boolean hasUserDemotedInvalidMsgApp(String packageName, int uid) {
- synchronized (mPackagePreferences) {
+ synchronized (mLock) {
PackagePreferences r = getOrCreatePackagePreferencesLocked(packageName, uid);
return isInInvalidMsgState(packageName, uid) ? r.userDemotedMsgApp : false;
}
}
public void setInvalidMsgAppDemoted(String packageName, int uid, boolean isDemoted) {
- synchronized (mPackagePreferences) {
+ synchronized (mLock) {
PackagePreferences r = getOrCreatePackagePreferencesLocked(packageName, uid);
r.userDemotedMsgApp = isDemoted;
}
}
public boolean setInvalidMessageSent(String packageName, int uid) {
- synchronized (mPackagePreferences) {
+ synchronized (mLock) {
PackagePreferences r = getOrCreatePackagePreferencesLocked(packageName, uid);
boolean valueChanged = r.hasSentInvalidMessage == false;
r.hasSentInvalidMessage = true;
@@ -862,7 +865,7 @@
}
public boolean setValidMessageSent(String packageName, int uid) {
- synchronized (mPackagePreferences) {
+ synchronized (mLock) {
PackagePreferences r = getOrCreatePackagePreferencesLocked(packageName, uid);
boolean valueChanged = r.hasSentValidMessage == false;
r.hasSentValidMessage = true;
@@ -873,7 +876,7 @@
@VisibleForTesting
boolean hasSentInvalidMsg(String packageName, int uid) {
- synchronized (mPackagePreferences) {
+ synchronized (mLock) {
PackagePreferences r = getOrCreatePackagePreferencesLocked(packageName, uid);
return r.hasSentInvalidMessage;
}
@@ -881,7 +884,7 @@
@VisibleForTesting
boolean hasSentValidMsg(String packageName, int uid) {
- synchronized (mPackagePreferences) {
+ synchronized (mLock) {
PackagePreferences r = getOrCreatePackagePreferencesLocked(packageName, uid);
return r.hasSentValidMessage;
}
@@ -889,7 +892,7 @@
@VisibleForTesting
boolean didUserEverDemoteInvalidMsgApp(String packageName, int uid) {
- synchronized (mPackagePreferences) {
+ synchronized (mLock) {
PackagePreferences r = getOrCreatePackagePreferencesLocked(packageName, uid);
return r.userDemotedMsgApp;
}
@@ -897,7 +900,7 @@
/** Sets whether this package has sent a notification with valid bubble metadata. */
public boolean setValidBubbleSent(String packageName, int uid) {
- synchronized (mPackagePreferences) {
+ synchronized (mLock) {
PackagePreferences r = getOrCreatePackagePreferencesLocked(packageName, uid);
boolean valueChanged = !r.hasSentValidBubble;
r.hasSentValidBubble = true;
@@ -906,14 +909,14 @@
}
boolean hasSentValidBubble(String packageName, int uid) {
- synchronized (mPackagePreferences) {
+ synchronized (mLock) {
PackagePreferences r = getOrCreatePackagePreferencesLocked(packageName, uid);
return r.hasSentValidBubble;
}
}
boolean isImportanceLocked(String pkg, int uid) {
- synchronized (mPackagePreferences) {
+ synchronized (mLock) {
PackagePreferences r = getOrCreatePackagePreferencesLocked(pkg, uid);
return r.fixedImportance || r.defaultAppLockedImportance;
}
@@ -924,7 +927,7 @@
if (groupId == null) {
return false;
}
- synchronized (mPackagePreferences) {
+ synchronized (mLock) {
PackagePreferences r = getOrCreatePackagePreferencesLocked(packageName, uid);
NotificationChannelGroup group = r.groups.get(groupId);
if (group == null) {
@@ -935,13 +938,13 @@
}
int getPackagePriority(String pkg, int uid) {
- synchronized (mPackagePreferences) {
+ synchronized (mLock) {
return getOrCreatePackagePreferencesLocked(pkg, uid).priority;
}
}
int getPackageVisibility(String pkg, int uid) {
- synchronized (mPackagePreferences) {
+ synchronized (mLock) {
return getOrCreatePackagePreferencesLocked(pkg, uid).visibility;
}
}
@@ -956,7 +959,7 @@
throw new IllegalArgumentException("group.getName() can't be empty");
}
boolean needsDndChange = false;
- synchronized (mPackagePreferences) {
+ synchronized (mLock) {
PackagePreferences r = getOrCreatePackagePreferencesLocked(pkg, uid);
if (r == null) {
throw new IllegalArgumentException("Invalid package");
@@ -1010,7 +1013,7 @@
&& channel.getImportance() <= IMPORTANCE_MAX, "Invalid importance level");
boolean needsPolicyFileChange = false, wasUndeleted = false, needsDndChange = false;
- synchronized (mPackagePreferences) {
+ synchronized (mLock) {
PackagePreferences r = getOrCreatePackagePreferencesLocked(pkg, uid);
if (r == null) {
throw new IllegalArgumentException("Invalid package");
@@ -1154,7 +1157,7 @@
void unlockNotificationChannelImportance(String pkg, int uid, String updatedChannelId) {
Objects.requireNonNull(updatedChannelId);
- synchronized (mPackagePreferences) {
+ synchronized (mLock) {
PackagePreferences r = getOrCreatePackagePreferencesLocked(pkg, uid);
if (r == null) {
throw new IllegalArgumentException("Invalid package");
@@ -1176,7 +1179,7 @@
Objects.requireNonNull(updatedChannel.getId());
boolean changed = false;
boolean needsDndChange = false;
- synchronized (mPackagePreferences) {
+ synchronized (mLock) {
PackagePreferences r = getOrCreatePackagePreferencesLocked(pkg, uid);
if (r == null) {
throw new IllegalArgumentException("Invalid package");
@@ -1351,7 +1354,7 @@
String channelId, String conversationId, boolean returnParentIfNoConversationChannel,
boolean includeDeleted) {
Preconditions.checkNotNull(pkg);
- synchronized (mPackagePreferences) {
+ synchronized (mLock) {
PackagePreferences r = getOrCreatePackagePreferencesLocked(pkg, uid);
if (r == null) {
return null;
@@ -1392,7 +1395,7 @@
Preconditions.checkNotNull(pkg);
Preconditions.checkNotNull(conversationId);
List<NotificationChannel> channels = new ArrayList<>();
- synchronized (mPackagePreferences) {
+ synchronized (mLock) {
PackagePreferences r = getOrCreatePackagePreferencesLocked(pkg, uid);
if (r == null) {
return channels;
@@ -1412,7 +1415,7 @@
int callingUid, boolean fromSystemOrSystemUi) {
boolean deletedChannel = false;
boolean channelBypassedDnd = false;
- synchronized (mPackagePreferences) {
+ synchronized (mLock) {
PackagePreferences r = getPackagePreferencesLocked(pkg, uid);
if (r == null) {
return false;
@@ -1448,7 +1451,7 @@
public void permanentlyDeleteNotificationChannel(String pkg, int uid, String channelId) {
Objects.requireNonNull(pkg);
Objects.requireNonNull(channelId);
- synchronized (mPackagePreferences) {
+ synchronized (mLock) {
PackagePreferences r = getPackagePreferencesLocked(pkg, uid);
if (r == null) {
return;
@@ -1460,7 +1463,7 @@
@Override
public void permanentlyDeleteNotificationChannels(String pkg, int uid) {
Objects.requireNonNull(pkg);
- synchronized (mPackagePreferences) {
+ synchronized (mLock) {
PackagePreferences r = getPackagePreferencesLocked(pkg, uid);
if (r == null) {
return;
@@ -1491,7 +1494,7 @@
boolean fixed = mPermissionHelper.isPermissionFixed(
pi.packageName, user.getUserHandle().getIdentifier());
if (fixed) {
- synchronized (mPackagePreferences) {
+ synchronized (mLock) {
PackagePreferences p = getOrCreatePackagePreferencesLocked(
pi.packageName, pi.applicationInfo.uid);
p.fixedImportance = true;
@@ -1506,7 +1509,7 @@
public void updateDefaultApps(int userId, ArraySet<String> toRemove,
ArraySet<Pair<String, Integer>> toAdd) {
- synchronized (mPackagePreferences) {
+ synchronized (mLock) {
for (PackagePreferences p : mPackagePreferences.values()) {
if (userId == UserHandle.getUserId(p.uid)) {
if (toRemove != null && toRemove.contains(p.pkg)) {
@@ -1536,7 +1539,7 @@
public NotificationChannelGroup getNotificationChannelGroupWithChannels(String pkg,
int uid, String groupId, boolean includeDeleted) {
Objects.requireNonNull(pkg);
- synchronized (mPackagePreferences) {
+ synchronized (mLock) {
PackagePreferences r = getPackagePreferencesLocked(pkg, uid);
if (r == null || groupId == null || !r.groups.containsKey(groupId)) {
return null;
@@ -1559,7 +1562,7 @@
public NotificationChannelGroup getNotificationChannelGroup(String groupId, String pkg,
int uid) {
Objects.requireNonNull(pkg);
- synchronized (mPackagePreferences) {
+ synchronized (mLock) {
PackagePreferences r = getPackagePreferencesLocked(pkg, uid);
if (r == null) {
return null;
@@ -1573,7 +1576,7 @@
boolean includeBlocked, Set<String> activeChannelFilter) {
Objects.requireNonNull(pkg);
Map<String, NotificationChannelGroup> groups = new ArrayMap<>();
- synchronized (mPackagePreferences) {
+ synchronized (mLock) {
PackagePreferences r = getPackagePreferencesLocked(pkg, uid);
if (r == null) {
return ParceledListSlice.emptyList();
@@ -1624,7 +1627,7 @@
String groupId, int callingUid, boolean fromSystemOrSystemUi) {
List<NotificationChannel> deletedChannels = new ArrayList<>();
boolean groupBypassedDnd = false;
- synchronized (mPackagePreferences) {
+ synchronized (mLock) {
PackagePreferences r = getPackagePreferencesLocked(pkg, uid);
if (r == null || TextUtils.isEmpty(groupId)) {
return deletedChannels;
@@ -1656,7 +1659,7 @@
public Collection<NotificationChannelGroup> getNotificationChannelGroups(String pkg,
int uid) {
List<NotificationChannelGroup> groups = new ArrayList<>();
- synchronized (mPackagePreferences) {
+ synchronized (mLock) {
PackagePreferences r = getPackagePreferencesLocked(pkg, uid);
if (r == null) {
return groups;
@@ -1667,7 +1670,7 @@
}
public NotificationChannelGroup getGroupForChannel(String pkg, int uid, String channelId) {
- synchronized (mPackagePreferences) {
+ synchronized (mLock) {
PackagePreferences p = getPackagePreferencesLocked(pkg, uid);
if (p != null) {
NotificationChannel nc = p.channels.get(channelId);
@@ -1686,7 +1689,7 @@
public ArrayList<ConversationChannelWrapper> getConversations(IntArray userIds,
boolean onlyImportant) {
- synchronized (mPackagePreferences) {
+ synchronized (mLock) {
ArrayList<ConversationChannelWrapper> conversations = new ArrayList<>();
for (PackagePreferences p : mPackagePreferences.values()) {
if (userIds.binarySearch(UserHandle.getUserId(p.uid)) >= 0) {
@@ -1730,7 +1733,7 @@
public ArrayList<ConversationChannelWrapper> getConversations(String pkg, int uid) {
Objects.requireNonNull(pkg);
- synchronized (mPackagePreferences) {
+ synchronized (mLock) {
PackagePreferences r = getPackagePreferencesLocked(pkg, uid);
if (r == null) {
return new ArrayList<>();
@@ -1772,7 +1775,7 @@
public @NonNull List<String> deleteConversations(String pkg, int uid,
Set<String> conversationIds, int callingUid, boolean fromSystemOrSystemUi) {
List<String> deletedChannelIds = new ArrayList<>();
- synchronized (mPackagePreferences) {
+ synchronized (mLock) {
PackagePreferences r = getPackagePreferencesLocked(pkg, uid);
if (r == null) {
return deletedChannelIds;
@@ -1805,7 +1808,7 @@
boolean includeDeleted) {
Objects.requireNonNull(pkg);
List<NotificationChannel> channels = new ArrayList<>();
- synchronized (mPackagePreferences) {
+ synchronized (mLock) {
PackagePreferences r = getPackagePreferencesLocked(pkg, uid);
if (r == null) {
return ParceledListSlice.emptyList();
@@ -1827,7 +1830,7 @@
public ParceledListSlice<NotificationChannel> getNotificationChannelsBypassingDnd(String pkg,
int uid) {
List<NotificationChannel> channels = new ArrayList<>();
- synchronized (mPackagePreferences) {
+ synchronized (mLock) {
final PackagePreferences r = mPackagePreferences.get(
packagePreferencesKey(pkg, uid));
if (r != null) {
@@ -1848,7 +1851,7 @@
* upgrades.
*/
public boolean onlyHasDefaultChannel(String pkg, int uid) {
- synchronized (mPackagePreferences) {
+ synchronized (mLock) {
PackagePreferences r = getOrCreatePackagePreferencesLocked(pkg, uid);
if (r.channels.size() == (notificationClassification() ? 5 : 1)
&& r.channels.containsKey(NotificationChannel.DEFAULT_CHANNEL_ID)) {
@@ -1861,7 +1864,7 @@
public int getDeletedChannelCount(String pkg, int uid) {
Objects.requireNonNull(pkg);
int deletedCount = 0;
- synchronized (mPackagePreferences) {
+ synchronized (mLock) {
PackagePreferences r = getPackagePreferencesLocked(pkg, uid);
if (r == null) {
return deletedCount;
@@ -1880,7 +1883,7 @@
public int getBlockedChannelCount(String pkg, int uid) {
Objects.requireNonNull(pkg);
int blockedCount = 0;
- synchronized (mPackagePreferences) {
+ synchronized (mLock) {
PackagePreferences r = getPackagePreferencesLocked(pkg, uid);
if (r == null) {
return blockedCount;
@@ -1923,7 +1926,7 @@
ArraySet<Pair<String, Integer>> candidatePkgs = new ArraySet<>();
final IntArray currentUserIds = mUserProfiles.getCurrentProfileIds();
- synchronized (mPackagePreferences) {
+ synchronized (mLock) {
final int numPackagePreferences = mPackagePreferences.size();
for (int i = 0; i < numPackagePreferences; i++) {
final PackagePreferences r = mPackagePreferences.valueAt(i);
@@ -1992,7 +1995,7 @@
* considered for sentiment adjustments (and thus never show a blocking helper).
*/
public void setAppImportanceLocked(String packageName, int uid) {
- synchronized (mPackagePreferences) {
+ synchronized (mLock) {
PackagePreferences prefs = getOrCreatePackagePreferencesLocked(packageName, uid);
if ((prefs.lockedAppFields & LockableAppFields.USER_LOCKED_IMPORTANCE) != 0) {
return;
@@ -2008,7 +2011,7 @@
* Returns the delegate for a given package, if it's allowed by the package and the user.
*/
public @Nullable String getNotificationDelegate(String sourcePkg, int sourceUid) {
- synchronized (mPackagePreferences) {
+ synchronized (mLock) {
PackagePreferences prefs = getPackagePreferencesLocked(sourcePkg, sourceUid);
if (prefs == null || prefs.delegate == null) {
@@ -2026,7 +2029,7 @@
*/
public void setNotificationDelegate(String sourcePkg, int sourceUid,
String delegatePkg, int delegateUid) {
- synchronized (mPackagePreferences) {
+ synchronized (mLock) {
PackagePreferences prefs = getOrCreatePackagePreferencesLocked(sourcePkg, sourceUid);
prefs.delegate = new Delegate(delegatePkg, delegateUid, true);
}
@@ -2036,7 +2039,7 @@
* Used by an app to turn off its notification delegate.
*/
public void revokeNotificationDelegate(String sourcePkg, int sourceUid) {
- synchronized (mPackagePreferences) {
+ synchronized (mLock) {
PackagePreferences prefs = getPackagePreferencesLocked(sourcePkg, sourceUid);
if (prefs != null && prefs.delegate != null) {
prefs.delegate.mEnabled = false;
@@ -2050,7 +2053,7 @@
*/
public boolean isDelegateAllowed(String sourcePkg, int sourceUid,
String potentialDelegatePkg, int potentialDelegateUid) {
- synchronized (mPackagePreferences) {
+ synchronized (mLock) {
PackagePreferences prefs = getPackagePreferencesLocked(sourcePkg, sourceUid);
return prefs != null && prefs.isValidDelegate(potentialDelegatePkg,
@@ -2096,24 +2099,25 @@
pw.println("per-package config version: " + XML_VERSION);
pw.println("PackagePreferences:");
- synchronized (mPackagePreferences) {
+ synchronized (mLock) {
dumpPackagePreferencesLocked(pw, prefix, filter, mPackagePreferences, pkgPermissions);
+ pw.println("Restored without uid:");
+ dumpPackagePreferencesLocked(pw, prefix, filter, mRestoredWithoutUids, null);
}
- pw.println("Restored without uid:");
- dumpPackagePreferencesLocked(pw, prefix, filter, mRestoredWithoutUids, null);
}
public void dump(ProtoOutputStream proto,
@NonNull NotificationManagerService.DumpFilter filter,
ArrayMap<Pair<Integer, String>, Pair<Boolean, Boolean>> pkgPermissions) {
- synchronized (mPackagePreferences) {
+ synchronized (mLock) {
dumpPackagePreferencesLocked(proto, RankingHelperProto.RECORDS, filter,
mPackagePreferences, pkgPermissions);
+ dumpPackagePreferencesLocked(proto, RankingHelperProto.RECORDS_RESTORED_WITHOUT_UID,
+ filter, mRestoredWithoutUids, null);
}
- dumpPackagePreferencesLocked(proto, RankingHelperProto.RECORDS_RESTORED_WITHOUT_UID, filter,
- mRestoredWithoutUids, null);
}
+ @GuardedBy("mLock")
private void dumpPackagePreferencesLocked(PrintWriter pw, String prefix,
@NonNull NotificationManagerService.DumpFilter filter,
ArrayMap<String, PackagePreferences> packagePreferences,
@@ -2298,7 +2302,7 @@
pkgsWithPermissionsToHandle = pkgPermissions.keySet();
}
int pulledEvents = 0;
- synchronized (mPackagePreferences) {
+ synchronized (mLock) {
for (int i = 0; i < mPackagePreferences.size(); i++) {
if (pulledEvents > NOTIFICATION_PREFERENCES_PULL_LIMIT) {
break;
@@ -2378,7 +2382,7 @@
* {@link StatsEvent}.
*/
public void pullPackageChannelPreferencesStats(List<StatsEvent> events) {
- synchronized (mPackagePreferences) {
+ synchronized (mLock) {
int totalChannelsPulled = 0;
for (int i = 0; i < mPackagePreferences.size(); i++) {
if (totalChannelsPulled > NOTIFICATION_CHANNEL_PULL_LIMIT) {
@@ -2414,7 +2418,7 @@
* {@link StatsEvent}.
*/
public void pullPackageChannelGroupPreferencesStats(List<StatsEvent> events) {
- synchronized (mPackagePreferences) {
+ synchronized (mLock) {
int totalGroupsPulled = 0;
for (int i = 0; i < mPackagePreferences.size(); i++) {
if (totalGroupsPulled > NOTIFICATION_CHANNEL_GROUP_PULL_LIMIT) {
@@ -2443,10 +2447,12 @@
ArrayMap<Pair<Integer, String>, Pair<Boolean, Boolean>> pkgPermissions) {
JSONObject ranking = new JSONObject();
JSONArray PackagePreferencess = new JSONArray();
- try {
- ranking.put("noUid", mRestoredWithoutUids.size());
- } catch (JSONException e) {
- // pass
+ synchronized (mLock) {
+ try {
+ ranking.put("noUid", mRestoredWithoutUids.size());
+ } catch (JSONException e) {
+ // pass
+ }
}
// Track data that we've handled from the permissions-based list
@@ -2455,7 +2461,7 @@
pkgsWithPermissionsToHandle = pkgPermissions.keySet();
}
- synchronized (mPackagePreferences) {
+ synchronized (mLock) {
final int N = mPackagePreferences.size();
for (int i = 0; i < N; i++) {
final PackagePreferences r = mPackagePreferences.valueAt(i);
@@ -2561,7 +2567,7 @@
}
public Map<Integer, String> getPackageBans() {
- synchronized (mPackagePreferences) {
+ synchronized (mLock) {
final int N = mPackagePreferences.size();
ArrayMap<Integer, String> packageBans = new ArrayMap<>(N);
for (int i = 0; i < N; i++) {
@@ -2620,7 +2626,7 @@
private Map<String, Integer> getPackageChannels() {
ArrayMap<String, Integer> packageChannels = new ArrayMap<>();
- synchronized (mPackagePreferences) {
+ synchronized (mLock) {
for (int i = 0; i < mPackagePreferences.size(); i++) {
final PackagePreferences r = mPackagePreferences.valueAt(i);
int channelCount = 0;
@@ -2636,7 +2642,7 @@
}
public void onUserRemoved(int userId) {
- synchronized (mPackagePreferences) {
+ synchronized (mLock) {
int N = mPackagePreferences.size();
for (int i = N - 1; i >= 0; i--) {
PackagePreferences PackagePreferences = mPackagePreferences.valueAt(i);
@@ -2648,7 +2654,7 @@
}
protected void onLocaleChanged(Context context, int userId) {
- synchronized (mPackagePreferences) {
+ synchronized (mLock) {
int N = mPackagePreferences.size();
for (int i = 0; i < N; i++) {
PackagePreferences PackagePreferences = mPackagePreferences.valueAt(i);
@@ -2678,22 +2684,24 @@
for (int i = 0; i < size; i++) {
final String pkg = pkgList[i];
final int uid = uidList[i];
- synchronized (mPackagePreferences) {
+ synchronized (mLock) {
mPackagePreferences.remove(packagePreferencesKey(pkg, uid));
+ mRestoredWithoutUids.remove(unrestoredPackageKey(pkg, changeUserId));
}
- mRestoredWithoutUids.remove(unrestoredPackageKey(pkg, changeUserId));
updated = true;
}
} else {
for (String pkg : pkgList) {
- // Package install
- final PackagePreferences r =
- mRestoredWithoutUids.get(unrestoredPackageKey(pkg, changeUserId));
- if (r != null) {
- try {
- r.uid = mPm.getPackageUidAsUser(r.pkg, changeUserId);
- mRestoredWithoutUids.remove(unrestoredPackageKey(pkg, changeUserId));
- synchronized (mPackagePreferences) {
+ try {
+ // Package install
+ int uid = mPm.getPackageUidAsUser(pkg, changeUserId);
+ PackagePermission p = null;
+ synchronized (mLock) {
+ final PackagePreferences r =
+ mRestoredWithoutUids.get(unrestoredPackageKey(pkg, changeUserId));
+ if (r != null) {
+ r.uid = uid;
+ mRestoredWithoutUids.remove(unrestoredPackageKey(pkg, changeUserId));
mPackagePreferences.put(packagePreferencesKey(r.pkg, r.uid), r);
// Try to restore any unrestored sound resources
@@ -2715,32 +2723,29 @@
channel.setSound(restoredUri, channel.getAudioAttributes());
}
}
- }
- if (r.migrateToPm) {
- try {
- PackagePermission p = new PackagePermission(
+
+ if (r.migrateToPm) {
+ p = new PackagePermission(
r.pkg, UserHandle.getUserId(r.uid),
r.importance != IMPORTANCE_NONE,
hasUserConfiguredSettings(r));
- mPermissionHelper.setNotificationPermission(p);
- } catch (Exception e) {
- Slog.e(TAG, "could not migrate setting for " + r.pkg, e);
}
+ updated = true;
}
- updated = true;
- } catch (Exception e) {
- Slog.e(TAG, "could not restore " + r.pkg, e);
}
+ if (p != null) {
+ mPermissionHelper.setNotificationPermission(p);
+ }
+ } catch (Exception e) {
+ Slog.e(TAG, "could not restore " + pkg, e);
}
// Package upgrade
try {
- synchronized (mPackagePreferences) {
- PackagePreferences fullPackagePreferences = getPackagePreferencesLocked(pkg,
- mPm.getPackageUidAsUser(pkg, changeUserId));
- if (fullPackagePreferences != null) {
- updated |= createDefaultChannelIfNeededLocked(fullPackagePreferences);
- updated |= deleteDefaultChannelIfNeededLocked(fullPackagePreferences);
- }
+ PackagePreferences fullPackagePreferences = getPackagePreferencesLocked(pkg,
+ mPm.getPackageUidAsUser(pkg, changeUserId));
+ if (fullPackagePreferences != null) {
+ updated |= createDefaultChannelIfNeededLocked(fullPackagePreferences);
+ updated |= deleteDefaultChannelIfNeededLocked(fullPackagePreferences);
}
} catch (PackageManager.NameNotFoundException e) {
}
@@ -2754,7 +2759,7 @@
}
public void clearData(String pkg, int uid) {
- synchronized (mPackagePreferences) {
+ synchronized (mLock) {
PackagePreferences p = getPackagePreferencesLocked(pkg, uid);
if (p != null) {
p.channels = new ArrayMap<>();
@@ -2941,7 +2946,7 @@
}
public void unlockAllNotificationChannels() {
- synchronized (mPackagePreferences) {
+ synchronized (mLock) {
final int numPackagePreferences = mPackagePreferences.size();
for (int i = 0; i < numPackagePreferences; i++) {
final PackagePreferences r = mPackagePreferences.valueAt(i);
@@ -2958,7 +2963,7 @@
PackageManager.PackageInfoFlags.of(PackageManager.MATCH_ALL),
user.getUserHandle().getIdentifier());
for (PackageInfo pi : packages) {
- synchronized (mPackagePreferences) {
+ synchronized (mLock) {
PackagePreferences p = getOrCreatePackagePreferencesLocked(
pi.packageName, pi.applicationInfo.uid);
if (p.migrateToPm && p.uid != UNKNOWN_UID) {
diff --git a/services/core/java/com/android/server/pm/PackageManagerService.java b/services/core/java/com/android/server/pm/PackageManagerService.java
index c0b8034..2e63cdb 100644
--- a/services/core/java/com/android/server/pm/PackageManagerService.java
+++ b/services/core/java/com/android/server/pm/PackageManagerService.java
@@ -186,6 +186,7 @@
import com.android.internal.pm.pkg.component.ParsedMainComponent;
import com.android.internal.pm.pkg.parsing.ParsingPackageUtils;
import com.android.internal.telephony.CarrierAppUtils;
+import com.android.internal.telephony.TelephonyPermissions;
import com.android.internal.util.ArrayUtils;
import com.android.internal.util.CollectionUtils;
import com.android.internal.util.ConcurrentUtils;
@@ -4492,8 +4493,7 @@
void setSystemAppHiddenUntilInstalled(@NonNull Computer snapshot, String packageName,
boolean hidden) {
final int callingUid = Binder.getCallingUid();
- final boolean calledFromSystemOrPhone = callingUid == Process.PHONE_UID
- || callingUid == Process.SYSTEM_UID;
+ final boolean calledFromSystemOrPhone = TelephonyPermissions.isSystemOrPhone(callingUid);
if (!calledFromSystemOrPhone) {
mContext.enforceCallingOrSelfPermission(Manifest.permission.SUSPEND_APPS,
"setSystemAppHiddenUntilInstalled");
diff --git a/services/core/java/com/android/server/pm/PackageManagerServiceUtils.java b/services/core/java/com/android/server/pm/PackageManagerServiceUtils.java
index ff8abf8..924b36c 100644
--- a/services/core/java/com/android/server/pm/PackageManagerServiceUtils.java
+++ b/services/core/java/com/android/server/pm/PackageManagerServiceUtils.java
@@ -92,6 +92,7 @@
import com.android.internal.content.InstallLocationUtils;
import com.android.internal.content.NativeLibraryHelper;
+import com.android.internal.telephony.TelephonyPermissions;
import com.android.internal.util.ArrayUtils;
import com.android.internal.util.FastPrintWriter;
import com.android.internal.util.HexDump;
@@ -356,7 +357,7 @@
* If not, throws a {@link SecurityException}.
*/
public static void enforceSystemOrPhoneCaller(String methodName, int callingUid) {
- if (callingUid != Process.PHONE_UID && callingUid != Process.SYSTEM_UID) {
+ if (!TelephonyPermissions.isSystemOrPhone(callingUid)) {
throw new SecurityException(
"Cannot call " + methodName + " from UID " + callingUid);
}
diff --git a/services/java/com/android/server/SystemServer.java b/services/java/com/android/server/SystemServer.java
index 791d030..e5a1ebf 100644
--- a/services/java/com/android/server/SystemServer.java
+++ b/services/java/com/android/server/SystemServer.java
@@ -2445,11 +2445,11 @@
t.traceEnd();
}
- t.traceBegin("CertBlacklister");
+ t.traceBegin("CertBlocklister");
try {
- CertBlacklister blacklister = new CertBlacklister(context);
+ CertBlocklister blocklister = new CertBlocklister(context);
} catch (Throwable e) {
- reportWtf("starting CertBlacklister", e);
+ reportWtf("starting CertBlocklister", e);
}
t.traceEnd();
diff --git a/services/tests/mockingservicestests/src/com/android/server/trust/TrustManagerServiceTest.java b/services/tests/mockingservicestests/src/com/android/server/trust/TrustManagerServiceTest.java
index 7aec42b..00daf41 100644
--- a/services/tests/mockingservicestests/src/com/android/server/trust/TrustManagerServiceTest.java
+++ b/services/tests/mockingservicestests/src/com/android/server/trust/TrustManagerServiceTest.java
@@ -43,6 +43,7 @@
import android.Manifest;
import android.annotation.Nullable;
import android.app.ActivityManager;
+import android.app.ActivityManagerInternal;
import android.app.AlarmManager;
import android.app.IActivityManager;
import android.app.admin.DevicePolicyManager;
@@ -142,6 +143,7 @@
private final Map<ComponentName, ITrustAgentService.Stub> mMockTrustAgents = new HashMap<>();
private @Mock ActivityManager mActivityManager;
+ private @Mock ActivityManagerInternal mActivityManagerInternal;
private @Mock AlarmManager mAlarmManager;
private @Mock BiometricManager mBiometricManager;
private @Mock DevicePolicyManager mDevicePolicyManager;
@@ -158,6 +160,7 @@
private HandlerThread mHandlerThread;
private TrustManagerService mService;
private ITrustManager mTrustManager;
+ private ActivityManagerInternal mPreviousActivityManagerInternal;
@Before
public void setUp() throws Exception {
@@ -210,6 +213,11 @@
mMockContext.setMockPackageManager(mPackageManager);
mMockContext.addMockSystemService(UserManager.class, mUserManager);
doReturn(mWindowManager).when(() -> WindowManagerGlobal.getWindowManagerService());
+ mPreviousActivityManagerInternal = LocalServices.getService(
+ ActivityManagerInternal.class);
+ LocalServices.removeServiceForTest(ActivityManagerInternal.class);
+ LocalServices.addService(ActivityManagerInternal.class,
+ mActivityManagerInternal);
LocalServices.addService(SystemServiceManager.class, mock(SystemServiceManager.class));
grantPermission(Manifest.permission.ACCESS_KEYGUARD_SECURE_STORAGE);
@@ -257,7 +265,14 @@
@After
public void tearDown() {
LocalServices.removeServiceForTest(SystemServiceManager.class);
- mHandlerThread.quit();
+ LocalServices.removeServiceForTest(ActivityManagerInternal.class);
+ if (mPreviousActivityManagerInternal != null) {
+ LocalServices.addService(ActivityManagerInternal.class,
+ mPreviousActivityManagerInternal);
+ }
+ if (mHandlerThread != null) {
+ mHandlerThread.quit();
+ }
}
@Test
diff --git a/services/tests/uiservicestests/src/com/android/server/notification/PreferencesHelperTest.java b/services/tests/uiservicestests/src/com/android/server/notification/PreferencesHelperTest.java
index d151345..559c324 100644
--- a/services/tests/uiservicestests/src/com/android/server/notification/PreferencesHelperTest.java
+++ b/services/tests/uiservicestests/src/com/android/server/notification/PreferencesHelperTest.java
@@ -188,6 +188,7 @@
import java.util.Map;
import java.util.Objects;
import java.util.Set;
+import java.util.concurrent.CountDownLatch;
import java.util.concurrent.ThreadLocalRandom;
@SmallTest
@@ -489,6 +490,34 @@
when(mPm.getPackageUidAsUser(eq(packageName), anyInt())).thenReturn(uid);
}
+ private static void testThreadSafety(Runnable operationToTest, int nThreads,
+ int nRunsPerThread) throws Exception {
+ final CountDownLatch startLatch = new CountDownLatch(1);
+ final CountDownLatch doneLatch = new CountDownLatch(nThreads);
+
+ for (int i = 0; i < nThreads; i++) {
+ Runnable threadRunnable = () -> {
+ try {
+ startLatch.await();
+ for (int j = 0; j < nRunsPerThread; j++) {
+ operationToTest.run();
+ }
+ } catch (InterruptedException e) {
+ e.printStackTrace();
+ } finally {
+ doneLatch.countDown();
+ }
+ };
+ new Thread(threadRunnable, "Test Thread #" + i).start();
+ }
+
+ // Ready set go
+ startLatch.countDown();
+
+ // Wait for all test threads to be done.
+ doneLatch.await();
+ }
+
@Test
public void testWriteXml_onlyBackupsTargetUser() throws Exception {
// Setup package notifications.
@@ -6193,6 +6222,36 @@
.isEqualTo(IMPORTANCE_LOW);
}
+
+ @Test
+ public void testRestoredWithoutUid_threadSafety() throws Exception {
+ when(mPm.getPackageUidAsUser(anyString(), anyInt())).thenReturn(UNKNOWN_UID);
+ when(mPm.getApplicationInfoAsUser(anyString(), anyInt(), anyInt())).thenThrow(
+ new PackageManager.NameNotFoundException());
+ when(mClock.millis()).thenReturn(System.currentTimeMillis());
+ testThreadSafety(() -> {
+ String id = "id";
+ String xml = "<ranking version=\"1\">\n"
+ + "<package name=\"" + Thread.currentThread()+ "\" show_badge=\"true\">\n"
+ + "<channel id=\"" + id + "\" name=\"name\" importance=\"2\" "
+ + "show_badge=\"true\" />\n"
+ + "</package>\n"
+ + "<package name=\"" + PKG_P + "\" show_badge=\"true\">\n"
+ + "</package>\n"
+ + "</ranking>\n";
+
+ try {
+ loadByteArrayXml(xml.getBytes(), true, USER_SYSTEM);
+ } catch (Exception e) {
+ throw new RuntimeException(e);
+ }
+
+ // trigger a removal from the list
+ mXmlHelper.onPackagesChanged(true, USER_SYSTEM, new String[]{PKG_P},
+ new int[]{UNKNOWN_UID});
+ }, 20, 50);
+ }
+
private static NotificationChannel cloneChannel(NotificationChannel original) {
Parcel parcel = Parcel.obtain();
try {
diff --git a/telephony/common/android/telephony/LocationAccessPolicy.java b/telephony/common/android/telephony/LocationAccessPolicy.java
index d4b6c91..feea55b 100644
--- a/telephony/common/android/telephony/LocationAccessPolicy.java
+++ b/telephony/common/android/telephony/LocationAccessPolicy.java
@@ -32,6 +32,8 @@
import android.util.Log;
import android.widget.Toast;
+import com.android.internal.telephony.TelephonyPermissions;
+import com.android.internal.telephony.flags.Flags;
import com.android.internal.telephony.util.TelephonyUtils;
/**
@@ -310,10 +312,18 @@
// This avoid breaking legacy code that rely on public-facing APIs to access cell location,
// and it doesn't create an info leak risk because the cell location is stored in the phone
// process anyway, and the system server already has location access.
- if (query.callingUid == Process.PHONE_UID || query.callingUid == Process.SYSTEM_UID
- || query.callingUid == Process.NETWORK_STACK_UID
- || query.callingUid == Process.ROOT_UID) {
- return LocationPermissionResult.ALLOWED;
+ if (Flags.supportPhoneUidCheckForMultiuser()) {
+ if (TelephonyPermissions.isSystemOrPhone(query.callingUid)
+ || UserHandle.isSameApp(query.callingUid, Process.NETWORK_STACK_UID)
+ || UserHandle.isSameApp(query.callingUid, Process.ROOT_UID)) {
+ return LocationPermissionResult.ALLOWED;
+ }
+ } else {
+ if (query.callingUid == Process.PHONE_UID || query.callingUid == Process.SYSTEM_UID
+ || query.callingUid == Process.NETWORK_STACK_UID
+ || query.callingUid == Process.ROOT_UID) {
+ return LocationPermissionResult.ALLOWED;
+ }
}
// Check the system-wide requirements. If the location main switch is off and the caller is