Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 7c4da90c authored by Xiang Wang's avatar Xiang Wang
Browse files

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
parent 925d1a6f
Loading
Loading
Loading
Loading
+7 −2
Original line number Diff line number Diff line
@@ -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,
+5 −3
Original line number Diff line number Diff line
@@ -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());
    }

    /**
+62 −3
Original line number Diff line number Diff line
@@ -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,16 +382,25 @@ 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)) {
                if (isValidCallingUser(userId)) {
                    setToggleSensorPrivacyUnchecked(TOGGLE_TYPE_SOFTWARE, userId, OTHER, MICROPHONE,
                            false);
                }
            }
        }

        @Override
        public void onOpStarted(int code, int uid, String packageName, String attributionTag,
@@ -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.