/*
 * Copyright (C) 2018 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.hardware;

import android.Manifest;
import android.annotation.IntDef;
import android.annotation.NonNull;
import android.annotation.RequiresPermission;
import android.annotation.SystemApi;
import android.annotation.SystemService;
import android.annotation.TestApi;
import android.annotation.UserIdInt;
import android.content.Context;
import android.os.Binder;
import android.os.IBinder;
import android.os.RemoteException;
import android.os.ServiceManager;
import android.os.UserHandle;
import android.service.SensorPrivacyIndividualEnabledSensorProto;
import android.service.SensorPrivacySensorProto;
import android.service.SensorPrivacyToggleSourceProto;
import android.util.ArrayMap;
import android.util.Log;
import android.util.Pair;

import com.android.internal.annotations.GuardedBy;

import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.util.Objects;
import java.util.concurrent.Executor;

/**
 * This class provides information about the microphone and camera toggles.
 */
@SystemService(Context.SENSOR_PRIVACY_SERVICE)
public final class SensorPrivacyManager {

    private static final String LOG_TAG = SensorPrivacyManager.class.getSimpleName();

    /**
     * Unique Id of this manager to identify to the service
     * @hide
     */
    private IBinder token = new Binder();

    /**
     * An extra containing a sensor
     * @hide
     */
    public static final String EXTRA_SENSOR = SensorPrivacyManager.class.getName()
            + ".extra.sensor";

    /**
     * An extra containing the notification id that triggered the intent
     * @hide
     */
    public static final String EXTRA_NOTIFICATION_ID = SensorPrivacyManager.class.getName()
            + ".extra.notification_id";

    /**
     * An extra indicating if all sensors are affected
     * @hide
     */
    public static final String EXTRA_ALL_SENSORS = SensorPrivacyManager.class.getName()
            + ".extra.all_sensors";

    /**
     * An extra containing the sensor type
     * @hide
     */
    public static final String EXTRA_TOGGLE_TYPE = SensorPrivacyManager.class.getName()
            + ".extra.toggle_type";

    /**
     * Sensor constants which are used in {@link SensorPrivacyManager}
     */
    public static class Sensors {

        private Sensors() {}

        /**
         * Constant for the microphone
         */
        public static final int MICROPHONE = SensorPrivacySensorProto.MICROPHONE;

        /**
         * Constant for the camera
         */
        public static final int CAMERA = SensorPrivacySensorProto.CAMERA;

        /**
         * Individual sensors not listed in {@link Sensors}
         *
         * @hide
         */
        @IntDef(value = {
                MICROPHONE,
                CAMERA
        })
        @Retention(RetentionPolicy.SOURCE)
        public @interface Sensor {}
    }

    /**
     * Source through which Privacy Sensor was toggled.
     * @hide
     */
    @TestApi
    public static class Sources {
        private Sources() {}

        /**
         * Constant for the Quick Setting Tile.
         */
        public static final int QS_TILE = SensorPrivacyToggleSourceProto.QS_TILE;

        /**
         * Constant for the Settings.
         */
        public static final int SETTINGS = SensorPrivacyToggleSourceProto.SETTINGS;

        /**
         * Constant for Dialog.
         */
        public static final int DIALOG = SensorPrivacyToggleSourceProto.DIALOG;

        /**
         * Constant for SHELL.
         */
        public static final int SHELL = SensorPrivacyToggleSourceProto.SHELL;

        /**
         * Constant for OTHER.
         */
        public static final int OTHER = SensorPrivacyToggleSourceProto.OTHER;

        /**
         * Constant for SAFETY_CENTER.
         */
        public static final int SAFETY_CENTER = SensorPrivacyToggleSourceProto.SAFETY_CENTER;

        /**
         * Source for toggling sensors
         *
         * @hide
         */
        @IntDef(value = {
                QS_TILE,
                SETTINGS,
                DIALOG,
                SHELL,
                OTHER,
                SAFETY_CENTER
        })
        @Retention(RetentionPolicy.SOURCE)
        public @interface Source {}

    }


