diff options
35 files changed, 370 insertions, 438 deletions
diff --git a/core/api/system-current.txt b/core/api/system-current.txt index b92df4cf7884..a0547411cd9e 100644 --- a/core/api/system-current.txt +++ b/core/api/system-current.txt @@ -2950,6 +2950,7 @@ package android.app.supervision { @FlaggedApi("android.app.supervision.flags.supervision_manager_apis") public class SupervisionManager { method @FlaggedApi("android.app.supervision.flags.supervision_manager_apis") @Nullable @RequiresPermission(anyOf={android.Manifest.permission.MANAGE_USERS, android.Manifest.permission.QUERY_USERS}) public android.content.Intent createConfirmSupervisionCredentialsIntent(); method @FlaggedApi("android.app.supervision.flags.supervision_manager_apis") @RequiresPermission(anyOf={android.Manifest.permission.MANAGE_USERS, android.Manifest.permission.QUERY_USERS}) public boolean isSupervisionEnabled(); + method @FlaggedApi("android.permission.flags.enable_system_supervision_role_behavior") @RequiresPermission(android.Manifest.permission.MANAGE_ROLE_HOLDERS) public boolean shouldAllowBypassingSupervisionRoleQualification(); } } diff --git a/core/api/test-current.txt b/core/api/test-current.txt index daa1902edf02..1e21991cd380 100644 --- a/core/api/test-current.txt +++ b/core/api/test-current.txt @@ -369,7 +369,7 @@ package android.app { } public final class NotificationChannel implements android.os.Parcelable { - method @FlaggedApi("android.service.notification.notification_conversation_channel_management") @NonNull public android.app.NotificationChannel copy(); + method @NonNull public android.app.NotificationChannel copy(); method public int getOriginalImportance(); method public boolean isImportanceLockedByCriticalDeviceFunction(); method public void lockFields(int); diff --git a/core/java/android/app/NotificationChannel.java b/core/java/android/app/NotificationChannel.java index d88395331656..c1d80c93cfd6 100644 --- a/core/java/android/app/NotificationChannel.java +++ b/core/java/android/app/NotificationChannel.java @@ -508,7 +508,6 @@ public final class NotificationChannel implements Parcelable { /** @hide */ @TestApi @NonNull - @FlaggedApi(FLAG_NOTIFICATION_CONVERSATION_CHANNEL_MANAGEMENT) public NotificationChannel copy() { NotificationChannel copy = new NotificationChannel(mId, mName, mImportance); copy.setDescription(mDesc); diff --git a/core/java/android/app/NotificationChannelGroup.java b/core/java/android/app/NotificationChannelGroup.java index 92db8b329045..06b492c417d8 100644 --- a/core/java/android/app/NotificationChannelGroup.java +++ b/core/java/android/app/NotificationChannelGroup.java @@ -221,7 +221,10 @@ public final class NotificationChannelGroup implements Parcelable { * @hide */ public void setChannels(List<NotificationChannel> channels) { - mChannels = channels; + mChannels.clear(); + if (channels != null) { + mChannels.addAll(channels); + } } /** @@ -331,7 +334,9 @@ public final class NotificationChannelGroup implements Parcelable { NotificationChannelGroup cloned = new NotificationChannelGroup(getId(), getName()); cloned.setDescription(getDescription()); cloned.setBlocked(isBlocked()); - cloned.setChannels(getChannels()); + for (NotificationChannel c : mChannels) { + cloned.addChannel(c.copy()); + } cloned.lockFields(mUserLockedFields); return cloned; } diff --git a/core/java/android/app/NotificationManager.java b/core/java/android/app/NotificationManager.java index 69e3ef9086d5..f24eb0a63b26 100644 --- a/core/java/android/app/NotificationManager.java +++ b/core/java/android/app/NotificationManager.java @@ -1317,10 +1317,16 @@ public class NotificationManager { */ public List<NotificationChannel> getNotificationChannels() { if (Flags.nmBinderPerfCacheChannels()) { - return mNotificationChannelListCache.query(new NotificationChannelQuery( - mContext.getOpPackageName(), - mContext.getPackageName(), - mContext.getUserId())); + List<NotificationChannel> channelList = mNotificationChannelListCache.query( + new NotificationChannelQuery(mContext.getOpPackageName(), + mContext.getPackageName(), mContext.getUserId())); + List<NotificationChannel> out = new ArrayList(); + if (channelList != null) { + for (NotificationChannel c : channelList) { + out.add(c.copy()); + } + } + return out; } else { INotificationManager service = service(); try { @@ -1343,7 +1349,7 @@ public class NotificationManager { } for (NotificationChannel channel : channels) { if (channelId.equals(channel.getId())) { - return channel; + return channel.copy(); } } return null; @@ -1364,12 +1370,12 @@ public class NotificationManager { for (NotificationChannel channel : channels) { if (conversationId.equals(channel.getConversationId()) && channelId.equals(channel.getParentChannelId())) { - return channel; + return channel.copy(); } else if (channelId.equals(channel.getId())) { parent = channel; } } - return parent; + return parent != null ? parent.copy() : null; } /** @@ -1405,8 +1411,9 @@ public class NotificationManager { new NotificationChannelQuery(pkgName, pkgName, mContext.getUserId())); Map<String, NotificationChannelGroup> groupHeaders = mNotificationChannelGroupsCache.query(pkgName); - return NotificationChannelGroupsHelper.getGroupWithChannels(channelGroupId, channelList, - groupHeaders, /* includeDeleted= */ false); + NotificationChannelGroup ncg = NotificationChannelGroupsHelper.getGroupWithChannels( + channelGroupId, channelList, groupHeaders, /* includeDeleted= */ false); + return ncg != null ? ncg.clone() : null; } else { INotificationManager service = service(); try { @@ -1428,8 +1435,14 @@ public class NotificationManager { new NotificationChannelQuery(pkgName, pkgName, mContext.getUserId())); Map<String, NotificationChannelGroup> groupHeaders = mNotificationChannelGroupsCache.query(pkgName); - return NotificationChannelGroupsHelper.getGroupsWithChannels(channelList, groupHeaders, - NotificationChannelGroupsHelper.Params.forAllGroups()); + List<NotificationChannelGroup> populatedGroupList = + NotificationChannelGroupsHelper.getGroupsWithChannels(channelList, groupHeaders, + NotificationChannelGroupsHelper.Params.forAllGroups()); + List<NotificationChannelGroup> out = new ArrayList<>(); + for (NotificationChannelGroup g : populatedGroupList) { + out.add(g.clone()); + } + return out; } else { INotificationManager service = service(); try { diff --git a/core/java/android/app/supervision/ISupervisionManager.aidl b/core/java/android/app/supervision/ISupervisionManager.aidl index 2f67a8abcd17..801162f3cbd3 100644 --- a/core/java/android/app/supervision/ISupervisionManager.aidl +++ b/core/java/android/app/supervision/ISupervisionManager.aidl @@ -27,4 +27,6 @@ interface ISupervisionManager { boolean isSupervisionEnabledForUser(int userId); void setSupervisionEnabledForUser(int userId, boolean enabled); String getActiveSupervisionAppPackage(int userId); + @JavaPassthrough(annotation="@android.annotation.RequiresPermission(android.Manifest.permission.MANAGE_ROLE_HOLDERS)") + boolean shouldAllowBypassingSupervisionRoleQualification(); } diff --git a/core/java/android/app/supervision/SupervisionManager.java b/core/java/android/app/supervision/SupervisionManager.java index 172ed2358a5d..76a789d3426f 100644 --- a/core/java/android/app/supervision/SupervisionManager.java +++ b/core/java/android/app/supervision/SupervisionManager.java @@ -19,6 +19,7 @@ package android.app.supervision; import static android.Manifest.permission.INTERACT_ACROSS_USERS; import static android.Manifest.permission.MANAGE_USERS; import static android.Manifest.permission.QUERY_USERS; +import static android.permission.flags.Flags.FLAG_ENABLE_SYSTEM_SUPERVISION_ROLE_BEHAVIOR; import android.annotation.FlaggedApi; import android.annotation.Nullable; @@ -193,4 +194,25 @@ public class SupervisionManager { } return null; } + + + /** + * @return {@code true} if bypassing the qualification is allowed for the specified role based + * on the current state of the device. + * + * @hide + */ + @SystemApi + @FlaggedApi(FLAG_ENABLE_SYSTEM_SUPERVISION_ROLE_BEHAVIOR) + @RequiresPermission(android.Manifest.permission.MANAGE_ROLE_HOLDERS) + public boolean shouldAllowBypassingSupervisionRoleQualification() { + if (mService != null) { + try { + return mService.shouldAllowBypassingSupervisionRoleQualification(); + } catch (RemoteException e) { + throw e.rethrowFromSystemServer(); + } + } + return false; + } } diff --git a/core/java/android/permission/flags.aconfig b/core/java/android/permission/flags.aconfig index 34272b17cf54..ef6f37ac6f9c 100644 --- a/core/java/android/permission/flags.aconfig +++ b/core/java/android/permission/flags.aconfig @@ -554,3 +554,12 @@ flag { description: "This flag is used to add role protection to READ_BLOCKED_NUMBERS for SYSTEM_UI_INTELLIGENCE" bug: "354758615" } + +flag { + name: "enable_system_supervision_role_behavior" + is_fixed_read_only: true + is_exported: true + namespace: "supervision" + description: "This flag is used to enable the role behavior for the system supervision role" + bug: "378102594" +} diff --git a/core/java/android/window/flags/lse_desktop_experience.aconfig b/core/java/android/window/flags/lse_desktop_experience.aconfig index 2393edacd116..07882b6e5c67 100644 --- a/core/java/android/window/flags/lse_desktop_experience.aconfig +++ b/core/java/android/window/flags/lse_desktop_experience.aconfig @@ -1016,3 +1016,13 @@ flag { purpose: PURPOSE_BUGFIX } } + +flag { + name: "enable_desktop_close_task_animation_in_dtc_bugfix" + namespace: "lse_desktop_experience" + description: "Enables bugfix to handle close task animation within DesktopTasksController." + bug: "403345083" + metadata { + purpose: PURPOSE_BUGFIX + } +} diff --git a/core/tests/coretests/src/android/app/NotificationManagerTest.java b/core/tests/coretests/src/android/app/NotificationManagerTest.java index 250b9ce8d89d..001eb620dd0f 100644 --- a/core/tests/coretests/src/android/app/NotificationManagerTest.java +++ b/core/tests/coretests/src/android/app/NotificationManagerTest.java @@ -442,6 +442,44 @@ public class NotificationManagerTest { @Test @EnableFlags(Flags.FLAG_NM_BINDER_PERF_CACHE_CHANNELS) + public void getNotificationChannel_localModificationDoesNotChangeCache() throws Exception { + NotificationManager.invalidateNotificationChannelCache(); + NotificationChannel original = new NotificationChannel("id", "name", + NotificationManager.IMPORTANCE_DEFAULT); + NotificationChannel originalConv = new NotificationChannel("", "name_conversation", + NotificationManager.IMPORTANCE_DEFAULT); + originalConv.setConversationId("id", "id_conversation"); + when(mNotificationManager.mBackendService.getNotificationChannels(any(), any(), + anyInt())).thenReturn(new ParceledListSlice<>( + List.of(original.copy(), originalConv.copy()))); + + // modify the output channel, but only locally + NotificationChannel out = mNotificationManager.getNotificationChannel("id"); + out.setName("modified"); + + // This should not change the result of getNotificationChannel + assertThat(mNotificationManager.getNotificationChannel("id")).isEqualTo(original); + assertThat(mNotificationManager.getNotificationChannel("id")).isNotEqualTo(out); + + // and also check the conversation channel + NotificationChannel outConv = mNotificationManager.getNotificationChannel("id", + "id_conversation"); + outConv.setName("conversation_modified"); + assertThat(mNotificationManager.getNotificationChannel("id", "id_conversation")).isEqualTo( + originalConv); + assertThat( + mNotificationManager.getNotificationChannel("id", "id_conversation")).isNotEqualTo( + outConv); + + // nonexistent conversation returns the (not modified) parent channel + assertThat(mNotificationManager.getNotificationChannel("id", "nonexistent")).isEqualTo( + original); + assertThat(mNotificationManager.getNotificationChannel("id", "nonexistent")).isNotEqualTo( + out); + } + + @Test + @EnableFlags(Flags.FLAG_NM_BINDER_PERF_CACHE_CHANNELS) public void getNotificationChannelGroup_cachedUntilInvalidated() throws Exception { // Data setup: group has some channels in it NotificationChannelGroup g1 = new NotificationChannelGroup("g1", "group one"); @@ -521,6 +559,37 @@ public class NotificationManagerTest { } @Test + @EnableFlags(Flags.FLAG_NM_BINDER_PERF_CACHE_CHANNELS) + public void getNotificationChannelGroup_localModificationDoesNotChangeCache() throws Exception { + // Group setup + NotificationChannelGroup g1 = new NotificationChannelGroup("g1", "group one"); + NotificationChannel nc1 = new NotificationChannel("nc1", "channel one", + NotificationManager.IMPORTANCE_DEFAULT); + nc1.setGroup("g1"); + NotificationChannel nc2 = new NotificationChannel("nc2", "channel two", + NotificationManager.IMPORTANCE_DEFAULT); + nc2.setGroup("g1"); + + NotificationManager.invalidateNotificationChannelCache(); + NotificationManager.invalidateNotificationChannelGroupCache(); + when(mNotificationManager.mBackendService.getNotificationChannelGroupsWithoutChannels( + any())).thenReturn(new ParceledListSlice<>(List.of(g1.clone()))); + when(mNotificationManager.mBackendService.getNotificationChannels(any(), any(), anyInt())) + .thenReturn(new ParceledListSlice<>(List.of(nc1.copy(), nc2.copy()))); + + NotificationChannelGroup g1result = mNotificationManager.getNotificationChannelGroup("g1"); + g1result.setDescription("something different!"); + for (NotificationChannel c : g1result.getChannels()) { + c.setDescription("also something different"); + } + + // expected output equivalent to original, unchanged + NotificationChannelGroup expectedG1 = g1.clone(); + expectedG1.setChannels(List.of(nc1, nc2)); + assertThat(mNotificationManager.getNotificationChannelGroup("g1")).isEqualTo(expectedG1); + } + + @Test @EnableFlags(Flags.FLAG_MODES_UI) public void areAutomaticZenRulesUserManaged_handheld_isTrue() { PackageManager pm = mock(PackageManager.class); diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/common/split/SplitState.java b/libs/WindowManager/Shell/src/com/android/wm/shell/common/split/SplitState.java index ad0e7fc187e9..394c445787b4 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/common/split/SplitState.java +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/common/split/SplitState.java @@ -17,6 +17,10 @@ package com.android.wm.shell.common.split; import static com.android.wm.shell.shared.split.SplitScreenConstants.NOT_IN_SPLIT; +import static com.android.wm.shell.shared.split.SplitScreenConstants.SNAP_TO_2_10_90; +import static com.android.wm.shell.shared.split.SplitScreenConstants.SNAP_TO_2_90_10; +import static com.android.wm.shell.shared.split.SplitScreenConstants.SNAP_TO_3_10_45_45; +import static com.android.wm.shell.shared.split.SplitScreenConstants.SNAP_TO_3_45_45_10; import static com.android.wm.shell.shared.split.SplitScreenConstants.SplitScreenState; import android.graphics.Rect; @@ -62,4 +66,12 @@ public class SplitState { public List<RectF> getCurrentLayout() { return getLayout(mState); } + + /** @return {@code true} if at least one app is partially offscreen in the current layout. */ + public boolean currentStateSupportsOffscreenApps() { + return mState == SNAP_TO_2_10_90 + || mState == SNAP_TO_2_90_10 + || mState == SNAP_TO_3_10_45_45 + || mState == SNAP_TO_3_45_45_10; + } } diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/StageCoordinator.java b/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/StageCoordinator.java index 10db5ca03637..d240aca522bb 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/StageCoordinator.java +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/StageCoordinator.java @@ -3618,9 +3618,7 @@ public class StageCoordinator implements SplitLayout.SplitLayoutHandler, finishEnterSplitScreen(finishT); addDividerBarToTransition(info, true /* show */); - if (Flags.enableFlexibleTwoAppSplit()) { - addAllDimLayersToTransition(info, true /* show */); - } + addAllDimLayersToTransition(info, true /* show */); return true; } @@ -3871,9 +3869,7 @@ public class StageCoordinator implements SplitLayout.SplitLayoutHandler, } addDividerBarToTransition(info, false /* show */); - if (Flags.enableFlexibleTwoAppSplit()) { - addAllDimLayersToTransition(info, false /* show */); - } + addAllDimLayersToTransition(info, false /* show */); } /** Call this when the recents animation canceled during split-screen. */ @@ -3999,8 +3995,15 @@ public class StageCoordinator implements SplitLayout.SplitLayoutHandler, info.addChange(barChange); } - /** Add dim layers to the transition, so that they can be hidden/shown when animation starts. */ + /** + * Add dim layers to the transition, so that they can be hidden/shown when animation starts. + * They're only added if there is at least one offscreen app. + */ private void addAllDimLayersToTransition(@NonNull TransitionInfo info, boolean show) { + if (!mSplitState.currentStateSupportsOffscreenApps()) { + return; + } + if (Flags.enableFlexibleSplit()) { List<StageTaskListener> stages = mStageOrderOperator.getActiveStages(); for (int i = 0; i < stages.size(); i++) { @@ -4008,7 +4011,7 @@ public class StageCoordinator implements SplitLayout.SplitLayoutHandler, mSplitState.getCurrentLayout().get(i).roundOut(mTempRect1); addDimLayerToTransition(info, show, stage, mTempRect1); } - } else { + } else if (enableFlexibleTwoAppSplit()) { addDimLayerToTransition(info, show, mMainStage, getMainStageBounds()); addDimLayerToTransition(info, show, mSideStage, getSideStageBounds()); } diff --git a/libs/WindowManager/Shell/tests/e2e/desktopmode/scenarios/src/com/android/wm/shell/scenarios/UnminimizeAppFromTaskbar.kt b/libs/WindowManager/Shell/tests/e2e/desktopmode/scenarios/src/com/android/wm/shell/scenarios/UnminimizeAppFromTaskbar.kt index 7d9f2bf8fdf6..05ddb4043b82 100644 --- a/libs/WindowManager/Shell/tests/e2e/desktopmode/scenarios/src/com/android/wm/shell/scenarios/UnminimizeAppFromTaskbar.kt +++ b/libs/WindowManager/Shell/tests/e2e/desktopmode/scenarios/src/com/android/wm/shell/scenarios/UnminimizeAppFromTaskbar.kt @@ -19,7 +19,7 @@ package com.android.wm.shell.scenarios import android.app.Instrumentation import android.tools.NavBar import android.tools.Rotation -import android.tools.device.apphelpers.GmailAppHelper +import android.tools.device.apphelpers.CalculatorAppHelper import android.tools.flicker.rules.ChangeDisplayOrientationRule import android.tools.traces.parsers.WindowManagerStateHelper import androidx.test.platform.app.InstrumentationRegistry @@ -44,8 +44,9 @@ abstract class UnminimizeAppFromTaskbar(val rotation: Rotation = Rotation.ROTATI private val wmHelper = WindowManagerStateHelper(instrumentation) private val device = UiDevice.getInstance(instrumentation) private val testApp = DesktopModeAppHelper(SimpleAppHelper(instrumentation)) - private val gmailHelper = GmailAppHelper(instrumentation) - private val gmailApp = DesktopModeAppHelper(gmailHelper) + private val calculatorHelper = CalculatorAppHelper(instrumentation) + private val calculatorApp = DesktopModeAppHelper(calculatorHelper) + @Rule @JvmField val testSetupRule = Utils.testSetupRule(NavBar.MODE_GESTURAL, rotation) @@ -59,20 +60,20 @@ abstract class UnminimizeAppFromTaskbar(val rotation: Rotation = Rotation.ROTATI ChangeDisplayOrientationRule.setRotation(rotation) testApp.enterDesktopMode(wmHelper, device) tapl.showTaskbarIfHidden() - gmailApp.launchViaIntent(wmHelper) - gmailApp.minimizeDesktopApp(wmHelper, device) + calculatorApp.launchViaIntent(wmHelper) + calculatorApp.minimizeDesktopApp(wmHelper, device) } @Test open fun unminimizeApp() { tapl.launchedAppState.taskbar - .getAppIcon(gmailHelper.appName) - .launch(gmailHelper.packageName) + .getAppIcon(calculatorHelper.appName) + .launch(calculatorApp.packageName) } @After fun teardown() { testApp.exit(wmHelper) - gmailApp.exit(wmHelper) + calculatorApp.exit(wmHelper) } -}
\ No newline at end of file +} diff --git a/packages/SystemUI/animation/src/com/android/systemui/animation/RemoteAnimationRunnerCompat.java b/packages/SystemUI/animation/src/com/android/systemui/animation/RemoteAnimationRunnerCompat.java index 9e08317d2c6b..041ccb567146 100644 --- a/packages/SystemUI/animation/src/com/android/systemui/animation/RemoteAnimationRunnerCompat.java +++ b/packages/SystemUI/animation/src/com/android/systemui/animation/RemoteAnimationRunnerCompat.java @@ -199,8 +199,10 @@ public abstract class RemoteAnimationRunnerCompat extends IRemoteAnimationRunner info.releaseAllSurfaces(); // Make sure that the transition leashes created are not leaked. for (SurfaceControl leash : leashMap.values()) { - if (leash.isValid()) { + try { finishTransaction.reparent(leash, null); + } catch (Exception e) { + Log.e(TAG, "Failed to reparent leash", e); } } // Don't release here since launcher might still be using them. Instead diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/media/controls/domain/pipeline/MediaDataLoaderTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/media/controls/domain/pipeline/MediaDataLoaderTest.kt index 1f1a74b6c389..63c0f4371c62 100644 --- a/packages/SystemUI/multivalentTests/src/com/android/systemui/media/controls/domain/pipeline/MediaDataLoaderTest.kt +++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/media/controls/domain/pipeline/MediaDataLoaderTest.kt @@ -34,7 +34,6 @@ import androidx.media.utils.MediaConstants import androidx.test.ext.junit.runners.AndroidJUnit4 import androidx.test.filters.SmallTest import com.android.systemui.SysuiTestCase -import com.android.systemui.flags.Flags.MEDIA_RESUME_PROGRESS import com.android.systemui.flags.fakeFeatureFlagsClassic import com.android.systemui.graphics.ImageLoader import com.android.systemui.graphics.imageLoader @@ -167,8 +166,6 @@ class MediaDataLoaderTest : SysuiTestCase() { @Test fun loadMediaDataForResumption_returnsMediaData() = testScope.runTest { - fakeFeatureFlags.set(MEDIA_RESUME_PROGRESS, true) - val song = "THIS_IS_A_SONG" val artist = "THIS_IS_AN_ARTIST" val albumArt = Bitmap.createBitmap(100, 100, Bitmap.Config.ARGB_8888) diff --git a/packages/SystemUI/src/com/android/systemui/flags/Flags.kt b/packages/SystemUI/src/com/android/systemui/flags/Flags.kt index 84bb23140ae7..9a37439e7486 100644 --- a/packages/SystemUI/src/com/android/systemui/flags/Flags.kt +++ b/packages/SystemUI/src/com/android/systemui/flags/Flags.kt @@ -200,9 +200,6 @@ object Flags { // TODO(b/266157412): Tracking Bug val MEDIA_RETAIN_SESSIONS = unreleasedFlag("media_retain_sessions") - // TODO(b/267007629): Tracking Bug - val MEDIA_RESUME_PROGRESS = releasedFlag("media_resume_progress") - // TODO(b/270437894): Tracking Bug val MEDIA_REMOTE_RESUME = unreleasedFlag("media_remote_resume") diff --git a/packages/SystemUI/src/com/android/systemui/media/controls/domain/pipeline/LegacyMediaDataManagerImpl.kt b/packages/SystemUI/src/com/android/systemui/media/controls/domain/pipeline/LegacyMediaDataManagerImpl.kt index c2efc7559487..ab4467e87a3e 100644 --- a/packages/SystemUI/src/com/android/systemui/media/controls/domain/pipeline/LegacyMediaDataManagerImpl.kt +++ b/packages/SystemUI/src/com/android/systemui/media/controls/domain/pipeline/LegacyMediaDataManagerImpl.kt @@ -875,11 +875,7 @@ class LegacyMediaDataManagerImpl( desc.extras?.getLong(MediaConstants.METADATA_KEY_IS_EXPLICIT) == MediaConstants.METADATA_VALUE_ATTRIBUTE_PRESENT - val progress = - if (mediaFlags.isResumeProgressEnabled()) { - MediaDataUtils.getDescriptionProgress(desc.extras) - } else null - + val progress = MediaDataUtils.getDescriptionProgress(desc.extras) val mediaAction = getResumeMediaAction(resumeAction) val lastActive = systemClock.elapsedRealtime() val createdTimestampMillis = currentEntry?.createdTimestampMillis ?: 0L diff --git a/packages/SystemUI/src/com/android/systemui/media/controls/domain/pipeline/MediaDataLoader.kt b/packages/SystemUI/src/com/android/systemui/media/controls/domain/pipeline/MediaDataLoader.kt index a7c5a36b804a..1a4687b59dbd 100644 --- a/packages/SystemUI/src/com/android/systemui/media/controls/domain/pipeline/MediaDataLoader.kt +++ b/packages/SystemUI/src/com/android/systemui/media/controls/domain/pipeline/MediaDataLoader.kt @@ -339,11 +339,7 @@ constructor( desc.extras?.getLong(MediaConstants.METADATA_KEY_IS_EXPLICIT) == MediaConstants.METADATA_VALUE_ATTRIBUTE_PRESENT - val progress = - if (mediaFlags.isResumeProgressEnabled()) { - MediaDataUtils.getDescriptionProgress(desc.extras) - } else null - + val progress = MediaDataUtils.getDescriptionProgress(desc.extras) val mediaAction = getResumeMediaAction(resumeAction) return MediaDataLoaderResult( appName = appName, diff --git a/packages/SystemUI/src/com/android/systemui/media/controls/domain/pipeline/MediaDataProcessor.kt b/packages/SystemUI/src/com/android/systemui/media/controls/domain/pipeline/MediaDataProcessor.kt index ca4a65953cba..7dfa69efc155 100644 --- a/packages/SystemUI/src/com/android/systemui/media/controls/domain/pipeline/MediaDataProcessor.kt +++ b/packages/SystemUI/src/com/android/systemui/media/controls/domain/pipeline/MediaDataProcessor.kt @@ -719,11 +719,7 @@ class MediaDataProcessor( desc.extras?.getLong(MediaConstants.METADATA_KEY_IS_EXPLICIT) == MediaConstants.METADATA_VALUE_ATTRIBUTE_PRESENT - val progress = - if (mediaFlags.isResumeProgressEnabled()) { - MediaDataUtils.getDescriptionProgress(desc.extras) - } else null - + val progress = MediaDataUtils.getDescriptionProgress(desc.extras) val mediaAction = getResumeMediaAction(resumeAction) val lastActive = systemClock.elapsedRealtime() val createdTimestampMillis = currentEntry?.createdTimestampMillis ?: 0L diff --git a/packages/SystemUI/src/com/android/systemui/media/controls/util/MediaFlags.kt b/packages/SystemUI/src/com/android/systemui/media/controls/util/MediaFlags.kt index 172998e09266..8ad10ba2a240 100644 --- a/packages/SystemUI/src/com/android/systemui/media/controls/util/MediaFlags.kt +++ b/packages/SystemUI/src/com/android/systemui/media/controls/util/MediaFlags.kt @@ -46,9 +46,6 @@ class MediaFlags @Inject constructor(private val featureFlags: FeatureFlagsClass */ fun isRetainingPlayersEnabled() = featureFlags.isEnabled(FlagsClassic.MEDIA_RETAIN_SESSIONS) - /** Check whether to get progress information for resume players */ - fun isResumeProgressEnabled() = featureFlags.isEnabled(FlagsClassic.MEDIA_RESUME_PROGRESS) - /** Check whether we allow remote media to generate resume controls */ fun isRemoteResumeAllowed() = featureFlags.isEnabled(FlagsClassic.MEDIA_REMOTE_RESUME) } 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 9fe3ff4c4bce..ff97bff53a65 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 @@ -364,8 +364,6 @@ constructor( contentBuilder: PromotedNotificationContentModel.Builder, imageModelProvider: ImageModelProvider, ) { - contentBuilder.personIcon = null // TODO - contentBuilder.personName = null // TODO contentBuilder.verificationIcon = notification.skeletonVerificationIcon(imageModelProvider) contentBuilder.verificationText = notification.verificationText() } diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/promoted/shared/model/PromotedNotificationContentModel.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/promoted/shared/model/PromotedNotificationContentModel.kt index ae6b2cc6cb1f..79081f42c686 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/promoted/shared/model/PromotedNotificationContentModel.kt +++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/promoted/shared/model/PromotedNotificationContentModel.kt @@ -88,8 +88,6 @@ data class PromotedNotificationContentModel( val style: Style, // for CallStyle: - val personIcon: ImageModel?, - val personName: CharSequence?, val verificationIcon: ImageModel?, val verificationText: CharSequence?, @@ -114,8 +112,6 @@ data class PromotedNotificationContentModel( var colors: Colors = Colors(backgroundColor = 0, primaryTextColor = 0) // for CallStyle: - var personIcon: ImageModel? = null - var personName: CharSequence? = null var verificationIcon: ImageModel? = null var verificationText: CharSequence? = null @@ -140,8 +136,6 @@ data class PromotedNotificationContentModel( oldProgress = oldProgress, colors = colors, style = style, - personIcon = personIcon, - personName = personName, verificationIcon = verificationIcon, verificationText = verificationText, newProgress = newProgress, @@ -200,8 +194,6 @@ data class PromotedNotificationContentModel( "oldProgress=$oldProgress, " + "colors=$colors, " + "style=$style, " + - "personIcon=${personIcon?.toRedactedString()}, " + - "personName=${personName?.toRedactedString()}, " + "verificationIcon=$verificationIcon, " + "verificationText=$verificationText, " + "newProgress=$newProgress)") diff --git a/packages/SystemUI/tests/src/com/android/systemui/media/controls/domain/pipeline/LegacyMediaDataManagerImplTest.kt b/packages/SystemUI/tests/src/com/android/systemui/media/controls/domain/pipeline/LegacyMediaDataManagerImplTest.kt index 5713ddc8ae9d..5084f318b05d 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/media/controls/domain/pipeline/LegacyMediaDataManagerImplTest.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/media/controls/domain/pipeline/LegacyMediaDataManagerImplTest.kt @@ -52,7 +52,6 @@ import com.android.systemui.SysuiTestCase import com.android.systemui.broadcast.BroadcastDispatcher import com.android.systemui.dump.DumpManager import com.android.systemui.flags.Flags.MEDIA_REMOTE_RESUME -import com.android.systemui.flags.Flags.MEDIA_RESUME_PROGRESS import com.android.systemui.flags.Flags.MEDIA_RETAIN_SESSIONS import com.android.systemui.flags.fakeFeatureFlagsClassic import com.android.systemui.kosmos.testDispatcher @@ -288,7 +287,6 @@ class LegacyMediaDataManagerImplTest(flags: FlagsParameterization) : SysuiTestCa whenever(mediaSmartspaceTarget.creationTimeMillis).thenReturn(SMARTSPACE_CREATION_TIME) whenever(mediaSmartspaceTarget.expiryTimeMillis).thenReturn(SMARTSPACE_EXPIRY_TIME) fakeFeatureFlags.set(MEDIA_RETAIN_SESSIONS, false) - fakeFeatureFlags.set(MEDIA_RESUME_PROGRESS, false) fakeFeatureFlags.set(MEDIA_REMOTE_RESUME, false) whenever(logger.getNewInstanceId()).thenReturn(instanceIdSequence.newInstanceId()) whenever(keyguardUpdateMonitor.isUserInLockdown(any())).thenReturn(false) @@ -970,8 +968,6 @@ class LegacyMediaDataManagerImplTest(flags: FlagsParameterization) : SysuiTestCa @Test fun testAddResumptionControls_hasPartialProgress() { - fakeFeatureFlags.set(MEDIA_RESUME_PROGRESS, true) - // WHEN resumption controls are added with partial progress val progress = 0.5 val extras = @@ -997,8 +993,6 @@ class LegacyMediaDataManagerImplTest(flags: FlagsParameterization) : SysuiTestCa @Test fun testAddResumptionControls_hasNotPlayedProgress() { - fakeFeatureFlags.set(MEDIA_RESUME_PROGRESS, true) - // WHEN resumption controls are added that have not been played val extras = Bundle().apply { @@ -1022,8 +1016,6 @@ class LegacyMediaDataManagerImplTest(flags: FlagsParameterization) : SysuiTestCa @Test fun testAddResumptionControls_hasFullProgress() { - fakeFeatureFlags.set(MEDIA_RESUME_PROGRESS, true) - // WHEN resumption controls are added with progress info val extras = Bundle().apply { @@ -1048,8 +1040,6 @@ class LegacyMediaDataManagerImplTest(flags: FlagsParameterization) : SysuiTestCa @Test fun testAddResumptionControls_hasNoExtras() { - fakeFeatureFlags.set(MEDIA_RESUME_PROGRESS, true) - // WHEN resumption controls are added that do not have any extras val desc = MediaDescription.Builder().run { @@ -1066,8 +1056,6 @@ class LegacyMediaDataManagerImplTest(flags: FlagsParameterization) : SysuiTestCa @Test fun testAddResumptionControls_hasEmptyTitle() { - fakeFeatureFlags.set(MEDIA_RESUME_PROGRESS, true) - // WHEN resumption controls are added that have empty title val desc = MediaDescription.Builder().run { @@ -1099,8 +1087,6 @@ class LegacyMediaDataManagerImplTest(flags: FlagsParameterization) : SysuiTestCa @Test fun testAddResumptionControls_hasBlankTitle() { - fakeFeatureFlags.set(MEDIA_RESUME_PROGRESS, true) - // WHEN resumption controls are added that have a blank title val desc = MediaDescription.Builder().run { diff --git a/packages/SystemUI/tests/src/com/android/systemui/media/controls/domain/pipeline/MediaDataProcessorTest.kt b/packages/SystemUI/tests/src/com/android/systemui/media/controls/domain/pipeline/MediaDataProcessorTest.kt index 52e5e1520ec3..5ea669d74cc1 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/media/controls/domain/pipeline/MediaDataProcessorTest.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/media/controls/domain/pipeline/MediaDataProcessorTest.kt @@ -56,7 +56,6 @@ import com.android.systemui.coroutines.collectLastValue import com.android.systemui.dump.DumpManager import com.android.systemui.flags.EnableSceneContainer import com.android.systemui.flags.Flags.MEDIA_REMOTE_RESUME -import com.android.systemui.flags.Flags.MEDIA_RESUME_PROGRESS import com.android.systemui.flags.Flags.MEDIA_RETAIN_SESSIONS import com.android.systemui.flags.fakeFeatureFlagsClassic import com.android.systemui.kosmos.testDispatcher @@ -312,7 +311,6 @@ class MediaDataProcessorTest(flags: FlagsParameterization) : SysuiTestCase() { whenever(mediaSmartspaceTarget.creationTimeMillis).thenReturn(SMARTSPACE_CREATION_TIME) whenever(mediaSmartspaceTarget.expiryTimeMillis).thenReturn(SMARTSPACE_EXPIRY_TIME) fakeFeatureFlags.set(MEDIA_RETAIN_SESSIONS, false) - fakeFeatureFlags.set(MEDIA_RESUME_PROGRESS, false) fakeFeatureFlags.set(MEDIA_REMOTE_RESUME, false) whenever(logger.getNewInstanceId()).thenReturn(instanceIdSequence.newInstanceId()) whenever(keyguardUpdateMonitor.isUserInLockdown(any())).thenReturn(false) @@ -990,8 +988,6 @@ class MediaDataProcessorTest(flags: FlagsParameterization) : SysuiTestCase() { @Test fun testAddResumptionControls_hasPartialProgress() { - fakeFeatureFlags.set(MEDIA_RESUME_PROGRESS, true) - // WHEN resumption controls are added with partial progress val progress = 0.5 val extras = @@ -1017,8 +1013,6 @@ class MediaDataProcessorTest(flags: FlagsParameterization) : SysuiTestCase() { @Test fun testAddResumptionControls_hasNotPlayedProgress() { - fakeFeatureFlags.set(MEDIA_RESUME_PROGRESS, true) - // WHEN resumption controls are added that have not been played val extras = Bundle().apply { @@ -1042,8 +1036,6 @@ class MediaDataProcessorTest(flags: FlagsParameterization) : SysuiTestCase() { @Test fun testAddResumptionControls_hasFullProgress() { - fakeFeatureFlags.set(MEDIA_RESUME_PROGRESS, true) - // WHEN resumption controls are added with progress info val extras = Bundle().apply { @@ -1068,8 +1060,6 @@ class MediaDataProcessorTest(flags: FlagsParameterization) : SysuiTestCase() { @Test fun testAddResumptionControls_hasNoExtras() { - fakeFeatureFlags.set(MEDIA_RESUME_PROGRESS, true) - // WHEN resumption controls are added that do not have any extras val desc = MediaDescription.Builder().run { @@ -1086,8 +1076,6 @@ class MediaDataProcessorTest(flags: FlagsParameterization) : SysuiTestCase() { @Test fun testAddResumptionControls_hasEmptyTitle() { - fakeFeatureFlags.set(MEDIA_RESUME_PROGRESS, true) - // WHEN resumption controls are added that have empty title val desc = MediaDescription.Builder().run { @@ -1119,8 +1107,6 @@ class MediaDataProcessorTest(flags: FlagsParameterization) : SysuiTestCase() { @Test fun testAddResumptionControls_hasBlankTitle() { - fakeFeatureFlags.set(MEDIA_RESUME_PROGRESS, true) - // WHEN resumption controls are added that have a blank title val desc = MediaDescription.Builder().run { diff --git a/services/core/java/com/android/server/input/InputManagerService.java b/services/core/java/com/android/server/input/InputManagerService.java index 07530e1c6f7b..76284fb81814 100644 --- a/services/core/java/com/android/server/input/InputManagerService.java +++ b/services/core/java/com/android/server/input/InputManagerService.java @@ -510,8 +510,7 @@ public class InputManagerService extends IInputManager.Stub KeyboardBacklightControllerInterface getKeyboardBacklightController( NativeInputManagerService nativeService) { - return new KeyboardBacklightController(mContext, nativeService, mLooper, - mUEventManager); + return new KeyboardBacklightController(mContext, nativeService, mLooper); } } diff --git a/services/core/java/com/android/server/input/KeyboardBacklightController.java b/services/core/java/com/android/server/input/KeyboardBacklightController.java index 16368c7678d1..083c0006ad65 100644 --- a/services/core/java/com/android/server/input/KeyboardBacklightController.java +++ b/services/core/java/com/android/server/input/KeyboardBacklightController.java @@ -32,7 +32,6 @@ import android.os.Looper; import android.os.Message; import android.os.RemoteException; import android.os.SystemClock; -import android.os.UEventObserver; import android.sysprop.InputProperties; import android.text.TextUtils; import android.util.IndentingPrintWriter; @@ -83,8 +82,6 @@ final class KeyboardBacklightController implements private static final long TRANSITION_ANIMATION_DURATION_MILLIS = Duration.ofSeconds(1).toMillis(); - private static final String UEVENT_KEYBOARD_BACKLIGHT_TAG = "kbd_backlight"; - @VisibleForTesting static final int[] DEFAULT_BRIGHTNESS_VALUE_FOR_LEVEL = new int[DEFAULT_NUM_BRIGHTNESS_CHANGE_STEPS + 1]; @@ -93,7 +90,6 @@ final class KeyboardBacklightController implements private final NativeInputManagerService mNative; private final Handler mHandler; private final AnimatorFactory mAnimatorFactory; - private final UEventManager mUEventManager; // Always access on handler thread or need to lock this for synchronization. private final SparseArray<KeyboardBacklightState> mKeyboardBacklights = new SparseArray<>(1); // Maintains state if all backlights should be on or turned off @@ -124,19 +120,18 @@ final class KeyboardBacklightController implements } KeyboardBacklightController(Context context, NativeInputManagerService nativeService, - Looper looper, UEventManager uEventManager) { - this(context, nativeService, looper, ValueAnimator::ofInt, uEventManager); + Looper looper) { + this(context, nativeService, looper, ValueAnimator::ofInt); } @VisibleForTesting KeyboardBacklightController(Context context, NativeInputManagerService nativeService, - Looper looper, AnimatorFactory animatorFactory, UEventManager uEventManager) { + Looper looper, AnimatorFactory animatorFactory) { mContext = context; mNative = nativeService; mHandler = new Handler(looper, this::handleMessage); mAnimatorFactory = animatorFactory; mAmbientController = new AmbientKeyboardBacklightController(context, looper); - mUEventManager = uEventManager; Resources res = mContext.getResources(); mUserInactivityThresholdMs = res.getInteger( com.android.internal.R.integer.config_keyboardBacklightTimeoutMs); @@ -154,17 +149,6 @@ final class KeyboardBacklightController implements inputManager.getInputDeviceIds()); mHandler.sendMessage(msg); - // Observe UEvents for "kbd_backlight" sysfs nodes. - // We want to observe creation of such LED nodes since they might be created after device - // FD created and InputDevice creation logic doesn't initialize LED nodes which leads to - // backlight not working. - mUEventManager.addListener(new UEventManager.UEventListener() { - @Override - public void onUEvent(UEventObserver.UEvent event) { - onKeyboardBacklightUEvent(event); - } - }, UEVENT_KEYBOARD_BACKLIGHT_TAG); - // Start ambient backlight controller mAmbientController.systemRunning(); } @@ -414,17 +398,6 @@ final class KeyboardBacklightController implements } } - @VisibleForTesting - public void onKeyboardBacklightUEvent(UEventObserver.UEvent event) { - if ("ADD".equalsIgnoreCase(event.get("ACTION")) && "LEDS".equalsIgnoreCase( - event.get("SUBSYSTEM"))) { - final String devPath = event.get("DEVPATH"); - if (isValidBacklightNodePath(devPath)) { - mNative.sysfsNodeChanged("/sys" + devPath); - } - } - } - private void updateAmbientLightListener() { boolean needToListenAmbientLightSensor = false; for (int i = 0; i < mKeyboardBacklights.size(); i++) { diff --git a/services/core/java/com/android/server/input/debug/TouchpadDebugViewController.java b/services/core/java/com/android/server/input/debug/TouchpadDebugViewController.java index 2c1d68e3dbda..8d664e848ef5 100644 --- a/services/core/java/com/android/server/input/debug/TouchpadDebugViewController.java +++ b/services/core/java/com/android/server/input/debug/TouchpadDebugViewController.java @@ -55,15 +55,17 @@ public class TouchpadDebugViewController implements InputManager.InputDeviceList @Override public void onInputDeviceAdded(int deviceId) { + if (!mTouchpadVisualizerEnabled) { + return; + } final InputManager inputManager = Objects.requireNonNull( mContext.getSystemService(InputManager.class)); InputDevice inputDevice = inputManager.getInputDevice(deviceId); - - if (Objects.requireNonNull(inputDevice).supportsSource( - InputDevice.SOURCE_TOUCHPAD | InputDevice.SOURCE_MOUSE) - && mTouchpadVisualizerEnabled) { - showDebugView(deviceId); + if (inputDevice == null || !inputDevice.supportsSource( + InputDevice.SOURCE_TOUCHPAD | InputDevice.SOURCE_MOUSE)) { + return; } + showDebugView(deviceId); } @Override diff --git a/services/core/java/com/android/server/location/contexthub/ContextHubEndpointManager.java b/services/core/java/com/android/server/location/contexthub/ContextHubEndpointManager.java index 0dc1b832f5a4..47e19089de92 100644 --- a/services/core/java/com/android/server/location/contexthub/ContextHubEndpointManager.java +++ b/services/core/java/com/android/server/location/contexthub/ContextHubEndpointManager.java @@ -192,9 +192,10 @@ import java.util.function.Consumer; * This is separate from the constructor so that this may be passed into the callback registered * with the HAL. * - * @throws InstantiationException on any failure + * @throws InstantiationException on unexpected failure + * @throws UnsupportedOperationException if not supported by the HAL */ - /* package */ void init() throws InstantiationException { + /* package */ void init() throws InstantiationException, UnsupportedOperationException { if (mSessionIdsValid) { throw new IllegalStateException("Already initialized"); } @@ -214,12 +215,11 @@ import java.util.function.Consumer; if (mHubInterface == null) { throw new IllegalStateException("Received null IEndpointCommunication"); } - } catch (RemoteException | IllegalStateException | ServiceSpecificException - | UnsupportedOperationException e) { + } catch (RemoteException | IllegalStateException | ServiceSpecificException e) { String error = "Failed to register ContextHubService as message hub"; Log.e(TAG, error, e); throw new InstantiationException(error); - } + } // Forward UnsupportedOperationException to caller int[] range = null; try { diff --git a/services/core/java/com/android/server/location/contexthub/ContextHubService.java b/services/core/java/com/android/server/location/contexthub/ContextHubService.java index 2c0c55bd8df4..44996350e3f3 100644 --- a/services/core/java/com/android/server/location/contexthub/ContextHubService.java +++ b/services/core/java/com/android/server/location/contexthub/ContextHubService.java @@ -342,17 +342,19 @@ public class ContextHubService extends IContextHubService.Stub { new ContextHubEndpointManager( mContext, mContextHubWrapper, registry, mTransactionManager); mEndpointManager.init(); - Log.i(TAG, "Enabling generic offload API"); - } catch (InstantiationException e) { + Log.d(TAG, "Enabling generic offload API"); + } catch (InstantiationException | UnsupportedOperationException e) { mEndpointManager = null; registry = null; - Log.w(TAG, "Generic offload API not supported, disabling"); + if (e instanceof UnsupportedOperationException) { + Log.d(TAG, "Generic offload API not supported by HAL"); + } } mHubInfoRegistry = registry; } else { mHubInfoRegistry = null; mEndpointManager = null; - Log.i(TAG, "Disabling generic offload API"); + Log.d(TAG, "Disabling generic offload API due to flag config"); } initDefaultClientMap(); diff --git a/services/core/java/com/android/server/pm/ComputerEngine.java b/services/core/java/com/android/server/pm/ComputerEngine.java index 7e5ada54c953..38ac0473d1a3 100644 --- a/services/core/java/com/android/server/pm/ComputerEngine.java +++ b/services/core/java/com/android/server/pm/ComputerEngine.java @@ -5484,6 +5484,9 @@ public class ComputerEngine implements Computer { // For update or already installed case, leverage the existing visibility rule. if (targetAppId != INVALID_UID) { final Object targetSetting = mSettings.getSettingBase(targetAppId); + if (targetSetting == null) { + return false; + } if (targetSetting instanceof PackageSetting) { return !shouldFilterApplication( (PackageSetting) targetSetting, callingUid, userId); diff --git a/services/supervision/java/com/android/server/supervision/SupervisionService.java b/services/supervision/java/com/android/server/supervision/SupervisionService.java index 0b5a95b0e888..c419fd2ecbd7 100644 --- a/services/supervision/java/com/android/server/supervision/SupervisionService.java +++ b/services/supervision/java/com/android/server/supervision/SupervisionService.java @@ -17,6 +17,7 @@ package com.android.server.supervision; import static android.Manifest.permission.INTERACT_ACROSS_USERS; +import static android.Manifest.permission.MANAGE_ROLE_HOLDERS; import static android.Manifest.permission.MANAGE_USERS; import static android.Manifest.permission.QUERY_USERS; import static android.content.pm.PackageManager.PERMISSION_GRANTED; @@ -171,6 +172,44 @@ public class SupervisionService extends ISupervisionManager.Stub { } @Override + public boolean shouldAllowBypassingSupervisionRoleQualification() { + enforcePermission(MANAGE_ROLE_HOLDERS); + + if (hasNonTestDefaultUsers()) { + return false; + } + + synchronized (getLockObject()) { + for (int i = 0; i < mUserData.size(); i++) { + if (mUserData.valueAt(i).supervisionEnabled) { + return false; + } + } + } + + return true; + } + + /** + * Returns true if there are any non-default non-test users. + * + * This excludes the system and main user(s) as those users are created by default. + */ + private boolean hasNonTestDefaultUsers() { + List<UserInfo> users = mInjector.getUserManagerInternal().getUsers(true); + for (var user : users) { + if (!user.isForTesting() && !user.isMain() && !isSystemUser(user)) { + return true; + } + } + return false; + } + + private static boolean isSystemUser(UserInfo userInfo) { + return (userInfo.flags & UserInfo.FLAG_SYSTEM) == UserInfo.FLAG_SYSTEM; + } + + @Override public void onShellCommand( @Nullable FileDescriptor in, @Nullable FileDescriptor out, diff --git a/services/tests/servicestests/src/com/android/server/accessibility/autoclick/AutoclickControllerTest.java b/services/tests/servicestests/src/com/android/server/accessibility/autoclick/AutoclickControllerTest.java index 0f418ab5d19c..900d5ad58719 100644 --- a/services/tests/servicestests/src/com/android/server/accessibility/autoclick/AutoclickControllerTest.java +++ b/services/tests/servicestests/src/com/android/server/accessibility/autoclick/AutoclickControllerTest.java @@ -331,15 +331,7 @@ public class AutoclickControllerTest { injectFakeMouseActionHoverMoveEvent(); // Send hover enter event. - MotionEvent hoverEnter = MotionEvent.obtain( - /* downTime= */ 0, - /* eventTime= */ 100, - /* action= */ MotionEvent.ACTION_HOVER_ENTER, - /* x= */ 30f, - /* y= */ 0f, - /* metaState= */ 0); - hoverEnter.setSource(InputDevice.SOURCE_MOUSE); - mController.onMotionEvent(hoverEnter, hoverEnter, /* policyFlags= */ 0); + injectFakeMouseMoveEvent(/* x= */ 30f, /* y= */ 0, MotionEvent.ACTION_HOVER_ENTER); // Verify there is no pending click. assertThat(mController.mClickScheduler.getIsActiveForTesting()).isFalse(); @@ -351,15 +343,7 @@ public class AutoclickControllerTest { injectFakeMouseActionHoverMoveEvent(); // Send hover move event. - MotionEvent hoverMove = MotionEvent.obtain( - /* downTime= */ 0, - /* eventTime= */ 100, - /* action= */ MotionEvent.ACTION_HOVER_MOVE, - /* x= */ 30f, - /* y= */ 0f, - /* metaState= */ 0); - hoverMove.setSource(InputDevice.SOURCE_MOUSE); - mController.onMotionEvent(hoverMove, hoverMove, /* policyFlags= */ 0); + injectFakeMouseMoveEvent(/* x= */ 30f, /* y= */ 0, MotionEvent.ACTION_HOVER_MOVE); // Verify there is a pending click. assertThat(mController.mClickScheduler.getIsActiveForTesting()).isTrue(); @@ -368,39 +352,15 @@ public class AutoclickControllerTest { @Test public void smallJitteryMovement_doesNotTriggerClick() { // Initial hover move to set an anchor point. - MotionEvent initialHoverMove = MotionEvent.obtain( - /* downTime= */ 0, - /* eventTime= */ 100, - /* action= */ MotionEvent.ACTION_HOVER_MOVE, - /* x= */ 30f, - /* y= */ 40f, - /* metaState= */ 0); - initialHoverMove.setSource(InputDevice.SOURCE_MOUSE); - mController.onMotionEvent(initialHoverMove, initialHoverMove, /* policyFlags= */ 0); + injectFakeMouseMoveEvent(/* x= */ 30f, /* y= */ 40f, MotionEvent.ACTION_HOVER_MOVE); // Get the initial scheduled click time. long initialScheduledTime = mController.mClickScheduler.getScheduledClickTimeForTesting(); // Simulate small, jittery movements (all within the default slop). - MotionEvent jitteryMove1 = MotionEvent.obtain( - /* downTime= */ 0, - /* eventTime= */ 150, - /* action= */ MotionEvent.ACTION_HOVER_MOVE, - /* x= */ 31f, // Small change in x - /* y= */ 41f, // Small change in y - /* metaState= */ 0); - jitteryMove1.setSource(InputDevice.SOURCE_MOUSE); - mController.onMotionEvent(jitteryMove1, jitteryMove1, /* policyFlags= */ 0); + injectFakeMouseMoveEvent(/* x= */ 31f, /* y= */ 41f, MotionEvent.ACTION_HOVER_MOVE); - MotionEvent jitteryMove2 = MotionEvent.obtain( - /* downTime= */ 0, - /* eventTime= */ 200, - /* action= */ MotionEvent.ACTION_HOVER_MOVE, - /* x= */ 30.5f, // Small change in x - /* y= */ 39.8f, // Small change in y - /* metaState= */ 0); - jitteryMove2.setSource(InputDevice.SOURCE_MOUSE); - mController.onMotionEvent(jitteryMove2, jitteryMove2, /* policyFlags= */ 0); + injectFakeMouseMoveEvent(/* x= */ 30.5f, /* y= */ 39.8f, MotionEvent.ACTION_HOVER_MOVE); // Verify that the scheduled click time has NOT changed. assertThat(mController.mClickScheduler.getScheduledClickTimeForTesting()) @@ -410,29 +370,13 @@ public class AutoclickControllerTest { @Test public void singleSignificantMovement_triggersClick() { // Initial hover move to set an anchor point. - MotionEvent initialHoverMove = MotionEvent.obtain( - /* downTime= */ 0, - /* eventTime= */ 100, - /* action= */ MotionEvent.ACTION_HOVER_MOVE, - /* x= */ 30f, - /* y= */ 40f, - /* metaState= */ 0); - initialHoverMove.setSource(InputDevice.SOURCE_MOUSE); - mController.onMotionEvent(initialHoverMove, initialHoverMove, /* policyFlags= */ 0); + injectFakeMouseMoveEvent(/* x= */ 30f, /* y= */ 40f, MotionEvent.ACTION_HOVER_MOVE); // Get the initial scheduled click time. long initialScheduledTime = mController.mClickScheduler.getScheduledClickTimeForTesting(); - // Simulate a single, significant movement (greater than the default slop). - MotionEvent significantMove = MotionEvent.obtain( - /* downTime= */ 0, - /* eventTime= */ 150, - /* action= */ MotionEvent.ACTION_HOVER_MOVE, - /* x= */ 60f, // Significant change in x (30f difference) - /* y= */ 70f, // Significant change in y (30f difference) - /* metaState= */ 0); - significantMove.setSource(InputDevice.SOURCE_MOUSE); - mController.onMotionEvent(significantMove, significantMove, /* policyFlags= */ 0); + // Significant change in x (30f difference) and y (30f difference) + injectFakeMouseMoveEvent(/* x= */ 60f, /* y= */ 70f, MotionEvent.ACTION_HOVER_MOVE); // Verify that the scheduled click time has changed (click was rescheduled). assertThat(mController.mClickScheduler.getScheduledClickTimeForTesting()) @@ -459,15 +403,7 @@ public class AutoclickControllerTest { // Move the mouse down, less than customSize radius so a click is not triggered. float moveDownY = customSize - 25; - MotionEvent hoverMove = MotionEvent.obtain( - /* downTime= */ 0, - /* eventTime= */ 150, - /* action= */ MotionEvent.ACTION_HOVER_MOVE, - /* x= */ 0f, - /* y= */ moveDownY, - /* metaState= */ 0); - hoverMove.setSource(InputDevice.SOURCE_MOUSE); - mController.onMotionEvent(hoverMove, hoverMove, /* policyFlags= */ 0); + injectFakeMouseMoveEvent(/* x= */ 0, /* y= */ moveDownY, MotionEvent.ACTION_HOVER_MOVE); assertThat(mController.mClickScheduler.getIsActiveForTesting()).isFalse(); } @@ -491,15 +427,7 @@ public class AutoclickControllerTest { // Move the mouse right, greater than customSize radius so a click is triggered. float moveRightX = customSize + 100; - MotionEvent hoverMove = MotionEvent.obtain( - /* downTime= */ 0, - /* eventTime= */ 200, - /* action= */ MotionEvent.ACTION_HOVER_MOVE, - /* x= */ moveRightX, - /* y= */ 0, - /* metaState= */ 0); - hoverMove.setSource(InputDevice.SOURCE_MOUSE); - mController.onMotionEvent(hoverMove, hoverMove, /* policyFlags= */ 0); + injectFakeMouseMoveEvent(/* x= */ moveRightX, /* y= */ 0, MotionEvent.ACTION_HOVER_MOVE); assertThat(mController.mClickScheduler.getIsActiveForTesting()).isTrue(); } @@ -522,15 +450,7 @@ public class AutoclickControllerTest { // Move the mouse down less than customSize radius but ignore custom movement is not enabled // so a click is triggered. float moveDownY = customSize - 100; - MotionEvent hoverMove = MotionEvent.obtain( - /* downTime= */ 0, - /* eventTime= */ 150, - /* action= */ MotionEvent.ACTION_HOVER_MOVE, - /* x= */ 0f, - /* y= */ moveDownY, - /* metaState= */ 0); - hoverMove.setSource(InputDevice.SOURCE_MOUSE); - mController.onMotionEvent(hoverMove, hoverMove, /* policyFlags= */ 0); + injectFakeMouseMoveEvent(/* x= */ 0, /* y= */ moveDownY, MotionEvent.ACTION_HOVER_MOVE); assertThat(mController.mClickScheduler.getIsActiveForTesting()).isTrue(); } @@ -554,15 +474,7 @@ public class AutoclickControllerTest { // After enabling ignore custom movement, move the mouse right, less than customSize radius // so a click won't be triggered. float moveRightX = customSize - 100; - MotionEvent hoverMove = MotionEvent.obtain( - /* downTime= */ 0, - /* eventTime= */ 200, - /* action= */ MotionEvent.ACTION_HOVER_MOVE, - /* x= */ moveRightX, - /* y= */ 0, - /* metaState= */ 0); - hoverMove.setSource(InputDevice.SOURCE_MOUSE); - mController.onMotionEvent(hoverMove, hoverMove, /* policyFlags= */ 0); + injectFakeMouseMoveEvent(/* x= */ moveRightX, /* y= */ 0, MotionEvent.ACTION_HOVER_MOVE); assertThat(mController.mClickScheduler.getIsActiveForTesting()).isFalse(); } @@ -600,15 +512,7 @@ public class AutoclickControllerTest { mController.mAutoclickTypePanel = mockAutoclickTypePanel; // Send hover move event. - MotionEvent hoverMove = MotionEvent.obtain( - /* downTime= */ 0, - /* eventTime= */ 100, - /* action= */ MotionEvent.ACTION_HOVER_MOVE, - /* x= */ 30f, - /* y= */ 0f, - /* metaState= */ 0); - hoverMove.setSource(InputDevice.SOURCE_MOUSE); - mController.onMotionEvent(hoverMove, hoverMove, /* policyFlags= */ 0); + injectFakeMouseMoveEvent(/* x= */ 30f, /* y= */ 0, MotionEvent.ACTION_HOVER_MOVE); // Verify there is not a pending click. assertThat(mController.mClickScheduler.getIsActiveForTesting()).isFalse(); @@ -624,7 +528,7 @@ public class AutoclickControllerTest { assertThat(mController.mClickScheduler.getScheduledClickTimeForTesting()).isEqualTo(-1); // Send move again to trigger click and verify there is now a pending click. - mController.onMotionEvent(hoverMove, hoverMove, /* policyFlags= */ 0); + injectFakeMouseMoveEvent(/* x= */ 30f, /* y= */ 0, MotionEvent.ACTION_HOVER_MOVE); assertThat(mController.mClickScheduler.getIsActiveForTesting()).isTrue(); assertThat(mController.mClickScheduler.getScheduledClickTimeForTesting()).isNotEqualTo(-1); } @@ -641,15 +545,7 @@ public class AutoclickControllerTest { mController.mAutoclickTypePanel = mockAutoclickTypePanel; // Send hover move event. - MotionEvent hoverMove = MotionEvent.obtain( - /* downTime= */ 0, - /* eventTime= */ 100, - /* action= */ MotionEvent.ACTION_HOVER_MOVE, - /* x= */ 30f, - /* y= */ 0f, - /* metaState= */ 0); - hoverMove.setSource(InputDevice.SOURCE_MOUSE); - mController.onMotionEvent(hoverMove, hoverMove, /* policyFlags= */ 0); + injectFakeMouseMoveEvent(/* x= */ 30f, /* y= */ 0, MotionEvent.ACTION_HOVER_MOVE); // Verify click is not triggered. assertThat(mController.mClickScheduler.getIsActiveForTesting()).isFalse(); @@ -668,15 +564,7 @@ public class AutoclickControllerTest { mController.mAutoclickTypePanel = mockAutoclickTypePanel; // Send hover move event. - MotionEvent hoverMove = MotionEvent.obtain( - /* downTime= */ 0, - /* eventTime= */ 100, - /* action= */ MotionEvent.ACTION_HOVER_MOVE, - /* x= */ 30f, - /* y= */ 0f, - /* metaState= */ 0); - hoverMove.setSource(InputDevice.SOURCE_MOUSE); - mController.onMotionEvent(hoverMove, hoverMove, /* policyFlags= */ 0); + injectFakeMouseMoveEvent(/* x= */ 30f, /* y= */ 0, MotionEvent.ACTION_HOVER_MOVE); // Verify click is triggered. assertThat(mController.mClickScheduler.getIsActiveForTesting()).isTrue(); @@ -695,15 +583,7 @@ public class AutoclickControllerTest { mController.mAutoclickTypePanel = mockAutoclickTypePanel; // Send hover move event. - MotionEvent hoverMove = MotionEvent.obtain( - /* downTime= */ 0, - /* eventTime= */ 100, - /* action= */ MotionEvent.ACTION_HOVER_MOVE, - /* x= */ 30f, - /* y= */ 0f, - /* metaState= */ 0); - hoverMove.setSource(InputDevice.SOURCE_MOUSE); - mController.onMotionEvent(hoverMove, hoverMove, /* policyFlags= */ 0); + injectFakeMouseMoveEvent(/* x= */ 30f, /* y= */ 0, MotionEvent.ACTION_HOVER_MOVE); // Verify click is triggered. assertThat(mController.mClickScheduler.getIsActiveForTesting()).isTrue(); @@ -781,15 +661,7 @@ public class AutoclickControllerTest { mController.mClickScheduler.updateDelay(0); // Send hover move event. - MotionEvent hoverMove = MotionEvent.obtain( - /* downTime= */ 0, - /* eventTime= */ 100, - /* action= */ MotionEvent.ACTION_HOVER_MOVE, - /* x= */ 30f, - /* y= */ 0f, - /* metaState= */ 0); - hoverMove.setSource(InputDevice.SOURCE_MOUSE); - mController.onMotionEvent(hoverMove, hoverMove, /* policyFlags= */ 0); + injectFakeMouseMoveEvent(/* x= */ 30f, /* y= */ 0, MotionEvent.ACTION_HOVER_MOVE); mTestableLooper.processAllMessages(); // Verify left click sent. @@ -814,15 +686,7 @@ public class AutoclickControllerTest { mController.mAutoclickTypePanel = mockAutoclickTypePanel; // Send hover move event. - MotionEvent hoverMove = MotionEvent.obtain( - /* downTime= */ 0, - /* eventTime= */ 100, - /* action= */ MotionEvent.ACTION_HOVER_MOVE, - /* x= */ 30f, - /* y= */ 0f, - /* metaState= */ 0); - hoverMove.setSource(InputDevice.SOURCE_MOUSE); - mController.onMotionEvent(hoverMove, hoverMove, /* policyFlags= */ 0); + injectFakeMouseMoveEvent(/* x= */ 30f, /* y= */ 0, MotionEvent.ACTION_HOVER_MOVE); mTestableLooper.processAllMessages(); // Verify right click sent. @@ -850,15 +714,7 @@ public class AutoclickControllerTest { mController.mAutoclickScrollPanel = mockScrollPanel; // First hover move event. - MotionEvent hoverMove1 = MotionEvent.obtain( - /* downTime= */ 0, - /* eventTime= */ 100, - /* action= */ MotionEvent.ACTION_HOVER_MOVE, - /* x= */ 30f, - /* y= */ 0f, - /* metaState= */ 0); - hoverMove1.setSource(InputDevice.SOURCE_MOUSE); - mController.onMotionEvent(hoverMove1, hoverMove1, /* policyFlags= */ 0); + injectFakeMouseMoveEvent(/* x= */ 30f, /* y= */ 0, MotionEvent.ACTION_HOVER_MOVE); mTestableLooper.processAllMessages(); // Verify scroll panel is shown once. @@ -866,15 +722,7 @@ public class AutoclickControllerTest { assertThat(motionEventCaptor.downEvent).isNull(); // Second significant hover move event to trigger another autoclick. - MotionEvent hoverMove2 = MotionEvent.obtain( - /* downTime= */ 0, - /* eventTime= */ 200, - /* action= */ MotionEvent.ACTION_HOVER_MOVE, - /* x= */ 100f, - /* y= */ 100f, - /* metaState= */ 0); - hoverMove2.setSource(InputDevice.SOURCE_MOUSE); - mController.onMotionEvent(hoverMove2, hoverMove2, /* policyFlags= */ 0); + injectFakeMouseMoveEvent(/* x= */ 100f, /* y= */ 100f, MotionEvent.ACTION_HOVER_MOVE); mTestableLooper.processAllMessages(); // Verify scroll panel is still only shown once (not called again). @@ -918,15 +766,7 @@ public class AutoclickControllerTest { mController.mAutoclickTypePanel = mockAutoclickTypePanel; // Send hover move event. - MotionEvent hoverMove = MotionEvent.obtain( - /* downTime= */ 0, - /* eventTime= */ 100, - /* action= */ MotionEvent.ACTION_HOVER_MOVE, - /* x= */ 30f, - /* y= */ 0f, - /* metaState= */ 0); - hoverMove.setSource(InputDevice.SOURCE_MOUSE); - mController.onMotionEvent(hoverMove, hoverMove, /* policyFlags= */ 0); + injectFakeMouseMoveEvent(/* x= */ 30f, /* y= */ 100f, MotionEvent.ACTION_HOVER_MOVE); mTestableLooper.processAllMessages(); // Verify left click is sent due to the mouse hovering the panel. @@ -1039,29 +879,6 @@ public class AutoclickControllerTest { assertThat(scrollCaptor.scrollEvent.getY()).isEqualTo(expectedY); } - private void injectFakeMouseActionHoverMoveEvent() { - MotionEvent event = getFakeMotionHoverMoveEvent(); - event.setSource(InputDevice.SOURCE_MOUSE); - mController.onMotionEvent(event, event, /* policyFlags= */ 0); - } - - private void injectFakeNonMouseActionHoverMoveEvent() { - MotionEvent event = getFakeMotionHoverMoveEvent(); - event.setSource(InputDevice.SOURCE_KEYBOARD); - mController.onMotionEvent(event, event, /* policyFlags= */ 0); - } - - private void injectFakeKeyEvent(int keyCode, int modifiers) { - KeyEvent keyEvent = new KeyEvent( - /* downTime= */ 0, - /* eventTime= */ 0, - /* action= */ KeyEvent.ACTION_DOWN, - /* code= */ keyCode, - /* repeat= */ 0, - /* metaState= */ modifiers); - mController.onKeyEvent(keyEvent, /* policyFlags= */ 0); - } - @Test @EnableFlags(com.android.server.accessibility.Flags.FLAG_ENABLE_AUTOCLICK_INDICATOR) public void sendClick_clickType_doubleclick_triggerClickTwice() { @@ -1079,15 +896,7 @@ public class AutoclickControllerTest { mController.mAutoclickTypePanel = mockAutoclickTypePanel; // Send hover move event. - MotionEvent hoverMove = MotionEvent.obtain( - /* downTime= */ 0, - /* eventTime= */ 100, - /* action= */ MotionEvent.ACTION_HOVER_MOVE, - /* x= */ 30f, - /* y= */ 0f, - /* metaState= */ 0); - hoverMove.setSource(InputDevice.SOURCE_MOUSE); - mController.onMotionEvent(hoverMove, hoverMove, /* policyFlags= */ 0); + injectFakeMouseMoveEvent(/* x= */ 30f, /* y= */ 100f, MotionEvent.ACTION_HOVER_MOVE); mTestableLooper.processAllMessages(); // Verify left click sent. @@ -1097,6 +906,45 @@ public class AutoclickControllerTest { assertThat(motionEventCaptor.eventCount).isEqualTo(2); } + /** + * ========================================================================= + * Helper Functions + * ========================================================================= + */ + + private void injectFakeMouseActionHoverMoveEvent() { + injectFakeMouseMoveEvent(0, 0, MotionEvent.ACTION_HOVER_MOVE); + } + + private void injectFakeMouseMoveEvent(float x, float y, int action) { + MotionEvent event = MotionEvent.obtain( + /* downTime= */ 0, + /* eventTime= */ 0, + /* action= */ action, + /* x= */ x, + /* y= */ y, + /* metaState= */ 0); + event.setSource(InputDevice.SOURCE_MOUSE); + mController.onMotionEvent(event, event, /* policyFlags= */ 0); + } + + private void injectFakeNonMouseActionHoverMoveEvent() { + MotionEvent event = getFakeMotionHoverMoveEvent(); + event.setSource(InputDevice.SOURCE_KEYBOARD); + mController.onMotionEvent(event, event, /* policyFlags= */ 0); + } + + private void injectFakeKeyEvent(int keyCode, int modifiers) { + KeyEvent keyEvent = new KeyEvent( + /* downTime= */ 0, + /* eventTime= */ 0, + /* action= */ KeyEvent.ACTION_DOWN, + /* code= */ keyCode, + /* repeat= */ 0, + /* metaState= */ modifiers); + mController.onKeyEvent(keyEvent, /* policyFlags= */ 0); + } + private MotionEvent getFakeMotionHoverMoveEvent() { return MotionEvent.obtain( /* downTime= */ 0, diff --git a/services/tests/servicestests/src/com/android/server/supervision/SupervisionServiceTest.kt b/services/tests/servicestests/src/com/android/server/supervision/SupervisionServiceTest.kt index c59f0a05c619..02b97442b218 100644 --- a/services/tests/servicestests/src/com/android/server/supervision/SupervisionServiceTest.kt +++ b/services/tests/servicestests/src/com/android/server/supervision/SupervisionServiceTest.kt @@ -29,9 +29,15 @@ import android.content.Intent import android.content.IntentFilter import android.content.pm.PackageManager import android.content.pm.UserInfo +import android.content.pm.UserInfo.FLAG_FOR_TESTING +import android.content.pm.UserInfo.FLAG_FULL +import android.content.pm.UserInfo.FLAG_MAIN +import android.content.pm.UserInfo.FLAG_SYSTEM import android.os.Handler import android.os.PersistableBundle import android.os.UserHandle +import android.os.UserHandle.MIN_SECONDARY_USER_ID +import android.os.UserHandle.USER_SYSTEM import android.platform.test.annotations.RequiresFlagsEnabled import android.platform.test.flag.junit.DeviceFlagsValueProvider import androidx.test.ext.junit.runners.AndroidJUnit4 @@ -49,6 +55,7 @@ import org.junit.runner.RunWith import org.mockito.Mock import org.mockito.junit.MockitoJUnit import org.mockito.junit.MockitoRule +import org.mockito.kotlin.any import org.mockito.kotlin.whenever /** @@ -289,6 +296,36 @@ class SupervisionServiceTest { assertThat(service.createConfirmSupervisionCredentialsIntent()).isNull() } + fun shouldAllowBypassingSupervisionRoleQualification_returnsTrue() { + assertThat(service.isSupervisionEnabledForUser(USER_ID)).isFalse() + assertThat(service.shouldAllowBypassingSupervisionRoleQualification()).isTrue() + + addDefaultAndTestUsers() + assertThat(service.shouldAllowBypassingSupervisionRoleQualification()).isTrue() + } + + @Test + fun shouldAllowBypassingSupervisionRoleQualification_returnsFalse() { + assertThat(service.isSupervisionEnabledForUser(USER_ID)).isFalse() + assertThat(service.shouldAllowBypassingSupervisionRoleQualification()).isTrue() + + addDefaultAndTestUsers() + assertThat(service.shouldAllowBypassingSupervisionRoleQualification()).isTrue() + + // Enabling supervision on any user will disallow bypassing + service.setSupervisionEnabledForUser(USER_ID, true) + assertThat(service.isSupervisionEnabledForUser(USER_ID)).isTrue() + assertThat(service.shouldAllowBypassingSupervisionRoleQualification()).isFalse() + + // Adding non-default users should also disallow bypassing + addDefaultAndFullUsers() + assertThat(service.shouldAllowBypassingSupervisionRoleQualification()).isFalse() + + // Turning off supervision with non-default users should still disallow bypassing + service.setSupervisionEnabledForUser(USER_ID, false) + assertThat(service.isSupervisionEnabledForUser(USER_ID)).isFalse() + } + private val systemSupervisionPackage: String get() = context.getResources().getString(R.string.config_systemSupervision) @@ -310,10 +347,31 @@ class SupervisionServiceTest { context.sendBroadcastAsUser(intent, UserHandle.of(userId)) } + private fun addDefaultAndTestUsers() { + val userInfos = userData.map { (userId, flags) -> + UserInfo(userId, "user" + userId, USER_ICON, flags, USER_TYPE) + } + whenever(mockUserManagerInternal.getUsers(any())).thenReturn(userInfos) + } + + private fun addDefaultAndFullUsers() { + val userInfos = userData.map { (userId, flags) -> + UserInfo(userId, "user" + userId, USER_ICON, flags, USER_TYPE) + } + UserInfo(USER_ID, "user" + USER_ID, USER_ICON, FLAG_FULL, USER_TYPE) + whenever(mockUserManagerInternal.getUsers(any())).thenReturn(userInfos) + } + private companion object { const val USER_ID = 100 const val APP_UID = USER_ID * UserHandle.PER_USER_RANGE const val SUPERVISING_USER_ID = 10 + const val USER_ICON = "user_icon" + const val USER_TYPE = "fake_user_type" + val userData: Map<Int, Int> = mapOf( + USER_SYSTEM to FLAG_SYSTEM, + MIN_SECONDARY_USER_ID to FLAG_MAIN, + (MIN_SECONDARY_USER_ID + 1) to (FLAG_FULL or FLAG_FOR_TESTING) + ) } } diff --git a/tests/Input/src/com/android/server/input/KeyboardBacklightControllerTests.kt b/tests/Input/src/com/android/server/input/KeyboardBacklightControllerTests.kt index cf09b54753b0..a0cf88809af4 100644 --- a/tests/Input/src/com/android/server/input/KeyboardBacklightControllerTests.kt +++ b/tests/Input/src/com/android/server/input/KeyboardBacklightControllerTests.kt @@ -26,7 +26,6 @@ import android.hardware.input.IKeyboardBacklightState import android.hardware.input.InputManager import android.hardware.lights.Light import android.os.SystemProperties -import android.os.UEventObserver import android.os.test.TestLooper import android.platform.test.annotations.Presubmit import android.util.TypedValue @@ -98,14 +97,12 @@ class KeyboardBacklightControllerTests { @get:Rule val inputManagerRule = MockInputManagerRule() @Mock private lateinit var native: NativeInputManagerService - @Mock private lateinit var uEventManager: UEventManager @Mock private lateinit var resources: Resources private lateinit var keyboardBacklightController: KeyboardBacklightController private lateinit var context: Context private lateinit var testLooper: TestLooper private var lightColorMap: HashMap<Int, Int> = HashMap() private var lastBacklightState: KeyboardBacklightState? = null - private var sysfsNodeChanges = 0 private var lastAnimationValues = IntArray(2) @Before @@ -126,7 +123,6 @@ class KeyboardBacklightControllerTests { lightColorMap.getOrDefault(args[1] as Int, 0) } lightColorMap.clear() - `when`(native.sysfsNodeChanged(any())).then { sysfsNodeChanges++ } } private fun setupConfig() { @@ -158,13 +154,7 @@ class KeyboardBacklightControllerTests { private fun setupController() { keyboardBacklightController = - KeyboardBacklightController( - context, - native, - testLooper.looper, - FakeAnimatorFactory(), - uEventManager, - ) + KeyboardBacklightController(context, native, testLooper.looper, FakeAnimatorFactory()) } @Test @@ -318,77 +308,6 @@ class KeyboardBacklightControllerTests { } @Test - fun testKeyboardBacklightSysfsNodeAdded_AfterInputDeviceAdded() { - setupController() - var counter = sysfsNodeChanges - keyboardBacklightController.onKeyboardBacklightUEvent( - UEventObserver.UEvent( - "ACTION=add\u0000SUBSYSTEM=leds\u0000DEVPATH=/xyz/leds/abc::no_backlight\u0000" - ) - ) - assertEquals( - "Should not reload sysfs node if UEvent path doesn't contain kbd_backlight", - counter, - sysfsNodeChanges, - ) - - keyboardBacklightController.onKeyboardBacklightUEvent( - UEventObserver.UEvent( - "ACTION=add\u0000SUBSYSTEM=power\u0000DEVPATH=/xyz/leds/abc::kbd_backlight\u0000" - ) - ) - assertEquals( - "Should not reload sysfs node if UEvent doesn't belong to subsystem LED", - counter, - sysfsNodeChanges, - ) - - keyboardBacklightController.onKeyboardBacklightUEvent( - UEventObserver.UEvent( - "ACTION=remove\u0000SUBSYSTEM=leds\u0000DEVPATH=/xyz/leds/abc::kbd_backlight\u0000" - ) - ) - assertEquals( - "Should not reload sysfs node if UEvent doesn't have ACTION(add)", - counter, - sysfsNodeChanges, - ) - - keyboardBacklightController.onKeyboardBacklightUEvent( - UEventObserver.UEvent( - "ACTION=add\u0000SUBSYSTEM=leds\u0000DEVPATH=/xyz/pqr/abc::kbd_backlight\u0000" - ) - ) - assertEquals( - "Should not reload sysfs node if UEvent path doesn't belong to leds/ directory", - counter, - sysfsNodeChanges, - ) - - keyboardBacklightController.onKeyboardBacklightUEvent( - UEventObserver.UEvent( - "ACTION=add\u0000SUBSYSTEM=leds\u0000DEVPATH=/xyz/leds/abc::kbd_backlight\u0000" - ) - ) - assertEquals( - "Should reload sysfs node if a valid Keyboard backlight LED UEvent occurs", - ++counter, - sysfsNodeChanges, - ) - - keyboardBacklightController.onKeyboardBacklightUEvent( - UEventObserver.UEvent( - "ACTION=add\u0000SUBSYSTEM=leds\u0000DEVPATH=/xyz/leds/abc:kbd_backlight:red\u0000" - ) - ) - assertEquals( - "Should reload sysfs node if a valid Keyboard backlight LED UEvent occurs", - ++counter, - sysfsNodeChanges, - ) - } - - @Test @UiThreadTest fun testKeyboardBacklightAnimation_onChangeLevels() { ExtendedMockito.doReturn("true").`when` { diff --git a/tests/Tracing/src/com/android/internal/protolog/ProcessedPerfettoProtoLogImplTest.java b/tests/Tracing/src/com/android/internal/protolog/ProcessedPerfettoProtoLogImplTest.java index 34fef25b187c..d30ec1699d03 100644 --- a/tests/Tracing/src/com/android/internal/protolog/ProcessedPerfettoProtoLogImplTest.java +++ b/tests/Tracing/src/com/android/internal/protolog/ProcessedPerfettoProtoLogImplTest.java @@ -552,7 +552,7 @@ public class ProcessedPerfettoProtoLogImplTest { } final ResultReader reader = new ResultReader(mWriter.write(), mTraceConfig); - assertThrows(java.net.ConnectException.class, reader::readProtoLogTrace); + assertThrows(java.net.SocketException.class, reader::readProtoLogTrace); } @Test |