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

Commit f5170f48 authored by TreeHugger Robot's avatar TreeHugger Robot Committed by Android (Google) Code Review
Browse files

Merge "Fix secondary user test for VirtualDevice" into tm-dev

parents fc94de68 8e34e635
Loading
Loading
Loading
Loading
+28 −11
Original line number Diff line number Diff line
@@ -33,17 +33,19 @@ import com.android.internal.annotations.GuardedBy;
/**
 * Handles blocking access to the camera for apps running on virtual devices.
 */
class CameraAccessController extends CameraManager.AvailabilityCallback {
class CameraAccessController extends CameraManager.AvailabilityCallback implements AutoCloseable {
    private static final String TAG = "CameraAccessController";

    private final Object mLock = new Object();

    private final Context mContext;
    private VirtualDeviceManagerInternal mVirtualDeviceManagerInternal;
    CameraAccessBlockedCallback mBlockedCallback;
    private CameraManager mCameraManager;
    private boolean mListeningForCameraEvents;
    private PackageManager mPackageManager;
    private final VirtualDeviceManagerInternal mVirtualDeviceManagerInternal;
    private final CameraAccessBlockedCallback mBlockedCallback;
    private final CameraManager mCameraManager;
    private final PackageManager mPackageManager;

    @GuardedBy("mLock")
    private int mObserverCount = 0;