    /**
     * Constant for software toggle.
     */
    public static final int TOGGLE_TYPE_SOFTWARE =
            SensorPrivacyIndividualEnabledSensorProto.SOFTWARE;

    /**
     * Constant for hardware toggle.
     */
    public static final int TOGGLE_TYPE_HARDWARE =
            SensorPrivacyIndividualEnabledSensorProto.HARDWARE;

    /**
     * Types of toggles which can exist for sensor privacy
     *
     * @hide
     */
    @IntDef(value = {
            TOGGLE_TYPE_SOFTWARE,
            TOGGLE_TYPE_HARDWARE
    })
    @Retention(RetentionPolicy.SOURCE)
    public @interface ToggleType {}

    /**
     * Types of state which can exist for the sensor privacy toggle
     * @hide
     */
    public static class StateTypes {
        private StateTypes() {}

        /**
         * Constant indicating privacy is enabled.
         */
        public static final int ENABLED = SensorPrivacyIndividualEnabledSensorProto.ENABLED;

        /**
         * Constant indicating privacy is disabled.
         */
        public static final int DISABLED = SensorPrivacyIndividualEnabledSensorProto.DISABLED;

        /**
         * Types of state which can exist for a sensor privacy toggle
         *
         * @hide
         */
        @IntDef(value = {
                ENABLED,
                DISABLED
        })
        @Retention(RetentionPolicy.SOURCE)
        public @interface StateType {}

    }

    /**
     * A class implementing this interface can register with the {@link
     * android.hardware.SensorPrivacyManager} to receive notification when the sensor privacy
     * state changes.
     *
     * @hide
     */
    @SystemApi
    public interface OnSensorPrivacyChangedListener {
        /**
         * Callback invoked when the sensor privacy state changes.
         *
         * @param params Parameters describing the new state
         */
        default void onSensorPrivacyChanged(@NonNull SensorPrivacyChangedParams params) {
            onSensorPrivacyChanged(params.mSensor, params.mEnabled);
        }

        /**
         * Callback invoked when the sensor privacy state changes.
         *
         * @param sensor the sensor whose state is changing
         * @param enabled true if sensor privacy is enabled, false otherwise.
         *
         * @deprecated Please use
         * {@link #onSensorPrivacyChanged(SensorPrivacyChangedParams)}
         */
        @Deprecated
        void onSensorPrivacyChanged(int sensor, boolean enabled);

        /**
         * A class containing information about what the sensor privacy state has changed to.
         */
        class SensorPrivacyChangedParams {

            private int mToggleType;
            private int mSensor;
            private boolean mEnabled;

            private SensorPrivacyChangedParams(int toggleType, int sensor, boolean enabled) {
                mToggleType = toggleType;
                mSensor = sensor;
                mEnabled = enabled;
            }

            public @ToggleType int getToggleType() {
                return mToggleType;
            }

            public @Sensors.Sensor int getSensor() {
                return mSensor;
            }

            public boolean isEnabled() {
                return mEnabled;
            }
        }
    }

    private static final Object sInstanceLock = new Object();

    private final Object mLock = new Object();

    @GuardedBy("sInstanceLock")
    private static SensorPrivacyManager sInstance;

    @NonNull
    private final Context mContext;

    @NonNull
    private final ISensorPrivacyManager mService;

    @GuardedBy("mLock")
    private final ArrayMap<Pair<Integer, Integer>, Boolean> mToggleSupportCache = new ArrayMap<>();

    @NonNull
    private final ArrayMap<OnAllSensorPrivacyChangedListener, ISensorPrivacyListener> mListeners;

    /** Registered listeners */
    @GuardedBy("mLock")
    @NonNull
    private final ArrayMap<OnSensorPrivacyChangedListener, Executor> mToggleListeners =
            new ArrayMap<>();

    /** Listeners registered using the deprecated APIs and which
     * OnSensorPrivacyChangedListener they're using. */
    @GuardedBy("mLock")
    @NonNull
    private final ArrayMap<Pair<Integer, OnSensorPrivacyChangedListener>,
            OnSensorPrivacyChangedListener> mLegacyToggleListeners = new ArrayMap<>();

