summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
author Xiang Wang <xiangw@google.com> 2024-08-12 19:44:59 +0000
committer Xiang Wang <xiangw@google.com> 2024-08-26 19:11:17 +0000
commit7c4da90c9f2bff2c7ccf8846e4ca4a62d35f4bcc (patch)
tree54782736b978dd6f4a789ac9f8622a345a4596fc
parent925d1a6ffc25f268771831f78a2c50f8c6e51ac2 (diff)
Make SensorPrivacyManager and SensorPrivacyService concurrent multi user
aware In Automotive's Multi Display configuration, multiple Android users - the current user (driver) and visible background users (passengers) can interact with the device concurrently therefore may be accessing the sensor privacy API surface concurrently. Existing code that assumes the calling user is the current user will cause visible background users (passengers) to be able to toggle the current user (driver)'s sensor privacy. Fixes include: - Set sensor privacy for the context user instead of always assuming the current user. - Enforce valid calling users by disallowing visible background users to toggle sensor privacy based on Automotive's product decision to only allow the driver to toggle sensor privacy. - Check valid calling user before setting sensor privacy in onUserRestrictionsChanged because DISALLOW_MICROPHONE_TOGGLE and DISALLOW_CAMERA_TOGGLE are applied on visible background users in CarService but we don't allow setting sensor privacy on a visible background user. Bug: 348510106 Flag: EXEMPT bug fix Test: manually tested on gcar_md emulator Test: Temporarily remove DISALLOW_MICROPHONE_TOGGLE on passengers to make microphone toggle available on a passenger and toggling it will fail Change-Id: Iede71fa6cd6ac2962916479b8c5751cd75e6f4e6
-rw-r--r--core/java/android/app/SystemServiceRegistry.java9
-rw-r--r--core/java/android/hardware/SensorPrivacyManager.java8
-rw-r--r--services/core/java/com/android/server/sensorprivacy/SensorPrivacyService.java65
3 files changed, 74 insertions, 8 deletions
diff --git a/core/java/android/app/SystemServiceRegistry.java b/core/java/android/app/SystemServiceRegistry.java
index cb38cf297cf6..f315772a4eed 100644
--- a/core/java/android/app/SystemServiceRegistry.java
+++ b/core/java/android/app/SystemServiceRegistry.java
@@ -101,6 +101,7 @@ import android.debug.IAdbManager;
import android.devicelock.DeviceLockFrameworkInitializer;
import android.graphics.fonts.FontManager;
import android.hardware.ConsumerIrManager;
+import android.hardware.ISensorPrivacyManager;
import android.hardware.ISerialManager;
import android.hardware.SensorManager;
import android.hardware.SensorPrivacyManager;
@@ -704,8 +705,12 @@ public final class SystemServiceRegistry {
registerService(Context.SENSOR_PRIVACY_SERVICE, SensorPrivacyManager.class,
new CachedServiceFetcher<SensorPrivacyManager>() {
@Override
- public SensorPrivacyManager createService(ContextImpl ctx) {
- return SensorPrivacyManager.getInstance(ctx);
+ public SensorPrivacyManager createService(ContextImpl ctx)
+ throws ServiceNotFoundException {
+ IBinder b = ServiceManager.getServiceOrThrow(
+ Context.SENSOR_PRIVACY_SERVICE);
+ return SensorPrivacyManager.getInstance(
+ ctx, ISensorPrivacyManager.Stub.asInterface(b));
}});
registerService(Context.STATUS_BAR_SERVICE, StatusBarManager.class,
diff --git a/core/java/android/hardware/SensorPrivacyManager.java b/core/java/android/hardware/SensorPrivacyManager.java
index 4cdaaddd05bf..a4c0e87c965b 100644
--- a/core/java/android/hardware/SensorPrivacyManager.java
+++ b/core/java/android/hardware/SensorPrivacyManager.java
@@ -797,7 +797,7 @@ public final class SensorPrivacyManager {
public void setSensorPrivacy(@Sensors.Sensor int sensor,
boolean enable) {
setSensorPrivacy(resolveSourceFromCurrentContext(), sensor, enable,
- UserHandle.USER_CURRENT);
+ mContext.getUserId());
}
private @Sources.Source int resolveSourceFromCurrentContext() {
@@ -837,6 +837,8 @@ public final class SensorPrivacyManager {
@RequiresPermission(Manifest.permission.MANAGE_SENSOR_PRIVACY)
public void setSensorPrivacy(@Sources.Source int source, @Sensors.Sensor int sensor,
boolean enable) {
+ // TODO(b/348510106): Replace USER_CURRENT with Context user and fix any tests that may be
+ // affected.
setSensorPrivacy(source, sensor, enable, UserHandle.USER_CURRENT);
}
@@ -894,7 +896,7 @@ public final class SensorPrivacyManager {
@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);
+ setSensorPrivacyForProfileGroup(source , sensor, enable, mContext.getUserId());
}
/**
@@ -950,7 +952,7 @@ public final class SensorPrivacyManager {
@RequiresPermission(Manifest.permission.MANAGE_SENSOR_PRIVACY)
public void suppressSensorPrivacyReminders(int sensor,
boolean suppress) {
- suppressSensorPrivacyReminders(sensor, suppress, UserHandle.USER_CURRENT);
+ suppressSensorPrivacyReminders(sensor, suppress, mContext.getUserId());
}
/**
diff --git a/services/core/java/com/android/server/sensorprivacy/SensorPrivacyService.java b/services/core/java/com/android/server/sensorprivacy/SensorPrivacyService.java
index 06a2565da75a..81217014bafe 100644
--- a/services/core/java/com/android/server/sensorprivacy/SensorPrivacyService.java
+++ b/services/core/java/com/android/server/sensorprivacy/SensorPrivacyService.java
@@ -51,6 +51,7 @@ import static android.hardware.SensorPrivacyManager.StateTypes.ENABLED_EXCEPT_AL
import static android.hardware.SensorPrivacyManager.TOGGLE_TYPE_HARDWARE;
import static android.hardware.SensorPrivacyManager.TOGGLE_TYPE_SOFTWARE;
import static android.os.UserHandle.USER_NULL;
+import static android.os.UserHandle.getCallingUserId;
import static android.service.SensorPrivacyIndividualEnabledSensorProto.UNKNOWN;
import static com.android.internal.util.FrameworkStatsLog.PRIVACY_SENSOR_TOGGLE_INTERACTION;
@@ -187,6 +188,7 @@ public final class SensorPrivacyService extends SystemService {
private final TelephonyManager mTelephonyManager;
private final PackageManagerInternal mPackageManagerInternal;
private final NotificationManager mNotificationManager;
+ private final UserManager mUserManager;
private CameraPrivacyLightController mCameraPrivacyLightController;
@@ -214,6 +216,7 @@ public final class SensorPrivacyService extends SystemService {
mTelephonyManager = context.getSystemService(TelephonyManager.class);
mPackageManagerInternal = getLocalService(PackageManagerInternal.class);
mNotificationManager = mContext.getSystemService(NotificationManager.class);
+ mUserManager = context.getSystemService(UserManager.class);
mSensorPrivacyServiceImpl = new SensorPrivacyServiceImpl();
for (String entry : SystemConfig.getInstance().getCameraPrivacyAllowlist()) {
mCameraPrivacyAllowlist.add(entry);
@@ -379,14 +382,23 @@ public final class SensorPrivacyService extends SystemService {
public void onUserRestrictionsChanged(int userId, Bundle newRestrictions,
Bundle prevRestrictions) {
// Reset sensor privacy when restriction is added
+ // Note: isValidCallingUser needs to be called before resetting sensor privacy
+ // because DISALLOW_CAMERA_TOGGLE and DISALLOW_MICROPHONE_TOGGLE are applied on
+ // visible background users in Automotive's Multi Display configuration but we don't
+ // allow sensor privacy to be set on a visible background user.
if (!prevRestrictions.getBoolean(UserManager.DISALLOW_CAMERA_TOGGLE)
&& newRestrictions.getBoolean(UserManager.DISALLOW_CAMERA_TOGGLE)) {
- setToggleSensorPrivacyUnchecked(TOGGLE_TYPE_SOFTWARE, userId, OTHER, CAMERA, false);
+ if (isValidCallingUser(userId)) {
+ setToggleSensorPrivacyUnchecked(TOGGLE_TYPE_SOFTWARE, userId, OTHER, CAMERA,
+ false);
+ }
}
if (!prevRestrictions.getBoolean(UserManager.DISALLOW_MICROPHONE_TOGGLE)
&& newRestrictions.getBoolean(UserManager.DISALLOW_MICROPHONE_TOGGLE)) {
- setToggleSensorPrivacyUnchecked(TOGGLE_TYPE_SOFTWARE, userId, OTHER, MICROPHONE,
- false);
+ if (isValidCallingUser(userId)) {
+ setToggleSensorPrivacyUnchecked(TOGGLE_TYPE_SOFTWARE, userId, OTHER, MICROPHONE,
+ false);
+ }
}
}
@@ -779,6 +791,10 @@ public final class SensorPrivacyService extends SystemService {
@Override
public void setSensorPrivacy(boolean enable) {
enforceManageSensorPrivacyPermission();
+
+ // Enforce valid calling user on devices that enable visible background users.
+ enforceValidCallingUser(getCallingUserId());
+
mSensorPrivacyStateController.setAllSensorState(enable);
}
@@ -795,11 +811,15 @@ public final class SensorPrivacyService extends SystemService {
+ " enable=" + enable
+ ")");
}
+
enforceManageSensorPrivacyPermission();
if (userId == UserHandle.USER_CURRENT) {
userId = mCurrentUser;
}
+ // Enforce valid calling user on devices that enable visible background users.
+ enforceValidCallingUser(userId);
+
if (!canChangeToggleSensorPrivacy(userId, sensor)) {
return;
}
@@ -831,6 +851,9 @@ public final class SensorPrivacyService extends SystemService {
userId = mCurrentUser;
}
+ // Enforce valid calling user on devices that enable visible background users.
+ enforceValidCallingUser(userId);
+
if (!canChangeToggleSensorPrivacy(userId, sensor)) {
return;
}
@@ -1151,6 +1174,42 @@ public final class SensorPrivacyService extends SystemService {
});
}
+ // This method enforces valid calling user on devices that enable visible background users.
+ // Only system user or current user or the user that belongs to the same profile group
+ // as the current user is permitted to toggle sensor privacy.
+ // Visible background users are not permitted to toggle sensor privacy.
+ private void enforceValidCallingUser(@UserIdInt int userId) {
+ if (!isValidCallingUser(userId)) {
+ throw new SecurityException("User " + userId
+ + " is not permitted to toggle sensor privacy");
+ }
+ }
+
+ private boolean isValidCallingUser(@UserIdInt int userId) {
+ // Check whether visible background users are enabled.
+ // Visible background users are non current but can have UI access.
+ // The main use case for visible background users is the passenger in Automotive's
+ // Multi-Display configuration.
+ if (!UserManager.isVisibleBackgroundUsersEnabled()) {
+ return true;
+ }
+
+ if (userId == UserHandle.USER_SYSTEM || userId == mCurrentUser) {
+ return true;
+ }
+
+ final long ident = Binder.clearCallingIdentity();
+ try {
+ if (mUserManager.isSameProfileGroup(userId, mCurrentUser)) {
+ return true;
+ }
+ } finally {
+ Binder.restoreCallingIdentity(ident);
+ }
+
+ return false;
+ }
+
/**
* Enforces the caller contains the necessary permission to change the state of sensor
* privacy.