| /* |
| * 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; |
| |
| /** @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 |
| 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 |
| 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(); |
| } |
| } |
| |
| /** |
| * 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<Integer, Integer> 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<Integer, Integer>(disable1, disable2); |
| } |
| } |
| } |