    /** The singleton ISensorPrivacyListener for IPC which will be used to dispatch to local
     * listeners */
    @NonNull
    private final ISensorPrivacyListener mIToggleListener = new ISensorPrivacyListener.Stub() {
        @Override
        public void onSensorPrivacyChanged(int toggleType, int sensor, boolean enabled) {
            synchronized (mLock) {
                for (int i = 0; i < mToggleListeners.size(); i++) {
                    OnSensorPrivacyChangedListener listener = mToggleListeners.keyAt(i);
                    mToggleListeners.valueAt(i).execute(() -> listener
                            .onSensorPrivacyChanged(new OnSensorPrivacyChangedListener
                                    .SensorPrivacyChangedParams(toggleType, sensor, enabled)));
                }
            }
        }
    };

    /** Whether the singleton ISensorPrivacyListener has been registered */
    @GuardedBy("mLock")
    @NonNull
    private boolean mToggleListenerRegistered = false;

    private Boolean mRequiresAuthentication = null;

    /**
     * Private constructor to ensure only a single instance is created.
     */
    private SensorPrivacyManager(Context context, ISensorPrivacyManager service) {
        mContext = context;
        mService = service;
        mListeners = new ArrayMap<>();
    }

    /**
     * Returns the single instance of the SensorPrivacyManager.
     *
     * @hide
     */
    public static SensorPrivacyManager getInstance(Context context) {
        synchronized (sInstanceLock) {
            if (sInstance == null) {
                try {
                    IBinder b = ServiceManager.getServiceOrThrow(Context.SENSOR_PRIVACY_SERVICE);
                    ISensorPrivacyManager service = ISensorPrivacyManager.Stub.asInterface(b);
                    sInstance = new SensorPrivacyManager(context, service);
                } catch (ServiceManager.ServiceNotFoundException e) {
                    throw new IllegalStateException(e);
                }
            }
            return sInstance;
        }
    }

    /**
     * Returns the single instance of the SensorPrivacyManager.
     *
     * @hide
     */
    public static SensorPrivacyManager getInstance(Context context, ISensorPrivacyManager service) {
        synchronized (sInstanceLock) {
            sInstance = new SensorPrivacyManager(context, service);
            return sInstance;
        }
    }

    /**
     * Checks if the given toggle is supported on this device
     * @param sensor The sensor to check
     * @return whether the toggle for the sensor is supported on this device.
     */
    public boolean supportsSensorToggle(@Sensors.Sensor int sensor) {
        return supportsSensorToggle(TOGGLE_TYPE_SOFTWARE, sensor);
    }

    /**
     * Checks if the given toggle is supported on this device
     * @param sensor The sensor to check
     * @return whether the toggle for the sensor is supported on this device.
     *
     */
    public boolean supportsSensorToggle(@ToggleType int toggleType, @Sensors.Sensor int sensor) {
        try {
            Pair key = new Pair(toggleType, sensor);
            synchronized (mLock) {
                Boolean val = mToggleSupportCache.get(key);
                if (val == null) {
                    val = mService.supportsSensorToggle(toggleType, sensor);
                    mToggleSupportCache.put(key, val);
                }
                return val;
            }
        } catch (RemoteException e) {
            throw e.rethrowFromSystemServer();
        }
    }

    /**
     *
     * Registers a new listener to receive notification when the state of sensor privacy
     * changes.
     *
     * @param sensor the sensor to listen to changes to
     * @param listener the OnSensorPrivacyChangedListener to be notified when the state of sensor
     *                       privacy changes.
     *
     * @hide
     */
    @SystemApi
    @RequiresPermission(Manifest.permission.OBSERVE_SENSOR_PRIVACY)
    public void addSensorPrivacyListener(@Sensors.Sensor int sensor,
            @NonNull OnSensorPrivacyChangedListener listener) {
        addSensorPrivacyListener(sensor, mContext.getMainExecutor(), listener);
    }

