From 8ffa58cdea9349fb5b802d83ba3e4d35b8df56e6 Mon Sep 17 00:00:00 2001 From: Pat Manning Date: Mon, 22 Nov 2021 14:20:27 +0000 Subject: [PATCH] Create API to set taskbar to kids mode. - Disables recents in taskbar. - Changes back and home icons and centers them in the taskbar. Test: manual Bug: 203749295 Change-Id: I9aa2a213728549509da4cf7f50abceb690ba31cf --- core/api/system-current.txt | 4 + core/java/android/app/StatusBarManager.java | 73 +++++++++++++++++++ core/java/android/provider/Settings.java | 8 ++ .../internal/statusbar/IStatusBarService.aidl | 16 ++++ .../android/providers/settings/secure.proto | 3 +- .../validators/SecureSettingsValidators.java | 1 + .../settings/SettingsProtoDumpUtil.java | 4 + .../statusbar/StatusBarManagerService.java | 49 +++++++++++++ .../tests/servicestests/AndroidManifest.xml | 1 + .../StatusBarManagerServiceTest.java | 25 +++++++ 10 files changed, 183 insertions(+), 1 deletion(-) diff --git a/core/api/system-current.txt b/core/api/system-current.txt index 6e1ab915b92c1..b278bcfb05cd0 100644 --- a/core/api/system-current.txt +++ b/core/api/system-current.txt @@ -853,7 +853,11 @@ package android.app { public class StatusBarManager { method @NonNull @RequiresPermission(android.Manifest.permission.STATUS_BAR) public android.app.StatusBarManager.DisableInfo getDisableInfo(); + method @RequiresPermission(android.Manifest.permission.STATUS_BAR) public int getNavBarModeOverride(); method @RequiresPermission(android.Manifest.permission.STATUS_BAR) public void setDisabledForSetup(boolean); + method @RequiresPermission(android.Manifest.permission.STATUS_BAR) public void setNavBarModeOverride(int); + field public static final int NAV_BAR_MODE_OVERRIDE_KIDS = 1; // 0x1 + field public static final int NAV_BAR_MODE_OVERRIDE_NONE = 0; // 0x0 } public static final class StatusBarManager.DisableInfo { diff --git a/core/java/android/app/StatusBarManager.java b/core/java/android/app/StatusBarManager.java index ae578f5e60ed0..64d3a9f08548e 100644 --- a/core/java/android/app/StatusBarManager.java +++ b/core/java/android/app/StatusBarManager.java @@ -282,6 +282,33 @@ public class StatusBarManager { @Retention(RetentionPolicy.SOURCE) public @interface RequestResult {} + /** + * Constant for {@link #setNavBarModeOverride(int)} indicating the default navbar mode. + * + * @hide + */ + @SystemApi + public static final int NAV_BAR_MODE_OVERRIDE_NONE = 0; + + /** + * Constant for {@link #setNavBarModeOverride(int)} indicating kids navbar mode. + * + *

When used, back and home icons will change drawables and layout, recents will be hidden, + * and the navbar will remain visible when apps are in immersive mode. + * + * @hide + */ + @SystemApi + public static final int NAV_BAR_MODE_OVERRIDE_KIDS = 1; + + /** @hide */ + @IntDef(prefix = {"NAV_BAR_MODE_OVERRIDE_"}, value = { + NAV_BAR_MODE_OVERRIDE_NONE, + NAV_BAR_MODE_OVERRIDE_KIDS + }) + @Retention(RetentionPolicy.SOURCE) + public @interface NavBarModeOverride {} + @UnsupportedAppUsage private Context mContext; private IStatusBarService mService; @@ -687,6 +714,52 @@ public class StatusBarManager { } } + /** + * Sets or removes the navigation bar mode override. + * + * @param navBarModeOverride the mode of the navigation bar override to be set. + * + * @hide + */ + @SystemApi + @RequiresPermission(android.Manifest.permission.STATUS_BAR) + public void setNavBarModeOverride(@NavBarModeOverride int navBarModeOverride) { + if (navBarModeOverride != NAV_BAR_MODE_OVERRIDE_NONE + && navBarModeOverride != NAV_BAR_MODE_OVERRIDE_KIDS) { + throw new UnsupportedOperationException( + "Supplied navBarModeOverride not supported: " + navBarModeOverride); + } + + try { + final IStatusBarService svc = getService(); + if (svc != null) { + svc.setNavBarModeOverride(navBarModeOverride); + } + } catch (RemoteException e) { + throw e.rethrowFromSystemServer(); + } + } + + /** + * Gets the navigation bar mode override. Returns default value if no override is set. + * + * @hide + */ + @SystemApi + @RequiresPermission(android.Manifest.permission.STATUS_BAR) + public @NavBarModeOverride int getNavBarModeOverride() { + int navBarModeOverride = NAV_BAR_MODE_OVERRIDE_NONE; + try { + final IStatusBarService svc = getService(); + if (svc != null) { + navBarModeOverride = svc.getNavBarModeOverride(); + } + } catch (RemoteException e) { + throw e.rethrowFromSystemServer(); + } + return navBarModeOverride; + } + /** @hide */ public static String windowStateToString(int state) { if (state == WINDOW_STATE_HIDING) return "WINDOW_STATE_HIDING"; diff --git a/core/java/android/provider/Settings.java b/core/java/android/provider/Settings.java index edacffca494ff..875223b239ddc 100644 --- a/core/java/android/provider/Settings.java +++ b/core/java/android/provider/Settings.java @@ -10060,6 +10060,14 @@ public final class Settings { public static final String THEME_CUSTOMIZATION_OVERLAY_PACKAGES = "theme_customization_overlay_packages"; + /** + * Indicates whether the device is in kids nav mode. + *

Type: int (0 for false, 1 for true) + * + * @hide + */ + public static final String NAV_BAR_KIDS_MODE = "nav_bar_kids_mode"; + /** * Navigation bar mode. * 0 = 3 button diff --git a/core/java/com/android/internal/statusbar/IStatusBarService.aidl b/core/java/com/android/internal/statusbar/IStatusBarService.aidl index 1db7426ba6cff..3c6b7ff60a030 100644 --- a/core/java/com/android/internal/statusbar/IStatusBarService.aidl +++ b/core/java/com/android/internal/statusbar/IStatusBarService.aidl @@ -162,4 +162,20 @@ interface IStatusBarService void requestAddTile(in ComponentName componentName, in CharSequence label, in Icon icon, int userId, in IAddTileResultCallback callback); void cancelRequestAddTile(in String packageName); + + /** + * Overrides the navigation bar mode. + * + * @param navBarModeOverride the mode of the navigation bar override to be set. + * + * @hide + */ + void setNavBarModeOverride(int navBarModeOverride); + + /** + * Gets the navigation bar mode override. + * + * @hide + */ + int getNavBarModeOverride(); } diff --git a/core/proto/android/providers/settings/secure.proto b/core/proto/android/providers/settings/secure.proto index ba4a5b0ce222f..60fb119fd6069 100644 --- a/core/proto/android/providers/settings/secure.proto +++ b/core/proto/android/providers/settings/secure.proto @@ -382,6 +382,7 @@ message SecureSettingsProto { optional SettingProto multi_press_timeout = 38 [ (android.privacy).dest = DEST_AUTOMATIC ]; + optional SettingProto nav_bar_kids_mode = 91 [ (android.privacy).dest = DEST_AUTOMATIC ]; optional SettingProto navigation_mode = 76 [ (android.privacy).dest = DEST_AUTOMATIC ]; message NfcPayment { @@ -664,5 +665,5 @@ message SecureSettingsProto { // Please insert fields in alphabetical order and group them into messages // if possible (to avoid reaching the method limit). - // Next tag = 91; + // Next tag = 92; } diff --git a/packages/SettingsProvider/src/android/provider/settings/validators/SecureSettingsValidators.java b/packages/SettingsProvider/src/android/provider/settings/validators/SecureSettingsValidators.java index dd1cb6b32d4f2..9b8c20d62d494 100644 --- a/packages/SettingsProvider/src/android/provider/settings/validators/SecureSettingsValidators.java +++ b/packages/SettingsProvider/src/android/provider/settings/validators/SecureSettingsValidators.java @@ -229,6 +229,7 @@ public class SecureSettingsValidators { VALIDATORS.put(Secure.SKIP_DIRECTION, BOOLEAN_VALIDATOR); VALIDATORS.put(Secure.SILENCE_GESTURE, BOOLEAN_VALIDATOR); VALIDATORS.put(Secure.THEME_CUSTOMIZATION_OVERLAY_PACKAGES, JSON_OBJECT_VALIDATOR); + VALIDATORS.put(Secure.NAV_BAR_KIDS_MODE, BOOLEAN_VALIDATOR); VALIDATORS.put( Secure.NAVIGATION_MODE, new DiscreteValueValidator(new String[] {"0", "1", "2"})); VALIDATORS.put(Secure.BACK_GESTURE_INSET_SCALE_LEFT, diff --git a/packages/SettingsProvider/src/com/android/providers/settings/SettingsProtoDumpUtil.java b/packages/SettingsProvider/src/com/android/providers/settings/SettingsProtoDumpUtil.java index 6072f68e36917..3564d3423265d 100644 --- a/packages/SettingsProvider/src/com/android/providers/settings/SettingsProtoDumpUtil.java +++ b/packages/SettingsProvider/src/com/android/providers/settings/SettingsProtoDumpUtil.java @@ -2247,6 +2247,10 @@ class SettingsProtoDumpUtil { Settings.Secure.MULTI_PRESS_TIMEOUT, SecureSettingsProto.MULTI_PRESS_TIMEOUT); + dumpSetting(s, p, + Settings.Secure.NAV_BAR_KIDS_MODE, + SecureSettingsProto.NAV_BAR_KIDS_MODE); + dumpSetting(s, p, Settings.Secure.NAVIGATION_MODE, SecureSettingsProto.NAVIGATION_MODE); diff --git a/services/core/java/com/android/server/statusbar/StatusBarManagerService.java b/services/core/java/com/android/server/statusbar/StatusBarManagerService.java index 4eae939f9e34c..54ec8845b24fb 100644 --- a/services/core/java/com/android/server/statusbar/StatusBarManagerService.java +++ b/services/core/java/com/android/server/statusbar/StatusBarManagerService.java @@ -18,6 +18,9 @@ package com.android.server.statusbar; import static android.app.StatusBarManager.DISABLE2_GLOBAL_ACTIONS; import static android.app.StatusBarManager.DISABLE2_NOTIFICATION_SHADE; +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 android.Manifest; @@ -59,6 +62,7 @@ import android.os.RemoteException; import android.os.ResultReceiver; import android.os.ShellCallback; import android.os.UserHandle; +import android.provider.Settings; import android.service.notification.NotificationStats; import android.service.quicksettings.TileService; import android.text.TextUtils; @@ -1846,6 +1850,51 @@ public class StatusBarManagerService extends IStatusBarService.Stub implements D return mContext.getResources().getStringArray(R.array.config_statusBarIcons); } + /** + * Sets or removes the navigation bar mode override. + * + * @param navBarModeOverride the mode of the navigation bar override to be set. + */ + public void setNavBarModeOverride(@NavBarModeOverride int navBarModeOverride) { + enforceStatusBar(); + if (navBarModeOverride != NAV_BAR_MODE_OVERRIDE_NONE + && navBarModeOverride != NAV_BAR_MODE_OVERRIDE_KIDS) { + throw new UnsupportedOperationException( + "Supplied navBarModeOverride not supported: " + navBarModeOverride); + } + + final int userId = mCurrentUserId; + final long userIdentity = Binder.clearCallingIdentity(); + try { + Settings.Secure.putIntForUser(mContext.getContentResolver(), + Settings.Secure.NAV_BAR_KIDS_MODE, navBarModeOverride, userId); + } finally { + Binder.restoreCallingIdentity(userIdentity); + } + } + + /** + * Gets the navigation bar mode override. Returns default value if no override is set. + * + * @hide + */ + public @NavBarModeOverride int getNavBarModeOverride() { + enforceStatusBar(); + + int navBarKidsMode = NAV_BAR_MODE_OVERRIDE_NONE; + final int userId = mCurrentUserId; + final long userIdentity = Binder.clearCallingIdentity(); + try { + navBarKidsMode = Settings.Secure.getIntForUser(mContext.getContentResolver(), + Settings.Secure.NAV_BAR_KIDS_MODE, userId); + } catch (Settings.SettingNotFoundException ex) { + return navBarKidsMode; + } finally { + Binder.restoreCallingIdentity(userIdentity); + } + return navBarKidsMode; + } + /** @hide */ public void passThroughShellCommand(String[] args, FileDescriptor fd) { enforceStatusBarOrShell(); diff --git a/services/tests/servicestests/AndroidManifest.xml b/services/tests/servicestests/AndroidManifest.xml index 80f2729051439..0f11e4fb87f95 100644 --- a/services/tests/servicestests/AndroidManifest.xml +++ b/services/tests/servicestests/AndroidManifest.xml @@ -57,6 +57,7 @@ + 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 c293b5e7c5930..d164d2a4f5818 100644 --- a/services/tests/servicestests/src/com/android/server/statusbar/StatusBarManagerServiceTest.java +++ b/services/tests/servicestests/src/com/android/server/statusbar/StatusBarManagerServiceTest.java @@ -21,6 +21,7 @@ import static android.app.ActivityManager.PROCESS_STATE_TOP; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertNotEquals; +import static org.junit.Assert.assertThrows; import static org.junit.Assert.fail; import static org.mockito.ArgumentMatchers.nullable; import static org.mockito.Mockito.any; @@ -575,6 +576,30 @@ public class StatusBarManagerServiceTest { } } + @Test + public void testSetNavBarModeOverride_setsOverrideModeKids() { + int navBarModeOverrideKids = StatusBarManager.NAV_BAR_MODE_OVERRIDE_KIDS; + mStatusBarManagerService.setNavBarModeOverride(navBarModeOverrideKids); + + assertEquals(navBarModeOverrideKids, mStatusBarManagerService.getNavBarModeOverride()); + } + + @Test + public void testSetNavBarModeOverride_setsOverrideModeNone() { + int navBarModeOverrideNone = StatusBarManager.NAV_BAR_MODE_OVERRIDE_NONE; + mStatusBarManagerService.setNavBarModeOverride(navBarModeOverrideNone); + + assertEquals(navBarModeOverrideNone, mStatusBarManagerService.getNavBarModeOverride()); + } + + @Test + public void testSetNavBarModeOverride_invalidInputThrowsError() { + int navBarModeOverrideInvalid = -1; + + assertThrows(UnsupportedOperationException.class, + () -> mStatusBarManagerService.setNavBarModeOverride(navBarModeOverrideInvalid)); + } + private void mockUidCheck() { mockUidCheck(TEST_PACKAGE); }