From ac4276a9efaa04ddacc5945924170a9467e79593 Mon Sep 17 00:00:00 2001 From: Pat Manning Date: Fri, 14 Jan 2022 11:52:41 +0000 Subject: [PATCH] Enable 3-button navigation when kids mode is enabled. Test: StatusBarManagerServiceTest.java Bug: 195631691 Change-Id: If17623144159c86a5e63d6e574a4eb13ee9ac945 --- .../statusbar/StatusBarManagerService.java | 46 +++++++++++++++++++ .../StatusBarManagerServiceTest.java | 42 +++++++++++++++-- 2 files changed, 85 insertions(+), 3 deletions(-) diff --git a/services/core/java/com/android/server/statusbar/StatusBarManagerService.java b/services/core/java/com/android/server/statusbar/StatusBarManagerService.java index 17f5566a98643..0edd06acd7e9a 100644 --- a/services/core/java/com/android/server/statusbar/StatusBarManagerService.java +++ b/services/core/java/com/android/server/statusbar/StatusBarManagerService.java @@ -22,6 +22,7 @@ import static android.app.StatusBarManager.NAV_BAR_MODE_OVERRIDE_KIDS; import static android.app.StatusBarManager.NAV_BAR_MODE_OVERRIDE_NONE; import static android.app.StatusBarManager.NavBarModeOverride; import static android.view.Display.DEFAULT_DISPLAY; +import static android.view.WindowManagerPolicyConstants.NAV_BAR_MODE_3BUTTON_OVERLAY; import android.Manifest; import android.annotation.NonNull; @@ -38,6 +39,7 @@ import android.compat.annotation.EnabledSince; import android.content.ComponentName; import android.content.Context; import android.content.Intent; +import android.content.om.IOverlayManager; import android.content.pm.PackageManager; import android.content.pm.PackageManagerInternal; import android.content.pm.ResolveInfo; @@ -60,6 +62,7 @@ import android.os.PowerManager; import android.os.Process; import android.os.RemoteException; import android.os.ResultReceiver; +import android.os.ServiceManager; import android.os.ShellCallback; import android.os.UserHandle; import android.provider.Settings; @@ -79,6 +82,7 @@ import android.view.WindowInsetsController.Behavior; import com.android.internal.R; import com.android.internal.annotations.GuardedBy; +import com.android.internal.annotations.VisibleForTesting; import com.android.internal.inputmethod.SoftInputShowHideReason; import com.android.internal.os.TransferPipe; import com.android.internal.statusbar.IAddTileResultCallback; @@ -154,6 +158,8 @@ public class StatusBarManagerService extends IStatusBarService.Stub implements D private final ArrayMap mCurrentRequestAddTilePackages = new ArrayMap<>(); private static final long REQUEST_TIME_OUT = TimeUnit.MINUTES.toNanos(5); + private IOverlayManager mOverlayManager; + private class DeathRecipient implements IBinder.DeathRecipient { public void binderDied() { mBar.asBinder().unlinkToDeath(this,0); @@ -256,6 +262,18 @@ public class StatusBarManagerService extends IStatusBarService.Stub implements D mTileRequestTracker = new TileRequestTracker(mContext); } + private IOverlayManager getOverlayManager() { + // No need to synchronize; worst-case scenario it will be fetched twice. + if (mOverlayManager == null) { + mOverlayManager = IOverlayManager.Stub.asInterface( + ServiceManager.getService(Context.OVERLAY_SERVICE)); + if (mOverlayManager == null) { + Slog.w("StatusBarManager", "warning: no OVERLAY_SERVICE"); + } + } + return mOverlayManager; + } + @Override public void onDisplayAdded(int displayId) {} @@ -1296,6 +1314,11 @@ public class StatusBarManagerService extends IStatusBarService.Stub implements D }); } + @VisibleForTesting + void registerOverlayManager(IOverlayManager overlayManager) { + mOverlayManager = overlayManager; + } + /** * @param clearNotificationEffects whether to consider notifications as "shown" and stop * LED, vibration, and ringing @@ -1869,6 +1892,14 @@ public class StatusBarManagerService extends IStatusBarService.Stub implements D try { Settings.Secure.putIntForUser(mContext.getContentResolver(), Settings.Secure.NAV_BAR_KIDS_MODE, navBarModeOverride, userId); + + IOverlayManager overlayManager = getOverlayManager(); + if (overlayManager != null && navBarModeOverride == NAV_BAR_MODE_OVERRIDE_KIDS + && isPackageSupported(NAV_BAR_MODE_3BUTTON_OVERLAY)) { + overlayManager.setEnabledExclusiveInCategory(NAV_BAR_MODE_3BUTTON_OVERLAY, userId); + } + } catch (RemoteException e) { + throw e.rethrowFromSystemServer(); } finally { Binder.restoreCallingIdentity(userIdentity); } @@ -1896,6 +1927,21 @@ public class StatusBarManagerService extends IStatusBarService.Stub implements D return navBarKidsMode; } + private boolean isPackageSupported(String packageName) { + if (packageName == null) { + return false; + } + try { + return mContext.getPackageManager().getPackageInfo(packageName, + PackageManager.PackageInfoFlags.of(0)) != null; + } catch (PackageManager.NameNotFoundException ignored) { + if (SPEW) { + Slog.d(TAG, "Package not found: " + packageName); + } + } + return false; + } + /** @hide */ public void passThroughShellCommand(String[] args, FileDescriptor fd) { enforceStatusBarOrShell(); diff --git a/services/tests/servicestests/src/com/android/server/statusbar/StatusBarManagerServiceTest.java b/services/tests/servicestests/src/com/android/server/statusbar/StatusBarManagerServiceTest.java index d164d2a4f5818..0e98b5e79aa0e 100644 --- a/services/tests/servicestests/src/com/android/server/statusbar/StatusBarManagerServiceTest.java +++ b/services/tests/servicestests/src/com/android/server/statusbar/StatusBarManagerServiceTest.java @@ -29,6 +29,7 @@ import static org.mockito.Mockito.anyInt; import static org.mockito.Mockito.anyString; import static org.mockito.Mockito.argThat; import static org.mockito.Mockito.eq; +import static org.mockito.Mockito.never; import static org.mockito.Mockito.times; import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; @@ -38,6 +39,7 @@ import android.app.ActivityManagerInternal; import android.app.StatusBarManager; import android.content.ComponentName; import android.content.Intent; +import android.content.om.IOverlayManager; import android.content.pm.ApplicationInfo; import android.content.pm.PackageManager; import android.content.pm.PackageManagerInternal; @@ -96,6 +98,10 @@ public class StatusBarManagerServiceTest { private ApplicationInfo mApplicationInfo; @Mock private IStatusBar.Stub mMockStatusBar; + @Mock + private IOverlayManager mOverlayManager; + @Mock + private PackageManager mPackageManager; @Captor private ArgumentCaptor mAddTileResultCallbackCaptor; @@ -130,6 +136,7 @@ public class StatusBarManagerServiceTest { mStatusBarManagerService); mStatusBarManagerService.registerStatusBar(mMockStatusBar); + mStatusBarManagerService.registerOverlayManager(mOverlayManager); mIcon = Icon.createWithResource(mContext, android.R.drawable.btn_plus); } @@ -577,27 +584,56 @@ public class StatusBarManagerServiceTest { } @Test - public void testSetNavBarModeOverride_setsOverrideModeKids() { + public void testSetNavBarModeOverride_setsOverrideModeKids() throws RemoteException { int navBarModeOverrideKids = StatusBarManager.NAV_BAR_MODE_OVERRIDE_KIDS; + mStatusBarManagerService.setNavBarModeOverride(navBarModeOverrideKids); assertEquals(navBarModeOverrideKids, mStatusBarManagerService.getNavBarModeOverride()); + verify(mOverlayManager).setEnabledExclusiveInCategory(anyString(), anyInt()); } @Test - public void testSetNavBarModeOverride_setsOverrideModeNone() { + public void testSetNavBarModeOverride_setsOverrideModeNone() throws RemoteException { int navBarModeOverrideNone = StatusBarManager.NAV_BAR_MODE_OVERRIDE_NONE; + mStatusBarManagerService.setNavBarModeOverride(navBarModeOverrideNone); assertEquals(navBarModeOverrideNone, mStatusBarManagerService.getNavBarModeOverride()); + verify(mOverlayManager, never()).setEnabledExclusiveInCategory(anyString(), anyInt()); } @Test - public void testSetNavBarModeOverride_invalidInputThrowsError() { + public void testSetNavBarModeOverride_invalidInputThrowsError() throws RemoteException { int navBarModeOverrideInvalid = -1; assertThrows(UnsupportedOperationException.class, () -> mStatusBarManagerService.setNavBarModeOverride(navBarModeOverrideInvalid)); + verify(mOverlayManager, never()).setEnabledExclusiveInCategory(anyString(), anyInt()); + } + + @Test + public void testSetNavBarModeOverride_noOverlayManagerDoesNotEnable() throws RemoteException { + mOverlayManager = null; + int navBarModeOverrideKids = StatusBarManager.NAV_BAR_MODE_OVERRIDE_KIDS; + + mStatusBarManagerService.setNavBarModeOverride(navBarModeOverrideKids); + + assertEquals(navBarModeOverrideKids, mStatusBarManagerService.getNavBarModeOverride()); + verify(mOverlayManager, never()).setEnabledExclusiveInCategory(anyString(), anyInt()); + } + + @Test + public void testSetNavBarModeOverride_noPackageDoesNotEnable() throws Exception { + mContext.setMockPackageManager(mPackageManager); + when(mPackageManager.getPackageInfo(anyString(), + any(PackageManager.PackageInfoFlags.class))).thenReturn(null); + int navBarModeOverrideKids = StatusBarManager.NAV_BAR_MODE_OVERRIDE_KIDS; + + mStatusBarManagerService.setNavBarModeOverride(navBarModeOverrideKids); + + assertEquals(navBarModeOverrideKids, mStatusBarManagerService.getNavBarModeOverride()); + verify(mOverlayManager, never()).setEnabledExclusiveInCategory(anyString(), anyInt()); } private void mockUidCheck() {