    /**
     *
     * Registers a new listener to receive notification when the state of sensor privacy
     * changes.
     *
     * @param sensor the sensor to listen to changes to
     * @param userId the user's id
     * @param listener the OnSensorPrivacyChangedListener to be notified when the state of sensor
     *                 privacy changes.
     *
     * @hide
     */
    @RequiresPermission(Manifest.permission.OBSERVE_SENSOR_PRIVACY)
    public void addSensorPrivacyListener(@Sensors.Sensor int sensor, int userId,
            @NonNull OnSensorPrivacyChangedListener listener) {
        addSensorPrivacyListener(sensor, mContext.getMainExecutor(), listener);
    }

    /**
     *
     * Registers a new listener to receive notification when the state of sensor privacy
     * changes.
     *
     * @param sensor the sensor to listen to changes to
     * @param executor the executor to dispatch the callback on
     * @param listener the OnSensorPrivacyChangedListener to be notified when the state of sensor
     *                       privacy changes.
     *
     * @hide
     */
    @SystemApi
    @RequiresPermission(Manifest.permission.OBSERVE_SENSOR_PRIVACY)
    public void addSensorPrivacyListener(@Sensors.Sensor int sensor, @NonNull Executor executor,
            @NonNull OnSensorPrivacyChangedListener listener) {
        Pair<Integer, OnSensorPrivacyChangedListener> pair = new Pair(sensor, listener);
        OnSensorPrivacyChangedListener toggleListener = new OnSensorPrivacyChangedListener() {
            @Override
            public void onSensorPrivacyChanged(SensorPrivacyChangedParams params) {
                if (params.getSensor() == sensor) {
                    listener.onSensorPrivacyChanged(params);
                }
            }
            @Override
            public void onSensorPrivacyChanged(int sensor, boolean enabled) {
            }
        };

        synchronized (mLock) {
            mLegacyToggleListeners.put(pair, toggleListener);
            addSensorPrivacyListenerLocked(executor, toggleListener);
        }
    }

    /**
     *
     * Registers a new listener to receive notification when the state of sensor privacy
     * changes.
     *
     * @param listener the OnSensorPrivacyChangedListener to be notified when the state of
     *                 sensor privacy changes.
     *
     * @hide
     */
    @SystemApi
    @RequiresPermission(Manifest.permission.OBSERVE_SENSOR_PRIVACY)
    public void addSensorPrivacyListener(@NonNull OnSensorPrivacyChangedListener listener) {
        addSensorPrivacyListener(mContext.getMainExecutor(), listener);
    }

    /**
     *
     * Registers a new listener to receive notification when the state of sensor privacy
     * changes.
     *
     * @param executor the executor to dispatch the callback on
     * @param listener the OnSensorPrivacyChangedListener to be notified when the state of
     *                 sensor privacy changes.
     *
     * @hide
     */
    @SystemApi
    @RequiresPermission(Manifest.permission.OBSERVE_SENSOR_PRIVACY)
    public void addSensorPrivacyListener(@NonNull Executor executor,
            @NonNull OnSensorPrivacyChangedListener listener) {
        synchronized (mLock) {
            addSensorPrivacyListenerLocked(executor, listener);
        }
    }

    @GuardedBy("mLock")
    private void addSensorPrivacyListenerLocked(@NonNull Executor executor,
            @NonNull OnSensorPrivacyChangedListener listener) {
        if (!mToggleListenerRegistered) {
            try {
                mService.addToggleSensorPrivacyListener(mIToggleListener);
                mToggleListenerRegistered = true;
            } catch (RemoteException e) {
                e.rethrowFromSystemServer();
            }
        }
        if (mToggleListeners.containsKey(listener)) {
            throw new IllegalArgumentException("listener is already registered");
        }
        mToggleListeners.put(listener, executor);
    }

    /**
     * Unregisters the specified listener from receiving notifications when the state of any sensor
     * privacy changes.
     *
     * @param listener the OnSensorPrivacyChangedListener to be unregistered from notifications when
     *                 sensor privacy changes.
     *
     * @hide
     */
    @SystemApi
    @RequiresPermission(Manifest.permission.OBSERVE_SENSOR_PRIVACY)
    public void removeSensorPrivacyListener(@Sensors.Sensor int sensor,
            @NonNull OnSensorPrivacyChangedListener listener) {
        Pair<Integer, OnSensorPrivacyChangedListener> pair = new Pair(sensor, listener);
        synchronized (mLock) {
            OnSensorPrivacyChangedListener onToggleSensorPrivacyChangedListener =
                    mLegacyToggleListeners.remove(pair);
            if (onToggleSensorPrivacyChangedListener != null) {
                removeSensorPrivacyListenerLocked(onToggleSensorPrivacyChangedListener);
            }
        }
    }