    @GuardedBy("mLock")
    private ArrayMap<String, InjectionSessionData> mPackageToSessionData = new ArrayMap<>();
@@ -77,21 +79,36 @@ class CameraAccessController extends CameraManager.AvailabilityCallback {
     */
    public void startObservingIfNeeded() {
        synchronized (mLock) {
            if (!mListeningForCameraEvents) {
            if (mObserverCount == 0) {
                mCameraManager.registerAvailabilityCallback(mContext.getMainExecutor(), this);
                mListeningForCameraEvents = true;
            }
            mObserverCount++;
        }
    }

    /**
     * Stop watching for camera access.
     */
    public void stopObserving() {
    public void stopObservingIfNeeded() {
        synchronized (mLock) {
            mCameraManager.unregisterAvailabilityCallback(this);
            mListeningForCameraEvents = false;
            mObserverCount--;
            if (mObserverCount <= 0) {
                close();
            }
        }
    }


    @Override
    public void close() {
        synchronized (mLock) {
            if (mObserverCount < 0) {
                Slog.wtf(TAG, "Unexpected negative mObserverCount: " + mObserverCount);
            } else if (mObserverCount > 0) {
                Slog.w(TAG, "Unexpected close with observers remaining: " + mObserverCount);
            }
        }
        mCameraManager.unregisterAvailabilityCallback(this);
    }

    @Override
+11 −5
Original line number Diff line number Diff line
@@ -18,6 +18,8 @@ package com.android.server.companion.virtual;

import android.content.Context;
import android.content.pm.PackageManager;
import android.os.Binder;
import android.os.UserHandle;
import android.util.Slog;

/**
@@ -32,13 +34,15 @@ class PermissionUtils {
     *
     * @param context the context
     * @param callingPackage the calling application package name
     * @param callingUid the calling application uid
     * @return {@code true} if the package name matches the calling app uid, {@code false} otherwise
     * @return {@code true} if the package name matches {@link Binder#getCallingUid()}, or
     *   {@code false} otherwise
     */
    public static boolean validatePackageName(Context context, String callingPackage,
            int callingUid) {
    public static boolean validateCallingPackageName(Context context, String callingPackage) {
        final int callingUid = Binder.getCallingUid();
        final long token = Binder.clearCallingIdentity();
        try {
            int packageUid = context.getPackageManager().getPackageUid(callingPackage, 0);
            int packageUid = context.getPackageManager()
                    .getPackageUidAsUser(callingPackage, UserHandle.getUserId(callingUid));
            if (packageUid != callingUid) {
                Slog.e(LOG_TAG, "validatePackageName: App with package name " + callingPackage
                        + " is UID " + packageUid + " but caller is " + callingUid);
@@ -48,6 +52,8 @@ class PermissionUtils {
            Slog.e(LOG_TAG, "validatePackageName: App with package name " + callingPackage
                    + " does not exist");
            return false;
        } finally {
            Binder.restoreCallingIdentity(token);
        }
        return true;
    }
+2 −1
Original line number Diff line number Diff line
@@ -140,7 +140,8 @@ final class VirtualDeviceImpl extends IVirtualDevice.Stub
            int ownerUid, InputController inputController, OnDeviceCloseListener listener,
            PendingTrampolineCallback pendingTrampolineCallback,
            IVirtualDeviceActivityListener activityListener, VirtualDeviceParams params) {
        mContext = context;
        UserHandle ownerUserHandle = UserHandle.getUserHandleForUid(ownerUid);
        mContext = context.createContextAsUser(ownerUserHandle, 0);
        mAssociationInfo = associationInfo;
        mPendingTrampolineCallback = pendingTrampolineCallback;
        mActivityListener = activityListener;
+35 −10
Original line number Diff line number Diff line
@@ -36,6 +36,7 @@ import android.os.IBinder;
import android.os.Looper;
import android.os.Parcel;
import android.os.RemoteException;
import android.os.UserHandle;
import android.util.ExceptionUtils;
import android.util.Slog;
import android.util.SparseArray;
@@ -66,7 +67,12 @@ public class VirtualDeviceManagerService extends SystemService {
    private VirtualDeviceManagerInternal mLocalService;
    private final Handler mHandler = new Handler(Looper.getMainLooper());
    private final PendingTrampolineMap mPendingTrampolines = new PendingTrampolineMap(mHandler);
    private final CameraAccessController mCameraAccessController;
    /**
     * Mapping from user IDs to CameraAccessControllers.
     */
    @GuardedBy("mVirtualDeviceManagerLock")
    private final SparseArray<CameraAccessController> mCameraAccessControllers =
            new SparseArray<>();

    /**
     * Mapping from CDM association IDs to virtual devices. Only one virtual device is allowed for
@@ -94,8 +100,6 @@ public class VirtualDeviceManagerService extends SystemService {
        super(context);
        mImpl = new VirtualDeviceManagerImpl();
        mLocalService = new LocalService();
        mCameraAccessController = new CameraAccessController(getContext(), mLocalService,
                this::onCameraAccessBlocked);
    }

    private final ActivityInterceptorCallback mActivityInterceptorCallback =
@@ -144,16 +148,19 @@ public class VirtualDeviceManagerService extends SystemService {
    @Override
    public void onUserStarting(@NonNull TargetUser user) {
        super.onUserStarting(user);
        Context userContext = getContext().createContextAsUser(user.getUserHandle(), 0);
        synchronized (mVirtualDeviceManagerLock) {
            final CompanionDeviceManager cdm = getContext()
                    .createContextAsUser(user.getUserHandle(), 0)
                    .getSystemService(CompanionDeviceManager.class);
            final CompanionDeviceManager cdm =
                    userContext.getSystemService(CompanionDeviceManager.class);
            final int userId = user.getUserIdentifier();
            mAllAssociations.put(userId, cdm.getAllAssociations());
            OnAssociationsChangedListener listener =
                    associations -> mAllAssociations.put(userId, associations);
            mOnAssociationsChangedListeners.put(userId, listener);
            cdm.addOnAssociationsChangedListener(Runnable::run, listener);
            CameraAccessController cameraAccessController = new CameraAccessController(
                    userContext, mLocalService, this::onCameraAccessBlocked);
            mCameraAccessControllers.put(user.getUserIdentifier(), cameraAccessController);
        }
    }

@@ -171,6 +178,14 @@ public class VirtualDeviceManagerService extends SystemService {
                cdm.removeOnAssociationsChangedListener(listener);
                mOnAssociationsChangedListeners.remove(userId);
            }
            CameraAccessController cameraAccessController = mCameraAccessControllers.get(
                    user.getUserIdentifier());
            if (cameraAccessController != null) {
                cameraAccessController.close();
                mCameraAccessControllers.remove(user.getUserIdentifier());
            } else {
                Slog.w(TAG, "Cannot unregister cameraAccessController for user " + user);
            }
        }
    }

@@ -198,7 +213,7 @@ public class VirtualDeviceManagerService extends SystemService {
                    android.Manifest.permission.CREATE_VIRTUAL_DEVICE,
                    "createVirtualDevice");
            final int callingUid = getCallingUid();
            if (!PermissionUtils.validatePackageName(getContext(), packageName, callingUid)) {
            if (!PermissionUtils.validateCallingPackageName(getContext(), packageName)) {
                throw new SecurityException(
                        "Package name " + packageName + " does not belong to calling uid "
                                + callingUid);
@@ -213,6 +228,9 @@ public class VirtualDeviceManagerService extends SystemService {
                            "Virtual device for association ID " + associationId
                                    + " already exists");
                }
                final int userId = UserHandle.getUserId(callingUid);
                final CameraAccessController cameraAccessController =
                        mCameraAccessControllers.get(userId);
                VirtualDeviceImpl virtualDevice = new VirtualDeviceImpl(getContext(),
                        associationInfo, token, callingUid,
                        new VirtualDeviceImpl.OnDeviceCloseListener() {
@@ -220,14 +238,21 @@ public class VirtualDeviceManagerService extends SystemService {
                            public void onClose(int associationId) {
                                synchronized (mVirtualDeviceManagerLock) {
                                    mVirtualDevices.remove(associationId);
                                    if (mVirtualDevices.size() == 0) {
                                        mCameraAccessController.stopObserving();
                                    if (cameraAccessController != null) {
                                        cameraAccessController.stopObservingIfNeeded();
                                    } else {
                                        Slog.w(TAG, "cameraAccessController not found for user "
                                                + userId);
                                    }
                                }
                            }
                        },
                        this, activityListener, params);
                mCameraAccessController.startObservingIfNeeded();
                if (cameraAccessController != null) {
                    cameraAccessController.startObservingIfNeeded();
                } else {
                    Slog.w(TAG, "cameraAccessController not found for user " + userId);
                }
                mVirtualDevices.put(associationInfo.getId(), virtualDevice);
                return virtualDevice;
            }
+2 −0
Original line number Diff line number Diff line
@@ -98,6 +98,8 @@
    <uses-permission android:name="android.permission.MAINLINE_NETWORK_STACK"/>
    <uses-permission
        android:name="android.permission.OVERRIDE_COMPAT_CHANGE_CONFIG_ON_RELEASE_BUILD"/>
    <uses-permission android:name="android.permission.ASSOCIATE_INPUT_DEVICE_TO_DISPLAY" />
    <uses-permission android:name="android.permission.READ_NEARBY_STREAMING_POLICY" />

    <uses-permission android:name="android.permission.PACKAGE_VERIFICATION_AGENT" />

Loading