/* * Copyright (C) 2007 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package android.app; import android.annotation.IntDef; import android.annotation.NonNull; import android.annotation.Nullable; import android.annotation.RequiresPermission; import android.annotation.SystemApi; import android.annotation.SystemService; import android.annotation.TestApi; import android.compat.annotation.UnsupportedAppUsage; import android.content.Context; import android.os.Binder; import android.os.IBinder; import android.os.RemoteException; import android.os.ServiceManager; import android.util.Pair; import android.util.Slog; import android.view.View; import com.android.internal.statusbar.IStatusBarService; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; /** * Allows an app to control the status bar. */ @SystemService(Context.STATUS_BAR_SERVICE) public class StatusBarManager { /** @hide */ public static final int DISABLE_EXPAND = View.STATUS_BAR_DISABLE_EXPAND; /** @hide */ public static final int DISABLE_NOTIFICATION_ICONS = View.STATUS_BAR_DISABLE_NOTIFICATION_ICONS; /** @hide */ public static final int DISABLE_NOTIFICATION_ALERTS = View.STATUS_BAR_DISABLE_NOTIFICATION_ALERTS; /** @hide */ @Deprecated @UnsupportedAppUsage public static final int DISABLE_NOTIFICATION_TICKER = View.STATUS_BAR_DISABLE_NOTIFICATION_TICKER; /** @hide */ public static final int DISABLE_SYSTEM_INFO = View.STATUS_BAR_DISABLE_SYSTEM_INFO; /** @hide */ public static final int DISABLE_HOME = View.STATUS_BAR_DISABLE_HOME; /** @hide */ public static final int DISABLE_RECENT = View.STATUS_BAR_DISABLE_RECENT; /** @hide */ public static final int DISABLE_BACK = View.STATUS_BAR_DISABLE_BACK; /** @hide */ public static final int DISABLE_CLOCK = View.STATUS_BAR_DISABLE_CLOCK; /** @hide */ public static final int DISABLE_SEARCH = View.STATUS_BAR_DISABLE_SEARCH; /** @hide */ @Deprecated public static final int DISABLE_NAVIGATION = View.STATUS_BAR_DISABLE_HOME | View.STATUS_BAR_DISABLE_RECENT; /** @hide */ public static final int DISABLE_NONE = 0x00000000; /** @hide */ public static final int DISABLE_MASK = DISABLE_EXPAND | DISABLE_NOTIFICATION_ICONS | DISABLE_NOTIFICATION_ALERTS | DISABLE_NOTIFICATION_TICKER | DISABLE_SYSTEM_INFO | DISABLE_RECENT | DISABLE_HOME | DISABLE_BACK | DISABLE_CLOCK | DISABLE_SEARCH; /** @hide */ @IntDef(flag = true, prefix = {"DISABLE_"}, value = { DISABLE_NONE, DISABLE_EXPAND, DISABLE_NOTIFICATION_ICONS, DISABLE_NOTIFICATION_ALERTS, DISABLE_NOTIFICATION_TICKER, DISABLE_SYSTEM_INFO, DISABLE_HOME, DISABLE_RECENT, DISABLE_BACK, DISABLE_CLOCK, DISABLE_SEARCH }) @Retention(RetentionPolicy.SOURCE) public @interface DisableFlags {} /** * Flag to disable quick settings. * * Setting this flag disables quick settings completely, but does not disable expanding the * notification shade. */ /** @hide */ public static final int DISABLE2_QUICK_SETTINGS = 1; /** @hide */ public static final int DISABLE2_SYSTEM_ICONS = 1 << 1; /** @hide */ public static final int DISABLE2_NOTIFICATION_SHADE = 1 << 2; /** @hide */ public static final int DISABLE2_GLOBAL_ACTIONS = 1 << 3; /** @hide */ public static final int DISABLE2_ROTATE_SUGGESTIONS = 1 << 4; /** @hide */ public static final int DISABLE2_NONE = 0x00000000; /** @hide */ public static final int DISABLE2_MASK = DISABLE2_QUICK_SETTINGS | DISABLE2_SYSTEM_ICONS | DISABLE2_NOTIFICATION_SHADE | DISABLE2_GLOBAL_ACTIONS | DISABLE2_ROTATE_SUGGESTIONS; /** @hide */ @IntDef(flag = true, prefix = { "DISABLE2_" }, value = { DISABLE2_NONE, DISABLE2_MASK, DISABLE2_QUICK_SETTINGS, DISABLE2_SYSTEM_ICONS, DISABLE2_NOTIFICATION_SHADE, DISABLE2_GLOBAL_ACTIONS, DISABLE2_ROTATE_SUGGESTIONS }) @Retention(RetentionPolicy.SOURCE) public @interface Disable2Flags {} /** * Default disable flags for setup * * @hide */ public static final int DEFAULT_SETUP_DISABLE_FLAGS = DISABLE_NOTIFICATION_ALERTS | DISABLE_HOME | DISABLE_EXPAND | DISABLE_RECENT | DISABLE_CLOCK | DISABLE_SEARCH; /** * Default disable2 flags for setup * * @hide */ public static final int DEFAULT_SETUP_DISABLE2_FLAGS = DISABLE2_ROTATE_SUGGESTIONS; /** * disable flags to be applied when the device is sim-locked. */ private static final int DEFAULT_SIM_LOCKED_DISABLED_FLAGS = DISABLE_EXPAND; /** @hide */ public static final int NAVIGATION_HINT_BACK_ALT = 1 << 0; /** @hide */ public static final int NAVIGATION_HINT_IME_SHOWN = 1 << 1; /** @hide */ public static final int WINDOW_STATUS_BAR = 1; /** @hide */ public static final int WINDOW_NAVIGATION_BAR = 2; /** @hide */ @IntDef(flag = true, prefix = { "WINDOW_" }, value = { WINDOW_STATUS_BAR, WINDOW_NAVIGATION_BAR }) @Retention(RetentionPolicy.SOURCE) public @interface WindowType {} /** @hide */ public static final int WINDOW_STATE_SHOWING = 0; /** @hide */ public static final int WINDOW_STATE_HIDING = 1; /** @hide */ public static final int WINDOW_STATE_HIDDEN = 2; /** @hide */ @IntDef(flag = true, prefix = { "WINDOW_STATE_" }, value = { WINDOW_STATE_SHOWING, WINDOW_STATE_HIDING, WINDOW_STATE_HIDDEN }) @Retention(RetentionPolicy.SOURCE) public @interface WindowVisibleState {} /** @hide */ public static final int CAMERA_LAUNCH_SOURCE_WIGGLE = 0; /** @hide */ public static final int CAMERA_LAUNCH_SOURCE_POWER_DOUBLE_TAP = 1; /** @hide */ public static final int CAMERA_LAUNCH_SOURCE_LIFT_TRIGGER = 2; @UnsupportedAppUsage private Context mContext; private IStatusBarService mService; @UnsupportedAppUsage private IBinder mToken = new Binder(); @UnsupportedAppUsage StatusBarManager(Context context) { mContext = context; } @UnsupportedAppUsage private synchronized IStatusBarService getService() { if (mService == null) { mService = IStatusBarService.Stub.asInterface( ServiceManager.getService(Context.STATUS_BAR_SERVICE)); if (mService == null) { Slog.w("StatusBarManager", "warning: no STATUS_BAR_SERVICE"); } } return mService; } /** * Disable some features in the status bar. Pass the bitwise-or of the DISABLE_* flags. * To re-enable everything, pass {@link #DISABLE_NONE}. * * @hide */ @UnsupportedAppUsage public void disable(int what) { try { final int userId = Binder.getCallingUserHandle().getIdentifier(); final IStatusBarService svc = getService(); if (svc != null) { svc.disableForUser(what, mToken, mContext.getPackageName(), userId); } } catch (RemoteException ex) { throw ex.rethrowFromSystemServer(); } } /** * Disable additional status bar features. Pass the bitwise-or of the DISABLE2_* flags. * To re-enable everything, pass {@link #DISABLE_NONE}. * * Warning: Only pass DISABLE2_* flags into this function, do not use DISABLE_* flags. * * @hide */ public void disable2(@Disable2Flags int what) { try { final int userId = Binder.getCallingUserHandle().getIdentifier(); final IStatusBarService svc = getService(); if (svc != null) { svc.disable2ForUser(what, mToken, mContext.getPackageName(), userId); } } catch (RemoteException ex) { throw ex.rethrowFromSystemServer(); } } /** * Expand the notifications panel. * * @hide */ @UnsupportedAppUsage @TestApi public void expandNotificationsPanel() { try { final IStatusBarService svc = getService(); if (svc != null) { svc.expandNotificationsPanel(); } } catch (RemoteException ex) { throw ex.rethrowFromSystemServer(); } } /** * Collapse the notifications and settings panels. * * @hide */ @UnsupportedAppUsage @TestApi public void collapsePanels() { try { final IStatusBarService svc = getService(); if (svc != null) { svc.collapsePanels(); } } catch (RemoteException ex) { throw ex.rethrowFromSystemServer(); } } /** * Expand the settings panel. * * @hide */ @UnsupportedAppUsage public void expandSettingsPanel() { expandSettingsPanel(null); } /** * Expand the settings panel and open a subPanel. If the subpanel is null or does not have a * corresponding tile, the QS panel is simply expanded * * @hide */ @UnsupportedAppUsage public void expandSettingsPanel(@Nullable String subPanel) { try { final IStatusBarService svc = getService(); if (svc != null) { svc.expandSettingsPanel(subPanel); } } catch (RemoteException ex) { throw ex.rethrowFromSystemServer(); } } /** @hide */ @UnsupportedAppUsage public void setIcon(String slot, int iconId, int iconLevel, String contentDescription) { try { final IStatusBarService svc = getService(); if (svc != null) { svc.setIcon(slot, mContext.getPackageName(), iconId, iconLevel, contentDescription); } } catch (RemoteException ex) { throw ex.rethrowFromSystemServer(); } } /** @hide */ @UnsupportedAppUsage public void removeIcon(String slot) { try { final IStatusBarService svc = getService(); if (svc != null) { svc.removeIcon(slot); } } catch (RemoteException ex) { throw ex.rethrowFromSystemServer(); } } /** @hide */ @UnsupportedAppUsage public void setIconVisibility(String slot, boolean visible) { try { final IStatusBarService svc = getService(); if (svc != null) { svc.setIconVisibility(slot, visible); } } catch (RemoteException ex) { throw ex.rethrowFromSystemServer(); } } /** * Enable or disable status bar elements (notifications, clock) which are inappropriate during * device setup. * * @param disabled whether to apply or remove the disabled flags * * @hide */ @SystemApi @TestApi @RequiresPermission(android.Manifest.permission.STATUS_BAR) public void setDisabledForSetup(boolean disabled) { try { final int userId = Binder.getCallingUserHandle().getIdentifier(); final IStatusBarService svc = getService(); if (svc != null) { svc.disableForUser(disabled ? DEFAULT_SETUP_DISABLE_FLAGS : DISABLE_NONE, mToken, mContext.getPackageName(), userId); svc.disable2ForUser(disabled ? DEFAULT_SETUP_DISABLE2_FLAGS : DISABLE2_NONE, mToken, mContext.getPackageName(), userId); } } catch (RemoteException ex) { throw ex.rethrowFromSystemServer(); } } /** * Enable or disable expansion of the status bar. When the device is SIM-locked, the status * bar should not be expandable. * * @param disabled If {@code true}, the status bar will be set to non-expandable. If * {@code false}, re-enables expansion of the status bar. * @hide */ @TestApi @RequiresPermission(android.Manifest.permission.STATUS_BAR) public void setDisabledForSimNetworkLock(boolean disabled) { try { final int userId = Binder.getCallingUserHandle().getIdentifier(); final IStatusBarService svc = getService(); if (svc != null) { svc.disableForUser(disabled ? DEFAULT_SIM_LOCKED_DISABLED_FLAGS : DISABLE_NONE, mToken, mContext.getPackageName(), userId); } } catch (RemoteException ex) { throw ex.rethrowFromSystemServer(); } } /** * Get this app's currently requested disabled components * * @return a new DisableInfo * * @hide */ @SystemApi @TestApi @RequiresPermission(android.Manifest.permission.STATUS_BAR) @NonNull public DisableInfo getDisableInfo() { try { final int userId = Binder.getCallingUserHandle().getIdentifier(); final IStatusBarService svc = getService(); int[] flags = new int[] {0, 0}; if (svc != null) { flags = svc.getDisableFlags(mToken, userId); } return new DisableInfo(flags[0], flags[1]); } catch (RemoteException ex) { throw ex.rethrowFromSystemServer(); } } /** @hide */ public static String windowStateToString(int state) { if (state == WINDOW_STATE_HIDING) return "WINDOW_STATE_HIDING"; if (state == WINDOW_STATE_HIDDEN) return "WINDOW_STATE_HIDDEN"; if (state == WINDOW_STATE_SHOWING) return "WINDOW_STATE_SHOWING"; return "WINDOW_STATE_UNKNOWN"; } /** * DisableInfo describes this app's requested state of the StatusBar with regards to which * components are enabled/disabled * * @hide */ @SystemApi @TestApi public static final class DisableInfo { private boolean mStatusBarExpansion; private boolean mNavigateHome; private boolean mNotificationPeeking; private boolean mRecents; private boolean mSearch; private boolean mSystemIcons; private boolean mClock; private boolean mNotificationIcons; /** @hide */ public DisableInfo(int flags1, int flags2) { mStatusBarExpansion = (flags1 & DISABLE_EXPAND) != 0; mNavigateHome = (flags1 & DISABLE_HOME) != 0; mNotificationPeeking = (flags1 & DISABLE_NOTIFICATION_ALERTS) != 0; mRecents = (flags1 & DISABLE_RECENT) != 0; mSearch = (flags1 & DISABLE_SEARCH) != 0; mSystemIcons = (flags1 & DISABLE_SYSTEM_INFO) != 0; mClock = (flags1 & DISABLE_CLOCK) != 0; mNotificationIcons = (flags1 & DISABLE_NOTIFICATION_ICONS) != 0; } /** @hide */ public DisableInfo() {} /** * @return {@code true} if expanding the notification shade is disabled * * @hide */ @SystemApi @TestApi public boolean isStatusBarExpansionDisabled() { return mStatusBarExpansion; } /** * @hide */ public void setStatusBarExpansionDisabled(boolean disabled) { mStatusBarExpansion = disabled; } /** * @return {@code true} if navigation home is disabled * * @hide */ @SystemApi @TestApi public boolean isNavigateToHomeDisabled() { return mNavigateHome; } /** * @hide */ public void setNagivationHomeDisabled(boolean disabled) { mNavigateHome = disabled; } /** * @return {@code true} if notification peeking (heads-up notification) is disabled * * @hide */ @SystemApi @TestApi public boolean isNotificationPeekingDisabled() { return mNotificationPeeking; } /** @hide */ public void setNotificationPeekingDisabled(boolean disabled) { mNotificationPeeking = disabled; } /** * @return {@code true} if mRecents/overview is disabled * * @hide */ @SystemApi @TestApi public boolean isRecentsDisabled() { return mRecents; } /** @hide */ public void setRecentsDisabled(boolean disabled) { mRecents = disabled; } /** * @return {@code true} if mSearch is disabled * * @hide */ @SystemApi @TestApi public boolean isSearchDisabled() { return mSearch; } /** @hide */ public void setSearchDisabled(boolean disabled) { mSearch = disabled; } /** * @return {@code true} if system icons are disabled * * @hide */ public boolean areSystemIconsDisabled() { return mSystemIcons; } /** * @hide */ public void setSystemIconsDisabled(boolean disabled) { mSystemIcons = disabled; } /** * @return {@code true} if the clock icon is disabled * * @hide */ public boolean isClockDisabled() { return mClock; } /** * @hide */ public void setClockDisabled(boolean disabled) { mClock = disabled; } /** * @return {@code true} if notification icons are disabled * * @hide */ public boolean areNotificationIconsDisabled() { return mNotificationIcons; } /** * @hide */ public void setNotificationIconsDisabled(boolean disabled) { mNotificationIcons = disabled; } /** * @return {@code true} if no components are disabled (default state) * * @hide */ @SystemApi @TestApi public boolean areAllComponentsEnabled() { return !mStatusBarExpansion && !mNavigateHome && !mNotificationPeeking && !mRecents && !mSearch && !mSystemIcons && !mClock && !mNotificationIcons; } /** @hide */ public void setEnableAll() { mStatusBarExpansion = false; mNavigateHome = false; mNotificationPeeking = false; mRecents = false; mSearch = false; mSystemIcons = false; mClock = false; mNotificationIcons = false; } /** * @return {@code true} if all status bar components are disabled * * @hide */ public boolean areAllComponentsDisabled() { return mStatusBarExpansion && mNavigateHome && mNotificationPeeking && mRecents && mSearch && mSystemIcons && mClock && mNotificationIcons; } /** @hide */ public void setDisableAll() { mStatusBarExpansion = true; mNavigateHome = true; mNotificationPeeking = true; mRecents = true; mSearch = true; mSystemIcons = true; mClock = true; mNotificationIcons = true; } @NonNull @Override public String toString() { StringBuilder sb = new StringBuilder(); sb.append("DisableInfo: "); sb.append(" mStatusBarExpansion=").append(mStatusBarExpansion ? "disabled" : "enabled"); sb.append(" mNavigateHome=").append(mNavigateHome ? "disabled" : "enabled"); sb.append(" mNotificationPeeking=") .append(mNotificationPeeking ? "disabled" : "enabled"); sb.append(" mRecents=").append(mRecents ? "disabled" : "enabled"); sb.append(" mSearch=").append(mSearch ? "disabled" : "enabled"); sb.append(" mSystemIcons=").append(mSystemIcons ? "disabled" : "enabled"); sb.append(" mClock=").append(mClock ? "disabled" : "enabled"); sb.append(" mNotificationIcons=").append(mNotificationIcons ? "disabled" : "enabled"); return sb.toString(); } /** * Convert a DisableInfo to equivalent flags * @return a pair of equivalent disable flags * * @hide */ public Pair toFlags() { int disable1 = DISABLE_NONE; int disable2 = DISABLE2_NONE; if (mStatusBarExpansion) disable1 |= DISABLE_EXPAND; if (mNavigateHome) disable1 |= DISABLE_HOME; if (mNotificationPeeking) disable1 |= DISABLE_NOTIFICATION_ALERTS; if (mRecents) disable1 |= DISABLE_RECENT; if (mSearch) disable1 |= DISABLE_SEARCH; if (mSystemIcons) disable1 |= DISABLE_SYSTEM_INFO; if (mClock) disable1 |= DISABLE_CLOCK; if (mNotificationIcons) disable1 |= DISABLE_NOTIFICATION_ICONS; return new Pair(disable1, disable2); } } }