    /**
     * Unregisters the specified listener from receiving notifications when the state of any sensor
     * privacy changes.
     *
     * @param listener the {@link OnSensorPrivacyChangedListener} to be unregistered from
     *                 notifications when sensor privacy changes.
     *
     * @hide
     */
    @SystemApi
    @RequiresPermission(Manifest.permission.OBSERVE_SENSOR_PRIVACY)
    public void removeSensorPrivacyListener(
            @NonNull OnSensorPrivacyChangedListener listener) {
        synchronized (mLock) {
            removeSensorPrivacyListenerLocked(listener);
        }
    }

    @GuardedBy("mLock")
    private void removeSensorPrivacyListenerLocked(
            @NonNull OnSensorPrivacyChangedListener listener) {
        mToggleListeners.remove(listener);
        if (mToggleListeners.size() == 0) {
            try {
                mService.removeToggleSensorPrivacyListener(mIToggleListener);
                mToggleListenerRegistered = false;
            } catch (RemoteException e) {
                e.rethrowFromSystemServer();
            }
        }
    }

    /**
     * Returns whether sensor privacy is currently enabled by software control for a specific
     * sensor.
     *
     * @return true if sensor privacy is currently enabled, false otherwise.
     *
     * @deprecated Prefer to use {@link #isSensorPrivacyEnabled(int, int)}
     *
     * @hide
     */
    @Deprecated
    @SystemApi
    @RequiresPermission(Manifest.permission.OBSERVE_SENSOR_PRIVACY)
    public boolean isSensorPrivacyEnabled(@Sensors.Sensor int sensor) {
        return isSensorPrivacyEnabled(TOGGLE_TYPE_SOFTWARE, sensor);
    }

    /**
     * Returns whether sensor privacy is currently enabled for a specific sensor.
     *
     * @return true if sensor privacy is currently enabled, false otherwise.
     *
     * @hide
     */
    @SystemApi
    @RequiresPermission(Manifest.permission.OBSERVE_SENSOR_PRIVACY)
    public boolean isSensorPrivacyEnabled(@ToggleType int toggleType,
            @Sensors.Sensor int sensor) {
        try {
            return mService.isToggleSensorPrivacyEnabled(toggleType, sensor);
        } catch (RemoteException e) {
            throw e.rethrowFromSystemServer();
        }
    }

    /**
     * Returns whether sensor privacy is currently enabled for a specific sensor.
     * Combines the state of the SW + HW toggles and returns true if either the
     * SOFTWARE or the HARDWARE toggles are enabled.
     *
     * @return true if sensor privacy is currently enabled, false otherwise.
     *
     * @hide
     */
    @SystemApi
    @RequiresPermission(Manifest.permission.OBSERVE_SENSOR_PRIVACY)
    public boolean areAnySensorPrivacyTogglesEnabled(@Sensors.Sensor int sensor) {
        try {
            return mService.isCombinedToggleSensorPrivacyEnabled(sensor);
        } catch (RemoteException e) {
            throw e.rethrowFromSystemServer();
        }
    }

    /**
     * Sets sensor privacy to the specified state for an individual sensor.
     *
     * @param sensor the sensor which to change the state for
     * @param enable the state to which sensor privacy should be set.
     *
     * @hide
     */
    @SystemApi
    @RequiresPermission(Manifest.permission.MANAGE_SENSOR_PRIVACY)
    public void setSensorPrivacy(@Sensors.Sensor int sensor,
            boolean enable) {
        setSensorPrivacy(resolveSourceFromCurrentContext(), sensor, enable,
                UserHandle.USER_CURRENT);
    }

