/*
 * 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<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);
        }
    }
}
