diff options
| author | 2024-08-12 19:44:59 +0000 | |
|---|---|---|
| committer | 2024-08-26 19:11:17 +0000 | |
| commit | 7c4da90c9f2bff2c7ccf8846e4ca4a62d35f4bcc (patch) | |
| tree | 54782736b978dd6f4a789ac9f8622a345a4596fc | |
| parent | 925d1a6ffc25f268771831f78a2c50f8c6e51ac2 (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
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. |