    private @Sources.Source int resolveSourceFromCurrentContext() {
        String packageName = mContext.getOpPackageName();
        if (Objects.equals(packageName,
                mContext.getPackageManager().getPermissionControllerPackageName())) {
            return Sources.SAFETY_CENTER;
        }
        return Sources.OTHER;
    }

    /**
     * Sets sensor privacy to the specified state for an individual sensor.
     *
     * @param sensor the sensor which to change the state for
     * @param enable the state to which sensor privacy should be set.
     *
     * @hide
     */
    @TestApi
    @RequiresPermission(Manifest.permission.MANAGE_SENSOR_PRIVACY)
    public void setSensorPrivacy(@Sources.Source int source, @Sensors.Sensor int sensor,
            boolean enable) {
        setSensorPrivacy(source, sensor, enable, UserHandle.USER_CURRENT);
    }

    /**
     * Sets sensor privacy to the specified state for an individual sensor.
     *
     * @param sensor the sensor which to change the state for
     * @param enable the state to which sensor privacy should be set.
     * @param userId the user's id
     *
     * @hide
     */
    @RequiresPermission(Manifest.permission.MANAGE_SENSOR_PRIVACY)
    public void setSensorPrivacy(@Sources.Source int source, @Sensors.Sensor int sensor,
            boolean enable, @UserIdInt int userId) {
        try {
            mService.setToggleSensorPrivacy(userId, source, sensor, enable);
        } catch (RemoteException e) {
            throw e.rethrowFromSystemServer();
        }
    }

    /**
     * Sets sensor privacy to the specified state for an individual sensor for the profile group of
     * context's user.
     *
     * @param source the source using which the sensor is toggled.
     * @param sensor the sensor which to change the state for
     * @param enable the state to which sensor privacy should be set.
     *
     * @hide
     */
    @RequiresPermission(Manifest.permission.MANAGE_SENSOR_PRIVACY)
    public void setSensorPrivacyForProfileGroup(@Sources.Source int source,
            @Sensors.Sensor int sensor, boolean enable) {
        setSensorPrivacyForProfileGroup(source , sensor, enable, UserHandle.USER_CURRENT);
    }

    /**
     * Sets sensor privacy to the specified state for an individual sensor for the profile group of
     * context's user.
     *
     * @param source the source using which the sensor is toggled.
     * @param sensor the sensor which to change the state for
     * @param enable the state to which sensor privacy should be set.
     * @param userId the user's id
     *
     * @hide
     */
    @RequiresPermission(Manifest.permission.MANAGE_SENSOR_PRIVACY)
    public void setSensorPrivacyForProfileGroup(@Sources.Source int source,
            @Sensors.Sensor int sensor, boolean enable, @UserIdInt int userId) {
        try {
            mService.setToggleSensorPrivacyForProfileGroup(userId, source, sensor, enable);
        } catch (RemoteException e) {
            throw e.rethrowFromSystemServer();
        }
    }

    /**
     * Don't show dialogs to turn off sensor privacy for this package.
     *
     * @param suppress Whether to suppress or re-enable.
     *
     * @hide
     */
    @RequiresPermission(Manifest.permission.MANAGE_SENSOR_PRIVACY)
    public void suppressSensorPrivacyReminders(int sensor,
            boolean suppress) {
        suppressSensorPrivacyReminders(sensor, suppress, UserHandle.USER_CURRENT);
    }

    /**
     * Don't show dialogs to turn off sensor privacy for this package.
     *
     * @param suppress Whether to suppress or re-enable.
     * @param userId the user's id
     *
     * @hide
     */
    @RequiresPermission(Manifest.permission.MANAGE_SENSOR_PRIVACY)
    public void suppressSensorPrivacyReminders(int sensor,
            boolean suppress, @UserIdInt int userId) {
        try {
            mService.suppressToggleSensorPrivacyReminders(userId, sensor,
                    token, suppress);
        } catch (RemoteException e) {
            throw e.rethrowFromSystemServer();
        }
    }

    /**
     * @return whether the device is required to be unlocked to change software state.
     *
     * @hide
     */
    @RequiresPermission(Manifest.permission.OBSERVE_SENSOR_PRIVACY)
    public boolean requiresAuthentication() {
        if (mRequiresAuthentication == null) {
            try {
                mRequiresAuthentication = mService.requiresAuthentication();
            } catch (RemoteException e) {
                throw e.rethrowFromSystemServer();
            }
        }
        return mRequiresAuthentication;
    }

