diff options
10 files changed, 183 insertions, 1 deletions
diff --git a/core/api/system-current.txt b/core/api/system-current.txt index 6e1ab915b92c..b278bcfb05cd 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 ae578f5e60ed..64d3a9f08548 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. + * + * <p>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 edacffca494f..875223b239dd 100644 --- a/core/java/android/provider/Settings.java +++ b/core/java/android/provider/Settings.java @@ -10061,6 +10061,14 @@ public final class Settings { "theme_customization_overlay_packages"; /** + * Indicates whether the device is in kids nav mode. + * <p>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 * 1 = 2 button diff --git a/core/java/com/android/internal/statusbar/IStatusBarService.aidl b/core/java/com/android/internal/statusbar/IStatusBarService.aidl index 1db7426ba6cf..3c6b7ff60a03 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 ba4a5b0ce222..60fb119fd606 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 dd1cb6b32d4f..9b8c20d62d49 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 6072f68e3691..3564d3423265 100644 --- a/packages/SettingsProvider/src/com/android/providers/settings/SettingsProtoDumpUtil.java +++ b/packages/SettingsProvider/src/com/android/providers/settings/SettingsProtoDumpUtil.java @@ -2248,6 +2248,10 @@ class SettingsProtoDumpUtil { 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 4eae939f9e34..54ec8845b24f 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 80f272905143..0f11e4fb87f9 100644 --- a/services/tests/servicestests/AndroidManifest.xml +++ b/services/tests/servicestests/AndroidManifest.xml @@ -57,6 +57,7 @@ <uses-permission android:name="android.permission.FORCE_STOP_PACKAGES"/> <uses-permission android:name="android.permission.CHANGE_DEVICE_IDLE_TEMP_WHITELIST"/> <uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW"/> + <uses-permission android:name="android.permission.STATUS_BAR"/> <uses-permission android:name="android.permission.STATUS_BAR_SERVICE"/> <uses-permission android:name="android.permission.ACCESS_SURFACE_FLINGER"/> <uses-permission android:name="android.permission.READ_FRAME_BUFFER"/> 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 c293b5e7c593..d164d2a4f581 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); } |