1 /* 2 * Copyright (C) 2018 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 package android.hardware; 18 19 import android.annotation.NonNull; 20 import android.annotation.RequiresPermission; 21 import android.annotation.SystemService; 22 import android.content.Context; 23 import android.os.IBinder; 24 import android.os.RemoteException; 25 import android.os.ServiceManager; 26 import android.util.ArrayMap; 27 28 import com.android.internal.annotations.GuardedBy; 29 30 /** 31 * This class provides access to the sensor privacy services; sensor privacy allows the 32 * user to disable access to all sensors on the device. This class provides methods to query the 33 * current state of sensor privacy as well as to register / unregister for notification when 34 * the sensor privacy state changes. 35 * 36 * @hide 37 */ 38 @SystemService(Context.SENSOR_PRIVACY_SERVICE) 39 public final class SensorPrivacyManager { 40 41 /** 42 * A class implementing this interface can register with the {@link 43 * android.hardware.SensorPrivacyManager} to receive notification when the sensor privacy 44 * state changes. 45 */ 46 public interface OnSensorPrivacyChangedListener { 47 /** 48 * Callback invoked when the sensor privacy state changes. 49 * 50 * @param enabled true if sensor privacy is enabled, false otherwise. 51 */ onSensorPrivacyChanged(boolean enabled)52 void onSensorPrivacyChanged(boolean enabled); 53 } 54 55 private static final Object sInstanceLock = new Object(); 56 57 @GuardedBy("sInstanceLock") 58 private static SensorPrivacyManager sInstance; 59 60 @NonNull 61 private final Context mContext; 62 63 @NonNull 64 private final ISensorPrivacyManager mService; 65 66 @NonNull 67 private final ArrayMap<OnSensorPrivacyChangedListener, ISensorPrivacyListener> mListeners; 68 69 /** 70 * Private constructor to ensure only a single instance is created. 71 */ SensorPrivacyManager(Context context, ISensorPrivacyManager service)72 private SensorPrivacyManager(Context context, ISensorPrivacyManager service) { 73 mContext = context; 74 mService = service; 75 mListeners = new ArrayMap<>(); 76 } 77 78 /** 79 * Returns the single instance of the SensorPrivacyManager. 80 */ getInstance(Context context)81 public static SensorPrivacyManager getInstance(Context context) { 82 synchronized (sInstanceLock) { 83 if (sInstance == null) { 84 try { 85 IBinder b = ServiceManager.getServiceOrThrow(Context.SENSOR_PRIVACY_SERVICE); 86 ISensorPrivacyManager service = ISensorPrivacyManager.Stub.asInterface(b); 87 sInstance = new SensorPrivacyManager(context, service); 88 } catch (ServiceManager.ServiceNotFoundException e) { 89 throw new IllegalStateException(e); 90 } 91 } 92 return sInstance; 93 } 94 } 95 96 /** 97 * Sets sensor privacy to the specified state. 98 * 99 * @param enable the state to which sensor privacy should be set. 100 */ 101 @RequiresPermission(android.Manifest.permission.MANAGE_SENSOR_PRIVACY) setSensorPrivacy(boolean enable)102 public void setSensorPrivacy(boolean enable) { 103 try { 104 mService.setSensorPrivacy(enable); 105 } catch (RemoteException e) { 106 throw e.rethrowFromSystemServer(); 107 } 108 } 109 110 /** 111 * Registers a new listener to receive notification when the state of sensor privacy 112 * changes. 113 * 114 * @param listener the OnSensorPrivacyChangedListener to be notified when the state of sensor 115 * privacy changes. 116 */ addSensorPrivacyListener(final OnSensorPrivacyChangedListener listener)117 public void addSensorPrivacyListener(final OnSensorPrivacyChangedListener listener) { 118 synchronized (mListeners) { 119 ISensorPrivacyListener iListener = mListeners.get(listener); 120 if (iListener == null) { 121 iListener = new ISensorPrivacyListener.Stub() { 122 @Override 123 public void onSensorPrivacyChanged(boolean enabled) { 124 listener.onSensorPrivacyChanged(enabled); 125 } 126 }; 127 mListeners.put(listener, iListener); 128 } 129 130 try { 131 mService.addSensorPrivacyListener(iListener); 132 } catch (RemoteException e) { 133 throw e.rethrowFromSystemServer(); 134 } 135 } 136 } 137 138 /** 139 * Unregisters the specified listener from receiving notifications when the state of sensor 140 * privacy changes. 141 * 142 * @param listener the OnSensorPrivacyChangedListener to be unregistered from notifications when 143 * sensor privacy changes. 144 */ removeSensorPrivacyListener(OnSensorPrivacyChangedListener listener)145 public void removeSensorPrivacyListener(OnSensorPrivacyChangedListener listener) { 146 synchronized (mListeners) { 147 ISensorPrivacyListener iListener = mListeners.get(listener); 148 if (iListener != null) { 149 mListeners.remove(iListener); 150 try { 151 mService.removeSensorPrivacyListener(iListener); 152 } catch (RemoteException e) { 153 throw e.rethrowFromSystemServer(); 154 } 155 } 156 } 157 } 158 159 /** 160 * Returns whether sensor privacy is currently enabled. 161 * 162 * @return true if sensor privacy is currently enabled, false otherwise. 163 */ isSensorPrivacyEnabled()164 public boolean isSensorPrivacyEnabled() { 165 try { 166 return mService.isSensorPrivacyEnabled(); 167 } catch (RemoteException e) { 168 throw e.rethrowFromSystemServer(); 169 } 170 } 171 } 172