    /**
     * If sensor privacy for the provided sensor is enabled then this call will show the user the
     * dialog which is shown when an application attempts to use that sensor. If privacy isn't
     * enabled then this does nothing.
     *
     * This call can only be made by the system uid.
     *
     * @throws SecurityException when called by someone other than system uid.
     *
     * @hide
     */
    public void showSensorUseDialog(int sensor) {
        try {
            mService.showSensorUseDialog(sensor);
        } catch (RemoteException e) {
            Log.e(LOG_TAG, "Received exception while trying to show sensor use dialog", e);
        }
    }

    /**
     * A class implementing this interface can register with the {@link
     * android.hardware.SensorPrivacyManager} to receive notification when the all-sensor privacy
     * state changes.
     *
     * @hide
     */
    public interface OnAllSensorPrivacyChangedListener {
        /**
         * Callback invoked when the sensor privacy state changes.
         *
         * @param enabled true if sensor privacy is enabled, false otherwise.
         */
        void onAllSensorPrivacyChanged(boolean enabled);
    }

    /**
     * Sets all-sensor privacy to the specified state.
     *
     * @param enable the state to which sensor privacy should be set.
     *
     * @hide
     */
    @RequiresPermission(Manifest.permission.MANAGE_SENSOR_PRIVACY)
    public void setAllSensorPrivacy(boolean enable) {
        try {
            mService.setSensorPrivacy(enable);
        } catch (RemoteException e) {
            throw e.rethrowFromSystemServer();
        }
    }

    /**
     * Registers a new listener to receive notification when the state of all-sensor privacy
     * changes.
     *
     * @param listener the OnSensorPrivacyChangedListener to be notified when the state of
     *                 all-sensor privacy changes.
     *
     * @hide
     */
    @RequiresPermission(Manifest.permission.OBSERVE_SENSOR_PRIVACY)
    public void addAllSensorPrivacyListener(
            @NonNull final OnAllSensorPrivacyChangedListener listener) {
        synchronized (mListeners) {
            ISensorPrivacyListener iListener = mListeners.get(listener);
            if (iListener == null) {
                iListener = new ISensorPrivacyListener.Stub() {
                    @Override
                    public void onSensorPrivacyChanged(int toggleType, int sensor,
                            boolean enabled) {
                        listener.onAllSensorPrivacyChanged(enabled);
                    }
                };
                mListeners.put(listener, iListener);
            }

            try {
                mService.addSensorPrivacyListener(iListener);
            } catch (RemoteException e) {
                throw e.rethrowFromSystemServer();
            }
        }
    }

    /**
     * Unregisters the specified listener from receiving notifications when the state of all-sensor
     * privacy changes.
     *
     * @param listener the OnAllSensorPrivacyChangedListener to be unregistered from notifications
     *                 when all-sensor privacy changes.
     *
     * @hide
     */
    @RequiresPermission(Manifest.permission.OBSERVE_SENSOR_PRIVACY)
    public void removeAllSensorPrivacyListener(
            @NonNull OnAllSensorPrivacyChangedListener listener) {
        synchronized (mListeners) {
            ISensorPrivacyListener iListener = mListeners.get(listener);
            if (iListener != null) {
                mListeners.remove(iListener);
                try {
                    mService.removeSensorPrivacyListener(iListener);
                } catch (RemoteException e) {
                    throw e.rethrowFromSystemServer();
                }
            }
        }
    }

    /**
     * Returns whether all-sensor privacy is currently enabled.
     *
     * @return true if all-sensor privacy is currently enabled, false otherwise.
     *
     * @hide
     */
    @RequiresPermission(Manifest.permission.OBSERVE_SENSOR_PRIVACY)
    public boolean isAllSensorPrivacyEnabled() {
        try {
            return mService.isSensorPrivacyEnabled();
        } catch (RemoteException e) {
            throw e.rethrowFromSystemServer();
        }
    }

}
