Merge "Expose SensorPrivacy as SystemApi" into sc-dev

This commit is contained in:
Evan Severson
2021-02-25 18:29:43 +00:00
committed by Android (Google) Code Review
18 changed files with 248 additions and 102 deletions

View File

@@ -176,6 +176,7 @@ package android {
field public static final String OBSERVE_APP_USAGE = "android.permission.OBSERVE_APP_USAGE"; field public static final String OBSERVE_APP_USAGE = "android.permission.OBSERVE_APP_USAGE";
field public static final String OBSERVE_NETWORK_POLICY = "android.permission.OBSERVE_NETWORK_POLICY"; field public static final String OBSERVE_NETWORK_POLICY = "android.permission.OBSERVE_NETWORK_POLICY";
field public static final String OBSERVE_ROLE_HOLDERS = "android.permission.OBSERVE_ROLE_HOLDERS"; field public static final String OBSERVE_ROLE_HOLDERS = "android.permission.OBSERVE_ROLE_HOLDERS";
field public static final String OBSERVE_SENSOR_PRIVACY = "android.permission.OBSERVE_SENSOR_PRIVACY";
field public static final String OPEN_ACCESSIBILITY_DETAILS_SETTINGS = "android.permission.OPEN_ACCESSIBILITY_DETAILS_SETTINGS"; field public static final String OPEN_ACCESSIBILITY_DETAILS_SETTINGS = "android.permission.OPEN_ACCESSIBILITY_DETAILS_SETTINGS";
field public static final String OVERRIDE_WIFI_CONFIG = "android.permission.OVERRIDE_WIFI_CONFIG"; field public static final String OVERRIDE_WIFI_CONFIG = "android.permission.OVERRIDE_WIFI_CONFIG";
field public static final String PACKAGE_VERIFICATION_AGENT = "android.permission.PACKAGE_VERIFICATION_AGENT"; field public static final String PACKAGE_VERIFICATION_AGENT = "android.permission.PACKAGE_VERIFICATION_AGENT";
@@ -2550,10 +2551,12 @@ package android.content.pm {
field public static final String EXTRA_REQUEST_PERMISSIONS_NAMES = "android.content.pm.extra.REQUEST_PERMISSIONS_NAMES"; field public static final String EXTRA_REQUEST_PERMISSIONS_NAMES = "android.content.pm.extra.REQUEST_PERMISSIONS_NAMES";
field public static final String EXTRA_REQUEST_PERMISSIONS_RESULTS = "android.content.pm.extra.REQUEST_PERMISSIONS_RESULTS"; field public static final String EXTRA_REQUEST_PERMISSIONS_RESULTS = "android.content.pm.extra.REQUEST_PERMISSIONS_RESULTS";
field public static final String FEATURE_BROADCAST_RADIO = "android.hardware.broadcastradio"; field public static final String FEATURE_BROADCAST_RADIO = "android.hardware.broadcastradio";
field public static final String FEATURE_CAMERA_TOGGLE = "android.hardware.camera.toggle";
field public static final String FEATURE_CONTEXT_HUB = "android.hardware.context_hub"; field public static final String FEATURE_CONTEXT_HUB = "android.hardware.context_hub";
field public static final String FEATURE_CROSS_LAYER_BLUR = "android.software.cross_layer_blur"; field public static final String FEATURE_CROSS_LAYER_BLUR = "android.software.cross_layer_blur";
field @Deprecated public static final String FEATURE_INCREMENTAL_DELIVERY = "android.software.incremental_delivery"; field @Deprecated public static final String FEATURE_INCREMENTAL_DELIVERY = "android.software.incremental_delivery";
field public static final String FEATURE_INCREMENTAL_DELIVERY_VERSION = "android.software.incremental_delivery_version"; field public static final String FEATURE_INCREMENTAL_DELIVERY_VERSION = "android.software.incremental_delivery_version";
field public static final String FEATURE_MICROPHONE_TOGGLE = "android.hardware.microphone.toggle";
field public static final String FEATURE_REBOOT_ESCROW = "android.hardware.reboot_escrow"; field public static final String FEATURE_REBOOT_ESCROW = "android.hardware.reboot_escrow";
field public static final String FEATURE_TELEPHONY_CARRIERLOCK = "android.hardware.telephony.carrierlock"; field public static final String FEATURE_TELEPHONY_CARRIERLOCK = "android.hardware.telephony.carrierlock";
field public static final String FEATURE_TELEPHONY_IMS_SINGLE_REGISTRATION = "android.hardware.telephony.ims.singlereg"; field public static final String FEATURE_TELEPHONY_IMS_SINGLE_REGISTRATION = "android.hardware.telephony.ims.singlereg";
@@ -2908,6 +2911,22 @@ package android.hardware {
method public boolean injectSensorData(android.hardware.Sensor, float[], int, long); method public boolean injectSensorData(android.hardware.Sensor, float[], int, long);
} }
public final class SensorPrivacyManager {
method @RequiresPermission(android.Manifest.permission.OBSERVE_SENSOR_PRIVACY) public void addSensorPrivacyListener(int, @NonNull android.hardware.SensorPrivacyManager.OnSensorPrivacyChangedListener);
method @RequiresPermission(android.Manifest.permission.OBSERVE_SENSOR_PRIVACY) public void addSensorPrivacyListener(int, @NonNull java.util.concurrent.Executor, @NonNull android.hardware.SensorPrivacyManager.OnSensorPrivacyChangedListener);
method @RequiresPermission(android.Manifest.permission.OBSERVE_SENSOR_PRIVACY) public boolean isSensorPrivacyEnabled(int);
method @RequiresPermission(android.Manifest.permission.OBSERVE_SENSOR_PRIVACY) public void removeSensorPrivacyListener(@NonNull android.hardware.SensorPrivacyManager.OnSensorPrivacyChangedListener);
}
public static interface SensorPrivacyManager.OnSensorPrivacyChangedListener {
method public void onSensorPrivacyChanged(boolean);
}
public static class SensorPrivacyManager.Sensors {
field public static final int CAMERA = 2; // 0x2
field public static final int MICROPHONE = 1; // 0x1
}
} }
package android.hardware.biometrics { package android.hardware.biometrics {

View File

@@ -718,8 +718,10 @@ package android.content.pm {
method public void holdLock(android.os.IBinder, int); method public void holdLock(android.os.IBinder, int);
method @RequiresPermission(android.Manifest.permission.KEEP_UNINSTALLED_PACKAGES) public void setKeepUninstalledPackages(@NonNull java.util.List<java.lang.String>); method @RequiresPermission(android.Manifest.permission.KEEP_UNINSTALLED_PACKAGES) public void setKeepUninstalledPackages(@NonNull java.util.List<java.lang.String>);
field public static final String FEATURE_ADOPTABLE_STORAGE = "android.software.adoptable_storage"; field public static final String FEATURE_ADOPTABLE_STORAGE = "android.software.adoptable_storage";
field public static final String FEATURE_CAMERA_TOGGLE = "android.hardware.camera.toggle";
field public static final String FEATURE_FILE_BASED_ENCRYPTION = "android.software.file_based_encryption"; field public static final String FEATURE_FILE_BASED_ENCRYPTION = "android.software.file_based_encryption";
field public static final String FEATURE_HDMI_CEC = "android.hardware.hdmi.cec"; field public static final String FEATURE_HDMI_CEC = "android.hardware.hdmi.cec";
field public static final String FEATURE_MICROPHONE_TOGGLE = "android.hardware.microphone.toggle";
field public static final int FLAG_PERMISSION_REVOKE_WHEN_REQUESTED = 128; // 0x80 field public static final int FLAG_PERMISSION_REVOKE_WHEN_REQUESTED = 128; // 0x80
field public static final int MATCH_KNOWN_PACKAGES = 4202496; // 0x402000 field public static final int MATCH_KNOWN_PACKAGES = 4202496; // 0x402000
field public static final String SYSTEM_SHARED_LIBRARY_SERVICES = "android.ext.services"; field public static final String SYSTEM_SHARED_LIBRARY_SERVICES = "android.ext.services";
@@ -880,11 +882,21 @@ package android.graphics.fonts {
package android.hardware { package android.hardware {
public final class SensorPrivacyManager { public final class SensorPrivacyManager {
method public boolean isIndividualSensorPrivacyEnabled(int); method @RequiresPermission(android.Manifest.permission.OBSERVE_SENSOR_PRIVACY) public void addSensorPrivacyListener(int, @NonNull android.hardware.SensorPrivacyManager.OnSensorPrivacyChangedListener);
method @RequiresPermission(android.Manifest.permission.MANAGE_SENSOR_PRIVACY) public void setIndividualSensorPrivacy(int, boolean); method @RequiresPermission(android.Manifest.permission.OBSERVE_SENSOR_PRIVACY) public void addSensorPrivacyListener(int, @NonNull java.util.concurrent.Executor, @NonNull android.hardware.SensorPrivacyManager.OnSensorPrivacyChangedListener);
method @RequiresPermission(android.Manifest.permission.MANAGE_SENSOR_PRIVACY) public void setIndividualSensorPrivacyForProfileGroup(int, boolean); method @RequiresPermission(android.Manifest.permission.OBSERVE_SENSOR_PRIVACY) public boolean isSensorPrivacyEnabled(int);
field public static final int INDIVIDUAL_SENSOR_CAMERA = 2; // 0x2 method @RequiresPermission(android.Manifest.permission.OBSERVE_SENSOR_PRIVACY) public void removeSensorPrivacyListener(@NonNull android.hardware.SensorPrivacyManager.OnSensorPrivacyChangedListener);
field public static final int INDIVIDUAL_SENSOR_MICROPHONE = 1; // 0x1 method @RequiresPermission(android.Manifest.permission.MANAGE_SENSOR_PRIVACY) public void setSensorPrivacy(int, boolean);
method @RequiresPermission(android.Manifest.permission.MANAGE_SENSOR_PRIVACY) public void setSensorPrivacyForProfileGroup(int, boolean);
}
public static interface SensorPrivacyManager.OnSensorPrivacyChangedListener {
method public void onSensorPrivacyChanged(boolean);
}
public static class SensorPrivacyManager.Sensors {
field public static final int CAMERA = 2; // 0x2
field public static final int MICROPHONE = 1; // 0x1
} }
} }

View File

@@ -3623,11 +3623,26 @@ public abstract class PackageManager {
/** /**
* Feature for {@link #getSystemAvailableFeatures} and * Feature for {@link #getSystemAvailableFeatures} and
* {@link #hasSystemFeature}: The device supports a enabling/disabling sensor privacy for * {@link #hasSystemFeature}: The device supports a enabling/disabling sensor privacy for
* camera. When sensory privacy for the camera is enabled no camera data is send to clients, * microphone. When sensory privacy for the microphone is enabled no microphone data is sent to
* clients, e.g. all audio data is silent.
*
* @hide
*/
@SystemApi
@TestApi
@SdkConstant(SdkConstantType.FEATURE)
public static final String FEATURE_MICROPHONE_TOGGLE = "android.hardware.microphone.toggle";
/**
* Feature for {@link #getSystemAvailableFeatures} and
* {@link #hasSystemFeature}: The device supports a enabling/disabling sensor privacy for
* camera. When sensory privacy for the camera is enabled no camera data is sent to clients,
* e.g. the view finder in a camera app would appear blank. * e.g. the view finder in a camera app would appear blank.
* *
* @hide * @hide
*/ */
@SystemApi
@TestApi
@SdkConstant(SdkConstantType.FEATURE) @SdkConstant(SdkConstantType.FEATURE)
public static final String FEATURE_CAMERA_TOGGLE = "android.hardware.camera.toggle"; public static final String FEATURE_CAMERA_TOGGLE = "android.hardware.camera.toggle";

View File

@@ -19,6 +19,7 @@ package android.hardware;
import android.annotation.IntDef; import android.annotation.IntDef;
import android.annotation.NonNull; import android.annotation.NonNull;
import android.annotation.RequiresPermission; import android.annotation.RequiresPermission;
import android.annotation.SystemApi;
import android.annotation.SystemService; import android.annotation.SystemService;
import android.annotation.TestApi; import android.annotation.TestApi;
import android.content.Context; import android.content.Context;
@@ -33,6 +34,7 @@ import com.android.internal.annotations.GuardedBy;
import java.lang.annotation.Retention; import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy; import java.lang.annotation.RetentionPolicy;
import java.util.concurrent.Executor;
/** /**
* This class provides access to the sensor privacy services; sensor privacy allows the * This class provides access to the sensor privacy services; sensor privacy allows the
@@ -42,9 +44,21 @@ import java.lang.annotation.RetentionPolicy;
* *
* @hide * @hide
*/ */
@SystemApi
@TestApi @TestApi
@SystemService(Context.SENSOR_PRIVACY_SERVICE) @SystemService(Context.SENSOR_PRIVACY_SERVICE)
public final class SensorPrivacyManager { public final class SensorPrivacyManager {
/**
* @hide
*/
public static final boolean USE_MICROPHONE_TOGGLE = true;
/**
* @hide
*/
public static final boolean USE_CAMERA_TOGGLE = true;
/** /**
* Unique Id of this manager to identify to the service * Unique Id of this manager to identify to the service
* @hide * @hide
@@ -58,28 +72,39 @@ public final class SensorPrivacyManager {
public static final String EXTRA_SENSOR = SensorPrivacyManager.class.getName() public static final String EXTRA_SENSOR = SensorPrivacyManager.class.getName()
+ ".extra.sensor"; + ".extra.sensor";
/** Microphone
* @hide */
@TestApi
public static final int INDIVIDUAL_SENSOR_MICROPHONE =
SensorPrivacyIndividualEnabledSensorProto.MICROPHONE;
/** Camera
* @hide */
@TestApi
public static final int INDIVIDUAL_SENSOR_CAMERA =
SensorPrivacyIndividualEnabledSensorProto.CAMERA;
/** /**
* Individual sensors not listed in {@link Sensor} * Individual sensors not listed in {@link Sensors}
* @hide * @hide
*/ */
@IntDef(prefix = "INDIVIDUAL_SENSOR_", value = { @SystemApi
INDIVIDUAL_SENSOR_MICROPHONE, @TestApi
INDIVIDUAL_SENSOR_CAMERA public static class Sensors {
})
@Retention(RetentionPolicy.SOURCE) private Sensors() {}
public @interface IndividualSensor {}
/** Microphone
* @hide */
@SystemApi
@TestApi
public static final int MICROPHONE = SensorPrivacyIndividualEnabledSensorProto.MICROPHONE;
/** Camera
* @hide */
@SystemApi
@TestApi
public static final int CAMERA = SensorPrivacyIndividualEnabledSensorProto.CAMERA;
/**
* Individual sensors not listed in {@link Sensors}
*
* @hide
*/
@IntDef(value = {
MICROPHONE,
CAMERA
})
@Retention(RetentionPolicy.SOURCE)
public @interface Sensor {}
}
/** /**
* A class implementing this interface can register with the {@link * A class implementing this interface can register with the {@link
@@ -88,6 +113,8 @@ public final class SensorPrivacyManager {
* *
* @hide * @hide
*/ */
@SystemApi
@TestApi
public interface OnSensorPrivacyChangedListener { public interface OnSensorPrivacyChangedListener {
/** /**
* Callback invoked when the sensor privacy state changes. * Callback invoked when the sensor privacy state changes.
@@ -165,7 +192,8 @@ public final class SensorPrivacyManager {
* *
* @hide * @hide
*/ */
public void addSensorPrivacyListener(final OnSensorPrivacyChangedListener listener) { @RequiresPermission(android.Manifest.permission.OBSERVE_SENSOR_PRIVACY)
public void addSensorPrivacyListener(@NonNull final OnSensorPrivacyChangedListener listener) {
synchronized (mListeners) { synchronized (mListeners) {
ISensorPrivacyListener iListener = mListeners.get(listener); ISensorPrivacyListener iListener = mListeners.get(listener);
if (iListener == null) { if (iListener == null) {
@@ -196,15 +224,37 @@ public final class SensorPrivacyManager {
* *
* @hide * @hide
*/ */
public void addSensorPrivacyListener(@IndividualSensor int sensor, @SystemApi
final OnSensorPrivacyChangedListener listener) { @TestApi
@RequiresPermission(android.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 executor the executor to dispatch the callback on
* @param listener the OnSensorPrivacyChangedListener to be notified when the state of sensor
* privacy changes.
*
* @hide
*/
@SystemApi
@TestApi
@RequiresPermission(android.Manifest.permission.OBSERVE_SENSOR_PRIVACY)
public void addSensorPrivacyListener(@Sensors.Sensor int sensor, @NonNull Executor executor,
@NonNull OnSensorPrivacyChangedListener listener) {
synchronized (mListeners) { synchronized (mListeners) {
ISensorPrivacyListener iListener = mListeners.get(listener); ISensorPrivacyListener iListener = mListeners.get(listener);
if (iListener == null) { if (iListener == null) {
iListener = new ISensorPrivacyListener.Stub() { iListener = new ISensorPrivacyListener.Stub() {
@Override @Override
public void onSensorPrivacyChanged(boolean enabled) { public void onSensorPrivacyChanged(boolean enabled) {
listener.onSensorPrivacyChanged(enabled); executor.execute(() -> listener.onSensorPrivacyChanged(enabled));
} }
}; };
mListeners.put(listener, iListener); mListeners.put(listener, iListener);
@@ -228,7 +278,10 @@ public final class SensorPrivacyManager {
* *
* @hide * @hide
*/ */
public void removeSensorPrivacyListener(OnSensorPrivacyChangedListener listener) { @SystemApi
@TestApi
@RequiresPermission(android.Manifest.permission.OBSERVE_SENSOR_PRIVACY)
public void removeSensorPrivacyListener(@NonNull OnSensorPrivacyChangedListener listener) {
synchronized (mListeners) { synchronized (mListeners) {
ISensorPrivacyListener iListener = mListeners.get(listener); ISensorPrivacyListener iListener = mListeners.get(listener);
if (iListener != null) { if (iListener != null) {
@@ -249,6 +302,7 @@ public final class SensorPrivacyManager {
* *
* @hide * @hide
*/ */
@RequiresPermission(android.Manifest.permission.OBSERVE_SENSOR_PRIVACY)
public boolean isSensorPrivacyEnabled() { public boolean isSensorPrivacyEnabled() {
try { try {
return mService.isSensorPrivacyEnabled(); return mService.isSensorPrivacyEnabled();
@@ -264,8 +318,10 @@ public final class SensorPrivacyManager {
* *
* @hide * @hide
*/ */
@SystemApi
@TestApi @TestApi
public boolean isIndividualSensorPrivacyEnabled(@IndividualSensor int sensor) { @RequiresPermission(android.Manifest.permission.OBSERVE_SENSOR_PRIVACY)
public boolean isSensorPrivacyEnabled(@Sensors.Sensor int sensor) {
try { try {
return mService.isIndividualSensorPrivacyEnabled(mContext.getUserId(), sensor); return mService.isIndividualSensorPrivacyEnabled(mContext.getUserId(), sensor);
} catch (RemoteException e) { } catch (RemoteException e) {
@@ -283,8 +339,7 @@ public final class SensorPrivacyManager {
*/ */
@TestApi @TestApi
@RequiresPermission(android.Manifest.permission.MANAGE_SENSOR_PRIVACY) @RequiresPermission(android.Manifest.permission.MANAGE_SENSOR_PRIVACY)
public void setIndividualSensorPrivacy(@IndividualSensor int sensor, public void setSensorPrivacy(@Sensors.Sensor int sensor, boolean enable) {
boolean enable) {
try { try {
mService.setIndividualSensorPrivacy(mContext.getUserId(), sensor, enable); mService.setIndividualSensorPrivacy(mContext.getUserId(), sensor, enable);
} catch (RemoteException e) { } catch (RemoteException e) {
@@ -303,7 +358,7 @@ public final class SensorPrivacyManager {
*/ */
@TestApi @TestApi
@RequiresPermission(android.Manifest.permission.MANAGE_SENSOR_PRIVACY) @RequiresPermission(android.Manifest.permission.MANAGE_SENSOR_PRIVACY)
public void setIndividualSensorPrivacyForProfileGroup(@IndividualSensor int sensor, public void setSensorPrivacyForProfileGroup(@Sensors.Sensor int sensor,
boolean enable) { boolean enable) {
try { try {
mService.setIndividualSensorPrivacyForProfileGroup(mContext.getUserId(), sensor, mService.setIndividualSensorPrivacyForProfileGroup(mContext.getUserId(), sensor,
@@ -321,7 +376,8 @@ public final class SensorPrivacyManager {
* *
* @hide * @hide
*/ */
public void suppressIndividualSensorPrivacyReminders(@NonNull String packageName, @RequiresPermission(android.Manifest.permission.MANAGE_SENSOR_PRIVACY)
public void suppressSensorPrivacyReminders(@NonNull String packageName,
boolean suppress) { boolean suppress) {
try { try {
mService.suppressIndividualSensorPrivacyReminders(mContext.getUserId(), packageName, mService.suppressIndividualSensorPrivacyReminders(mContext.getUserId(), packageName,

View File

@@ -24,6 +24,7 @@ import android.app.ActivityManager;
import android.content.ComponentName; import android.content.ComponentName;
import android.content.pm.FeatureInfo; import android.content.pm.FeatureInfo;
import android.content.pm.PackageManager; import android.content.pm.PackageManager;
import android.hardware.SensorPrivacyManager;
import android.os.Build; import android.os.Build;
import android.os.CarrierAssociatedAppEntry; import android.os.CarrierAssociatedAppEntry;
import android.os.Environment; import android.os.Environment;
@@ -1252,6 +1253,14 @@ public class SystemConfig {
addFeature(PackageManager.FEATURE_CROSS_LAYER_BLUR, 0); addFeature(PackageManager.FEATURE_CROSS_LAYER_BLUR, 0);
} }
if (SensorPrivacyManager.USE_MICROPHONE_TOGGLE) {
addFeature(PackageManager.FEATURE_MICROPHONE_TOGGLE, 0);
}
if (SensorPrivacyManager.USE_CAMERA_TOGGLE) {
addFeature(PackageManager.FEATURE_CAMERA_TOGGLE, 0);
}
for (String featureName : mUnavailableFeatures) { for (String featureName : mUnavailableFeatures) {
removeFeature(featureName); removeFeature(featureName);
} }

View File

@@ -5431,6 +5431,12 @@
@hide --> @hide -->
<permission android:name="android.permission.MANAGE_SENSOR_PRIVACY" <permission android:name="android.permission.MANAGE_SENSOR_PRIVACY"
android:protectionLevel="signature" /> android:protectionLevel="signature" />
<!-- @SystemApi Allows sensor privacy changes to be observed.
@hide -->
<permission android:name="android.permission.OBSERVE_SENSOR_PRIVACY"
android:protectionLevel="signature|installer" />
<!-- @SystemApi Permission that protects the {@link Intent#ACTION_REVIEW_ACCESSIBILITY_SERVICES} <!-- @SystemApi Permission that protects the {@link Intent#ACTION_REVIEW_ACCESSIBILITY_SERVICES}
intent. intent.
@hide --> @hide -->

View File

@@ -400,6 +400,7 @@
<!-- Permission required for CTS to test sensor privacy behavior --> <!-- Permission required for CTS to test sensor privacy behavior -->
<uses-permission android:name="android.permission.MANAGE_SENSOR_PRIVACY" /> <uses-permission android:name="android.permission.MANAGE_SENSOR_PRIVACY" />
<uses-permission android:name="android.permission.OBSERVE_SENSOR_PRIVACY" />
<!-- Permission needed for CTS test - CallLogTest --> <!-- Permission needed for CTS test - CallLogTest -->
<uses-permission android:name="com.android.voicemail.permission.READ_VOICEMAIL" /> <uses-permission android:name="com.android.voicemail.permission.READ_VOICEMAIL" />

View File

@@ -87,6 +87,7 @@
<uses-permission android:name="android.permission.MASTER_CLEAR" /> <uses-permission android:name="android.permission.MASTER_CLEAR" />
<uses-permission android:name="android.permission.VIBRATE" /> <uses-permission android:name="android.permission.VIBRATE" />
<uses-permission android:name="android.permission.MANAGE_SENSOR_PRIVACY" /> <uses-permission android:name="android.permission.MANAGE_SENSOR_PRIVACY" />
<uses-permission android:name="android.permission.OBSERVE_SENSOR_PRIVACY" />
<!-- ActivityManager --> <!-- ActivityManager -->
<uses-permission android:name="android.permission.REAL_GET_TASKS" /> <uses-permission android:name="android.permission.REAL_GET_TASKS" />

View File

@@ -16,8 +16,8 @@
package com.android.systemui.appops; package com.android.systemui.appops;
import static android.hardware.SensorPrivacyManager.INDIVIDUAL_SENSOR_CAMERA; import static android.hardware.SensorPrivacyManager.Sensors.CAMERA;
import static android.hardware.SensorPrivacyManager.INDIVIDUAL_SENSOR_MICROPHONE; import static android.hardware.SensorPrivacyManager.Sensors.MICROPHONE;
import static android.media.AudioManager.ACTION_MICROPHONE_MUTE_CHANGED; import static android.media.AudioManager.ACTION_MICROPHONE_MUTE_CHANGED;
import android.Manifest; import android.Manifest;
@@ -137,8 +137,8 @@ public class AppOpsControllerImpl extends BroadcastReceiver implements AppOpsCon
mAudioManager = audioManager; mAudioManager = audioManager;
mSensorPrivacyController = sensorPrivacyController; mSensorPrivacyController = sensorPrivacyController;
mMicMuted = audioManager.isMicrophoneMute() mMicMuted = audioManager.isMicrophoneMute()
|| mSensorPrivacyController.isSensorBlocked(INDIVIDUAL_SENSOR_MICROPHONE); || mSensorPrivacyController.isSensorBlocked(MICROPHONE);
mCameraDisabled = mSensorPrivacyController.isSensorBlocked(INDIVIDUAL_SENSOR_CAMERA); mCameraDisabled = mSensorPrivacyController.isSensorBlocked(CAMERA);
mLocationManager = context.getSystemService(LocationManager.class); mLocationManager = context.getSystemService(LocationManager.class);
mPackageManager = context.getPackageManager(); mPackageManager = context.getPackageManager();
dumpManager.registerDumpable(TAG, this); dumpManager.registerDumpable(TAG, this);
@@ -159,8 +159,8 @@ public class AppOpsControllerImpl extends BroadcastReceiver implements AppOpsCon
mSensorPrivacyController.addCallback(this); mSensorPrivacyController.addCallback(this);
mMicMuted = mAudioManager.isMicrophoneMute() mMicMuted = mAudioManager.isMicrophoneMute()
|| mSensorPrivacyController.isSensorBlocked(INDIVIDUAL_SENSOR_MICROPHONE); || mSensorPrivacyController.isSensorBlocked(MICROPHONE);
mCameraDisabled = mSensorPrivacyController.isSensorBlocked(INDIVIDUAL_SENSOR_CAMERA); mCameraDisabled = mSensorPrivacyController.isSensorBlocked(CAMERA);
mBGHandler.post(() -> mAudioRecordingCallback.onRecordingConfigChanged( mBGHandler.post(() -> mAudioRecordingCallback.onRecordingConfigChanged(
mAudioManager.getActiveRecordingConfigurations())); mAudioManager.getActiveRecordingConfigurations()));
@@ -583,16 +583,16 @@ public class AppOpsControllerImpl extends BroadcastReceiver implements AppOpsCon
@Override @Override
public void onReceive(Context context, Intent intent) { public void onReceive(Context context, Intent intent) {
mMicMuted = mAudioManager.isMicrophoneMute() mMicMuted = mAudioManager.isMicrophoneMute()
|| mSensorPrivacyController.isSensorBlocked(INDIVIDUAL_SENSOR_MICROPHONE); || mSensorPrivacyController.isSensorBlocked(MICROPHONE);
updateSensorDisabledStatus(); updateSensorDisabledStatus();
} }
@Override @Override
public void onSensorBlockedChanged(int sensor, boolean blocked) { public void onSensorBlockedChanged(int sensor, boolean blocked) {
mBGHandler.post(() -> { mBGHandler.post(() -> {
if (sensor == INDIVIDUAL_SENSOR_CAMERA) { if (sensor == CAMERA) {
mCameraDisabled = blocked; mCameraDisabled = blocked;
} else if (sensor == INDIVIDUAL_SENSOR_MICROPHONE) { } else if (sensor == MICROPHONE) {
mMicMuted = mAudioManager.isMicrophoneMute() || blocked; mMicMuted = mAudioManager.isMicrophoneMute() || blocked;
} }
updateSensorDisabledStatus(); updateSensorDisabledStatus();

View File

@@ -16,10 +16,13 @@
package com.android.systemui.qs.tiles; package com.android.systemui.qs.tiles;
import static android.service.SensorPrivacyIndividualEnabledSensorProto.CAMERA; import static android.content.pm.PackageManager.FEATURE_CAMERA_TOGGLE;
import static android.hardware.SensorPrivacyManager.Sensors.CAMERA;
import static com.android.systemui.DejankUtils.whitelistIpcs; import static com.android.systemui.DejankUtils.whitelistIpcs;
import android.hardware.SensorPrivacyManager;
import android.hardware.SensorPrivacyManager.Sensors.Sensor;
import android.os.Handler; import android.os.Handler;
import android.os.Looper; import android.os.Looper;
import android.provider.DeviceConfig; import android.provider.DeviceConfig;
@@ -58,8 +61,8 @@ public class CameraToggleTile extends SensorPrivacyToggleTile {
@Override @Override
public boolean isAvailable() { public boolean isAvailable() {
return /*getHost().getContext().getPackageManager().hasSystemFeature(FEATURE_CAMERA_TOGGLE) return getHost().getContext().getPackageManager().hasSystemFeature(FEATURE_CAMERA_TOGGLE)
&& */whitelistIpcs(() -> DeviceConfig.getBoolean(DeviceConfig.NAMESPACE_PRIVACY, && whitelistIpcs(() -> DeviceConfig.getBoolean(DeviceConfig.NAMESPACE_PRIVACY,
"camera_toggle_enabled", "camera_toggle_enabled",
false)); false));
} }
@@ -75,7 +78,7 @@ public class CameraToggleTile extends SensorPrivacyToggleTile {
} }
@Override @Override
public int getSensorId() { public @Sensor int getSensorId() {
return CAMERA; return CAMERA;
} }
} }

View File

@@ -16,10 +16,13 @@
package com.android.systemui.qs.tiles; package com.android.systemui.qs.tiles;
import static android.service.SensorPrivacyIndividualEnabledSensorProto.MICROPHONE; import static android.content.pm.PackageManager.FEATURE_MICROPHONE_TOGGLE;
import static android.hardware.SensorPrivacyManager.Sensors.MICROPHONE;
import static com.android.systemui.DejankUtils.whitelistIpcs; import static com.android.systemui.DejankUtils.whitelistIpcs;
import android.hardware.SensorPrivacyManager;
import android.hardware.SensorPrivacyManager.Sensors.Sensor;
import android.os.Handler; import android.os.Handler;
import android.os.Looper; import android.os.Looper;
import android.provider.DeviceConfig; import android.provider.DeviceConfig;
@@ -58,7 +61,9 @@ public class MicrophoneToggleTile extends SensorPrivacyToggleTile {
@Override @Override
public boolean isAvailable() { public boolean isAvailable() {
return whitelistIpcs(() -> DeviceConfig.getBoolean(DeviceConfig.NAMESPACE_PRIVACY, return getHost().getContext().getPackageManager()
.hasSystemFeature(FEATURE_MICROPHONE_TOGGLE)
&& whitelistIpcs(() -> DeviceConfig.getBoolean(DeviceConfig.NAMESPACE_PRIVACY,
"mic_toggle_enabled", "mic_toggle_enabled",
false)); false));
} }
@@ -74,7 +79,7 @@ public class MicrophoneToggleTile extends SensorPrivacyToggleTile {
} }
@Override @Override
public int getSensorId() { public @Sensor int getSensorId() {
return MICROPHONE; return MICROPHONE;
} }
} }

View File

@@ -17,7 +17,7 @@
package com.android.systemui.qs.tiles; package com.android.systemui.qs.tiles;
import android.content.Intent; import android.content.Intent;
import android.hardware.SensorPrivacyManager.IndividualSensor; import android.hardware.SensorPrivacyManager.Sensors.Sensor;
import android.os.Handler; import android.os.Handler;
import android.os.Looper; import android.os.Looper;
import android.service.quicksettings.Tile; import android.service.quicksettings.Tile;
@@ -49,7 +49,7 @@ public abstract class SensorPrivacyToggleTile extends QSTileImpl<QSTile.BooleanS
/** /**
* @return Id of the sensor that will be toggled * @return Id of the sensor that will be toggled
*/ */
public abstract @IndividualSensor int getSensorId(); public abstract @Sensor int getSensorId();
/** /**
* @return icon for the QS tile * @return icon for the QS tile

View File

@@ -25,8 +25,8 @@ import android.content.pm.PackageManager
import android.content.res.Resources import android.content.res.Resources
import android.hardware.SensorPrivacyManager import android.hardware.SensorPrivacyManager
import android.hardware.SensorPrivacyManager.EXTRA_SENSOR import android.hardware.SensorPrivacyManager.EXTRA_SENSOR
import android.hardware.SensorPrivacyManager.INDIVIDUAL_SENSOR_CAMERA import android.hardware.SensorPrivacyManager.Sensors.CAMERA
import android.hardware.SensorPrivacyManager.INDIVIDUAL_SENSOR_MICROPHONE import android.hardware.SensorPrivacyManager.Sensors.MICROPHONE
import android.os.Bundle import android.os.Bundle
import android.os.Handler import android.os.Handler
import android.text.Html import android.text.Html
@@ -81,7 +81,7 @@ class SensorUseStartedActivity : AlertActivity(), DialogInterface.OnClickListene
dismiss() dismiss()
} }
} }
if (!sensorPrivacyManager.isIndividualSensorPrivacyEnabled(sensor)) { if (!sensorPrivacyManager.isSensorPrivacyEnabled(sensor)) {
finish() finish()
return return
} }
@@ -89,9 +89,9 @@ class SensorUseStartedActivity : AlertActivity(), DialogInterface.OnClickListene
mAlertParams.apply { mAlertParams.apply {
try { try {
mMessage = Html.fromHtml(getString(when (sensor) { mMessage = Html.fromHtml(getString(when (sensor) {
INDIVIDUAL_SENSOR_MICROPHONE -> MICROPHONE ->
R.string.sensor_privacy_start_use_mic_dialog_content R.string.sensor_privacy_start_use_mic_dialog_content
INDIVIDUAL_SENSOR_CAMERA -> CAMERA ->
R.string.sensor_privacy_start_use_camera_dialog_content R.string.sensor_privacy_start_use_camera_dialog_content
else -> Resources.ID_NULL else -> Resources.ID_NULL
}, packageManager.getApplicationInfo(sensorUsePackageName, 0) }, packageManager.getApplicationInfo(sensorUsePackageName, 0)
@@ -102,9 +102,9 @@ class SensorUseStartedActivity : AlertActivity(), DialogInterface.OnClickListene
} }
mIconId = when (sensor) { mIconId = when (sensor) {
INDIVIDUAL_SENSOR_MICROPHONE -> MICROPHONE ->
com.android.internal.R.drawable.perm_group_microphone com.android.internal.R.drawable.perm_group_microphone
INDIVIDUAL_SENSOR_CAMERA -> com.android.internal.R.drawable.perm_group_camera CAMERA -> com.android.internal.R.drawable.perm_group_camera
else -> Resources.ID_NULL else -> Resources.ID_NULL
} }
@@ -121,7 +121,7 @@ class SensorUseStartedActivity : AlertActivity(), DialogInterface.OnClickListene
override fun onStart() { override fun onStart() {
super.onStart() super.onStart()
sensorPrivacyManager.suppressIndividualSensorPrivacyReminders(sensorUsePackageName, true) sensorPrivacyManager.suppressSensorPrivacyReminders(sensorUsePackageName, true)
unsuppressImmediately = false unsuppressImmediately = false
} }
@@ -156,11 +156,11 @@ class SensorUseStartedActivity : AlertActivity(), DialogInterface.OnClickListene
if (unsuppressImmediately) { if (unsuppressImmediately) {
sensorPrivacyManager sensorPrivacyManager
.suppressIndividualSensorPrivacyReminders(sensorUsePackageName, false) .suppressSensorPrivacyReminders(sensorUsePackageName, false)
} else { } else {
Handler(mainLooper).postDelayed({ Handler(mainLooper).postDelayed({
sensorPrivacyManager sensorPrivacyManager
.suppressIndividualSensorPrivacyReminders(sensorUsePackageName, false) .suppressSensorPrivacyReminders(sensorUsePackageName, false)
}, SUPPRESS_REMINDERS_REMOVAL_DELAY_MILLIS) }, SUPPRESS_REMINDERS_REMOVAL_DELAY_MILLIS)
} }
} }
@@ -170,7 +170,7 @@ class SensorUseStartedActivity : AlertActivity(), DialogInterface.OnClickListene
} }
private fun disableSensorPrivacy() { private fun disableSensorPrivacy() {
sensorPrivacyManager.setIndividualSensorPrivacyForProfileGroup(sensor, false) sensorPrivacyManager.setSensorPrivacyForProfileGroup(sensor, false)
unsuppressImmediately = true unsuppressImmediately = true
setResult(RESULT_OK) setResult(RESULT_OK)
} }

View File

@@ -16,17 +16,17 @@
package com.android.systemui.statusbar.policy; package com.android.systemui.statusbar.policy;
import android.hardware.SensorPrivacyManager.IndividualSensor; import android.hardware.SensorPrivacyManager.Sensors.Sensor;
public interface IndividualSensorPrivacyController extends public interface IndividualSensorPrivacyController extends
CallbackController<IndividualSensorPrivacyController.Callback> { CallbackController<IndividualSensorPrivacyController.Callback> {
void init(); void init();
boolean isSensorBlocked(@IndividualSensor int sensor); boolean isSensorBlocked(@Sensor int sensor);
void setSensorBlocked(@IndividualSensor int sensor, boolean blocked); void setSensorBlocked(@Sensor int sensor, boolean blocked);
interface Callback { interface Callback {
void onSensorBlockedChanged(@IndividualSensor int sensor, boolean blocked); void onSensorBlockedChanged(@Sensor int sensor, boolean blocked);
} }
} }

View File

@@ -16,11 +16,11 @@
package com.android.systemui.statusbar.policy; package com.android.systemui.statusbar.policy;
import static android.hardware.SensorPrivacyManager.INDIVIDUAL_SENSOR_CAMERA; import static android.hardware.SensorPrivacyManager.Sensors.CAMERA;
import static android.hardware.SensorPrivacyManager.INDIVIDUAL_SENSOR_MICROPHONE; import static android.hardware.SensorPrivacyManager.Sensors.MICROPHONE;
import android.hardware.SensorPrivacyManager; import android.hardware.SensorPrivacyManager;
import android.hardware.SensorPrivacyManager.IndividualSensor; import android.hardware.SensorPrivacyManager.Sensors.Sensor;
import android.util.ArraySet; import android.util.ArraySet;
import android.util.SparseBooleanArray; import android.util.SparseBooleanArray;
@@ -30,8 +30,7 @@ import java.util.Set;
public class IndividualSensorPrivacyControllerImpl implements IndividualSensorPrivacyController { public class IndividualSensorPrivacyControllerImpl implements IndividualSensorPrivacyController {
private static final int[] SENSORS = new int[] {INDIVIDUAL_SENSOR_CAMERA, private static final int[] SENSORS = new int[] {CAMERA, MICROPHONE};
INDIVIDUAL_SENSOR_MICROPHONE};
private final @NonNull SensorPrivacyManager mSensorPrivacyManager; private final @NonNull SensorPrivacyManager mSensorPrivacyManager;
private final SparseBooleanArray mState = new SparseBooleanArray(); private final SparseBooleanArray mState = new SparseBooleanArray();
@@ -48,18 +47,18 @@ public class IndividualSensorPrivacyControllerImpl implements IndividualSensorPr
mSensorPrivacyManager.addSensorPrivacyListener(sensor, mSensorPrivacyManager.addSensorPrivacyListener(sensor,
(enabled) -> onSensorPrivacyChanged(sensor, enabled)); (enabled) -> onSensorPrivacyChanged(sensor, enabled));
mState.put(sensor, mSensorPrivacyManager.isIndividualSensorPrivacyEnabled(sensor)); mState.put(sensor, mSensorPrivacyManager.isSensorPrivacyEnabled(sensor));
} }
} }
@Override @Override
public boolean isSensorBlocked(@IndividualSensor int sensor) { public boolean isSensorBlocked(@Sensor int sensor) {
return mState.get(sensor, false); return mState.get(sensor, false);
} }
@Override @Override
public void setSensorBlocked(@IndividualSensor int sensor, boolean blocked) { public void setSensorBlocked(@Sensor int sensor, boolean blocked) {
mSensorPrivacyManager.setIndividualSensorPrivacyForProfileGroup(sensor, blocked); mSensorPrivacyManager.setSensorPrivacyForProfileGroup(sensor, blocked);
} }
@Override @Override
@@ -72,7 +71,7 @@ public class IndividualSensorPrivacyControllerImpl implements IndividualSensorPr
mCallbacks.remove(listener); mCallbacks.remove(listener);
} }
private void onSensorPrivacyChanged(@IndividualSensor int sensor, boolean blocked) { private void onSensorPrivacyChanged(@Sensor int sensor, boolean blocked) {
mState.put(sensor, blocked); mState.put(sensor, blocked);
for (Callback callback : mCallbacks) { for (Callback callback : mCallbacks) {

View File

@@ -16,8 +16,8 @@
package com.android.systemui.appops; package com.android.systemui.appops;
import static android.hardware.SensorPrivacyManager.INDIVIDUAL_SENSOR_CAMERA; import static android.hardware.SensorPrivacyManager.Sensors.CAMERA;
import static android.hardware.SensorPrivacyManager.INDIVIDUAL_SENSOR_MICROPHONE; import static android.hardware.SensorPrivacyManager.Sensors.MICROPHONE;
import static junit.framework.TestCase.assertFalse; import static junit.framework.TestCase.assertFalse;
@@ -125,9 +125,9 @@ public class AppOpsControllerTest extends SysuiTestCase {
when(mAudioManager.getActiveRecordingConfigurations()) when(mAudioManager.getActiveRecordingConfigurations())
.thenReturn(List.of(mPausedMockRecording)); .thenReturn(List.of(mPausedMockRecording));
when(mSensorPrivacyController.isSensorBlocked(INDIVIDUAL_SENSOR_CAMERA)) when(mSensorPrivacyController.isSensorBlocked(CAMERA))
.thenReturn(false); .thenReturn(false);
when(mSensorPrivacyController.isSensorBlocked(INDIVIDUAL_SENSOR_CAMERA)) when(mSensorPrivacyController.isSensorBlocked(CAMERA))
.thenReturn(false); .thenReturn(false);
mController = new AppOpsControllerImpl( mController = new AppOpsControllerImpl(
@@ -505,7 +505,7 @@ public class AppOpsControllerTest extends SysuiTestCase {
assertFalse(list.get(0).isDisabled()); assertFalse(list.get(0).isDisabled());
// Add a camera op, and disable the microphone. The camera op should be the only op returned // Add a camera op, and disable the microphone. The camera op should be the only op returned
mController.onSensorBlockedChanged(INDIVIDUAL_SENSOR_MICROPHONE, true); mController.onSensorBlockedChanged(MICROPHONE, true);
mController.onOpActiveChanged( mController.onOpActiveChanged(
AppOpsManager.OP_CAMERA, TEST_UID_OTHER, TEST_PACKAGE_NAME, true); AppOpsManager.OP_CAMERA, TEST_UID_OTHER, TEST_PACKAGE_NAME, true);
mTestableLooper.processAllMessages(); mTestableLooper.processAllMessages();
@@ -515,7 +515,7 @@ public class AppOpsControllerTest extends SysuiTestCase {
// Re enable the microphone, and verify the op returns // Re enable the microphone, and verify the op returns
mController.onSensorBlockedChanged(INDIVIDUAL_SENSOR_MICROPHONE, false); mController.onSensorBlockedChanged(MICROPHONE, false);
mTestableLooper.processAllMessages(); mTestableLooper.processAllMessages();
list = mController.getActiveAppOps(); list = mController.getActiveAppOps();
@@ -538,7 +538,7 @@ public class AppOpsControllerTest extends SysuiTestCase {
assertFalse(list.get(0).isDisabled()); assertFalse(list.get(0).isDisabled());
// Add an audio op, and disable the camera. The audio op should be the only op returned // Add an audio op, and disable the camera. The audio op should be the only op returned
mController.onSensorBlockedChanged(INDIVIDUAL_SENSOR_CAMERA, true); mController.onSensorBlockedChanged(CAMERA, true);
mController.onOpActiveChanged( mController.onOpActiveChanged(
AppOpsManager.OP_RECORD_AUDIO, TEST_UID_OTHER, TEST_PACKAGE_NAME, true); AppOpsManager.OP_RECORD_AUDIO, TEST_UID_OTHER, TEST_PACKAGE_NAME, true);
mTestableLooper.processAllMessages(); mTestableLooper.processAllMessages();
@@ -547,7 +547,7 @@ public class AppOpsControllerTest extends SysuiTestCase {
assertEquals(AppOpsManager.OP_RECORD_AUDIO, list.get(0).getCode()); assertEquals(AppOpsManager.OP_RECORD_AUDIO, list.get(0).getCode());
// Re enable the camera, and verify the op returns // Re enable the camera, and verify the op returns
mController.onSensorBlockedChanged(INDIVIDUAL_SENSOR_CAMERA, false); mController.onSensorBlockedChanged(CAMERA, false);
mTestableLooper.processAllMessages(); mTestableLooper.processAllMessages();
list = mController.getActiveAppOps(); list = mController.getActiveAppOps();

View File

@@ -25,9 +25,9 @@ import static android.app.AppOpsManager.OP_RECORD_AUDIO;
import static android.content.Intent.EXTRA_PACKAGE_NAME; import static android.content.Intent.EXTRA_PACKAGE_NAME;
import static android.content.pm.PackageManager.PERMISSION_GRANTED; import static android.content.pm.PackageManager.PERMISSION_GRANTED;
import static android.hardware.SensorPrivacyManager.EXTRA_SENSOR; import static android.hardware.SensorPrivacyManager.EXTRA_SENSOR;
import static android.hardware.SensorPrivacyManager.Sensors.CAMERA;
import static android.hardware.SensorPrivacyManager.Sensors.MICROPHONE;
import static android.os.UserHandle.USER_SYSTEM; import static android.os.UserHandle.USER_SYSTEM;
import static android.service.SensorPrivacyIndividualEnabledSensorProto.CAMERA;
import static android.service.SensorPrivacyIndividualEnabledSensorProto.MICROPHONE;
import static android.service.SensorPrivacyIndividualEnabledSensorProto.UNKNOWN; import static android.service.SensorPrivacyIndividualEnabledSensorProto.UNKNOWN;
import android.annotation.NonNull; import android.annotation.NonNull;
@@ -406,12 +406,12 @@ public final class SensorPrivacyService extends SystemService {
*/ */
@Override @Override
public void setSensorPrivacy(boolean enable) { public void setSensorPrivacy(boolean enable) {
enforceManageSensorPrivacyPermission();
// Keep the state consistent between all users to make it a single global state // Keep the state consistent between all users to make it a single global state
forAllUsers(userId -> setSensorPrivacy(userId, enable)); forAllUsers(userId -> setSensorPrivacy(userId, enable));
} }
private void setSensorPrivacy(@UserIdInt int userId, boolean enable) { private void setSensorPrivacy(@UserIdInt int userId, boolean enable) {
enforceSensorPrivacyPermission();
synchronized (mLock) { synchronized (mLock) {
mEnabled.put(userId, enable); mEnabled.put(userId, enable);
persistSensorPrivacyStateLocked(); persistSensorPrivacyStateLocked();
@@ -421,7 +421,7 @@ public final class SensorPrivacyService extends SystemService {
@Override @Override
public void setIndividualSensorPrivacy(@UserIdInt int userId, int sensor, boolean enable) { public void setIndividualSensorPrivacy(@UserIdInt int userId, int sensor, boolean enable) {
enforceSensorPrivacyPermission(); enforceManageSensorPrivacyPermission();
synchronized (mLock) { synchronized (mLock) {
SparseBooleanArray userIndividualEnabled = mIndividualEnabled.get(userId, SparseBooleanArray userIndividualEnabled = mIndividualEnabled.get(userId,
new SparseBooleanArray()); new SparseBooleanArray());
@@ -448,6 +448,7 @@ public final class SensorPrivacyService extends SystemService {
@Override @Override
public void setIndividualSensorPrivacyForProfileGroup(@UserIdInt int userId, int sensor, public void setIndividualSensorPrivacyForProfileGroup(@UserIdInt int userId, int sensor,
boolean enable) { boolean enable) {
enforceManageSensorPrivacyPermission();
int parentId = mUserManagerInternal.getProfileParentId(userId); int parentId = mUserManagerInternal.getProfileParentId(userId);
forAllUsers(userId2 -> { forAllUsers(userId2 -> {
if (parentId == mUserManagerInternal.getProfileParentId(userId2)) { if (parentId == mUserManagerInternal.getProfileParentId(userId2)) {
@@ -460,21 +461,35 @@ public final class SensorPrivacyService extends SystemService {
* Enforces the caller contains the necessary permission to change the state of sensor * Enforces the caller contains the necessary permission to change the state of sensor
* privacy. * privacy.
*/ */
private void enforceSensorPrivacyPermission() { private void enforceManageSensorPrivacyPermission() {
if (mContext.checkCallingOrSelfPermission( enforcePermission(android.Manifest.permission.MANAGE_SENSOR_PRIVACY,
MANAGE_SENSOR_PRIVACY) == PERMISSION_GRANTED) {
return;
}
throw new SecurityException(
"Changing sensor privacy requires the following permission: " "Changing sensor privacy requires the following permission: "
+ MANAGE_SENSOR_PRIVACY); + MANAGE_SENSOR_PRIVACY);
} }
/**
* Enforces the caller contains the necessary permission to observe changes to the sate of
* sensor privacy.
*/
private void enforceObserveSensorPrivacyPermission() {
enforcePermission(android.Manifest.permission.OBSERVE_SENSOR_PRIVACY,
"Observing sensor privacy changes requires the following permission: "
+ android.Manifest.permission.OBSERVE_SENSOR_PRIVACY);
}
private void enforcePermission(String permission, String message) {
if (mContext.checkCallingOrSelfPermission(permission) == PERMISSION_GRANTED) {
return;
}
throw new SecurityException(message);
}
/** /**
* Returns whether sensor privacy is enabled. * Returns whether sensor privacy is enabled.
*/ */
@Override @Override
public boolean isSensorPrivacyEnabled() { public boolean isSensorPrivacyEnabled() {
enforceObserveSensorPrivacyPermission();
return isSensorPrivacyEnabled(USER_SYSTEM); return isSensorPrivacyEnabled(USER_SYSTEM);
} }
@@ -486,6 +501,7 @@ public final class SensorPrivacyService extends SystemService {
@Override @Override
public boolean isIndividualSensorPrivacyEnabled(@UserIdInt int userId, int sensor) { public boolean isIndividualSensorPrivacyEnabled(@UserIdInt int userId, int sensor) {
enforceObserveSensorPrivacyPermission();
synchronized (mLock) { synchronized (mLock) {
SparseBooleanArray states = mIndividualEnabled.get(userId); SparseBooleanArray states = mIndividualEnabled.get(userId);
if (states == null) { if (states == null) {
@@ -703,6 +719,7 @@ public final class SensorPrivacyService extends SystemService {
*/ */
@Override @Override
public void addSensorPrivacyListener(ISensorPrivacyListener listener) { public void addSensorPrivacyListener(ISensorPrivacyListener listener) {
enforceObserveSensorPrivacyPermission();
if (listener == null) { if (listener == null) {
throw new NullPointerException("listener cannot be null"); throw new NullPointerException("listener cannot be null");
} }
@@ -715,6 +732,7 @@ public final class SensorPrivacyService extends SystemService {
@Override @Override
public void addIndividualSensorPrivacyListener(int userId, int sensor, public void addIndividualSensorPrivacyListener(int userId, int sensor,
ISensorPrivacyListener listener) { ISensorPrivacyListener listener) {
enforceObserveSensorPrivacyPermission();
if (listener == null) { if (listener == null) {
throw new NullPointerException("listener cannot be null"); throw new NullPointerException("listener cannot be null");
} }
@@ -726,6 +744,7 @@ public final class SensorPrivacyService extends SystemService {
*/ */
@Override @Override
public void removeSensorPrivacyListener(ISensorPrivacyListener listener) { public void removeSensorPrivacyListener(ISensorPrivacyListener listener) {
enforceObserveSensorPrivacyPermission();
if (listener == null) { if (listener == null) {
throw new NullPointerException("listener cannot be null"); throw new NullPointerException("listener cannot be null");
} }
@@ -735,6 +754,7 @@ public final class SensorPrivacyService extends SystemService {
@Override @Override
public void suppressIndividualSensorPrivacyReminders(int userId, String packageName, public void suppressIndividualSensorPrivacyReminders(int userId, String packageName,
IBinder token, boolean suppress) { IBinder token, boolean suppress) {
enforceManageSensorPrivacyPermission();
Objects.requireNonNull(packageName); Objects.requireNonNull(packageName);
Objects.requireNonNull(token); Objects.requireNonNull(token);
@@ -886,13 +906,13 @@ public final class SensorPrivacyService extends SystemService {
} }
/** /**
* Convert a string into a {@link SensorPrivacyManager.IndividualSensor id}. * Convert a string into a {@link SensorPrivacyManager.Sensors.Sensor id}.
* *
* @param sensor The name to convert * @param sensor The name to convert
* *
* @return The id corresponding to the name * @return The id corresponding to the name
*/ */
private @SensorPrivacyManager.IndividualSensor int sensorStrToId(@Nullable String sensor) { private @SensorPrivacyManager.Sensors.Sensor int sensorStrToId(@Nullable String sensor) {
if (sensor == null) { if (sensor == null) {
return UNKNOWN; return UNKNOWN;
} }
@@ -950,7 +970,7 @@ public final class SensorPrivacyService extends SystemService {
return -1; return -1;
} }
enforceSensorPrivacyPermission(); enforceManageSensorPrivacyPermission();
synchronized (mLock) { synchronized (mLock) {
SparseBooleanArray individualEnabled = SparseBooleanArray individualEnabled =

View File

@@ -295,7 +295,7 @@ public class ContextHubService extends IContextHubService.Stub {
}; };
SensorPrivacyManager manager = SensorPrivacyManager.getInstance(mContext); SensorPrivacyManager manager = SensorPrivacyManager.getInstance(mContext);
manager.addSensorPrivacyListener( manager.addSensorPrivacyListener(
SensorPrivacyManager.INDIVIDUAL_SENSOR_MICROPHONE, listener); SensorPrivacyManager.Sensors.MICROPHONE, listener);
} }
} }
@@ -1079,8 +1079,8 @@ public class ContextHubService extends IContextHubService.Stub {
*/ */
private void sendMicrophoneDisableSettingUpdate() { private void sendMicrophoneDisableSettingUpdate() {
SensorPrivacyManager manager = SensorPrivacyManager.getInstance(mContext); SensorPrivacyManager manager = SensorPrivacyManager.getInstance(mContext);
boolean disabled = manager.isIndividualSensorPrivacyEnabled( boolean disabled = manager.isSensorPrivacyEnabled(
SensorPrivacyManager.INDIVIDUAL_SENSOR_MICROPHONE); SensorPrivacyManager.Sensors.MICROPHONE);
Log.d(TAG, "Mic Disabled Setting: " + disabled); Log.d(TAG, "Mic Disabled Setting: " + disabled);
mContextHubWrapper.onMicrophoneDisableSettingChanged(disabled); mContextHubWrapper.onMicrophoneDisableSettingChanged(disabled);
} }