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

Commit 8d900756 authored by Vladimir Komsiyski's avatar Vladimir Komsiyski Committed by Android (Google) Code Review
Browse files

Merge "Fix VDM UID tracking." into main

parents eef752ca 7d746a33
Loading
Loading
Loading
Loading
+12 −24
Original line number Diff line number Diff line
@@ -183,8 +183,7 @@ public class ProxyManager {
        synchronized (mLock) {
            mProxyA11yServiceConnections.put(displayId, connection);
            if (mAppsOnVirtualDeviceListener == null) {
                mAppsOnVirtualDeviceListener = allRunningUids ->
                        notifyProxyOfRunningAppsChange(allRunningUids);
                mAppsOnVirtualDeviceListener = this::notifyProxyOfRunningAppsChange;
                final VirtualDeviceManagerInternal localVdm = getLocalVdm();
                if (localVdm != null) {
                    localVdm.registerAppsOnVirtualDeviceListener(mAppsOnVirtualDeviceListener);
@@ -870,34 +869,23 @@ public class ProxyManager {
    }

    @VisibleForTesting
    void notifyProxyOfRunningAppsChange(Set<Integer> allRunningUids) {
    void notifyProxyOfRunningAppsChange(int deviceId, @NonNull ArraySet<Integer> runningUids) {
        if (DEBUG) {
            Slog.v(LOG_TAG, "notifyProxyOfRunningAppsChange: " + allRunningUids);
            Slog.v(LOG_TAG, "notifyProxyOfRunningAppsChange: deviceId=" + deviceId
                    + " runningUids=" + runningUids);
        }
        boolean changed = false;
        synchronized (mLock) {
            if (mProxyA11yServiceConnections.size() == 0) {
                return;
            }
            final VirtualDeviceManagerInternal localVdm = getLocalVdm();
            if  (localVdm == null) {
                return;
            }
            final ArraySet<Integer> deviceIdsToUpdate = new ArraySet<>();
            for (int i = 0; i < mProxyA11yServiceConnections.size(); i++) {
                final ProxyAccessibilityServiceConnection proxy =
                        mProxyA11yServiceConnections.valueAt(i);
                if (proxy != null) {
                    final int proxyDeviceId = proxy.getDeviceId();
                    for (Integer uid : allRunningUids) {
                        if (localVdm.getDeviceIdsForUid(uid).contains(proxyDeviceId)) {
                            deviceIdsToUpdate.add(proxyDeviceId);
                        }
                    }
                ProxyAccessibilityServiceConnection proxy = mProxyA11yServiceConnections.valueAt(i);
                if (proxy != null && deviceId == proxy.getDeviceId()) {
                    changed = true;
                    break;
                }
            }
            for (Integer proxyDeviceId : deviceIdsToUpdate) {
                onProxyChanged(proxyDeviceId, true);
        }
        if (changed) {
            onProxyChanged(deviceId, true);
        }
    }

+9 −46
Original line number Diff line number Diff line
@@ -44,7 +44,6 @@ import android.view.Display;
import android.window.DisplayWindowPolicyController;

import com.android.internal.annotations.GuardedBy;
import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.app.BlockedAppStreamingActivity;
import com.android.modules.expresslog.Counter;

@@ -56,21 +55,13 @@ import java.util.function.Supplier;
/**
 * A controller to control the policies of the windows that can be displayed on the virtual display.
 */
public class GenericWindowPolicyController extends DisplayWindowPolicyController {
class GenericWindowPolicyController extends DisplayWindowPolicyController {

    private static final String TAG = "GenericWindowPolicyController";

    private static final ComponentName BLOCKED_APP_STREAMING_COMPONENT =
            new ComponentName("android", BlockedAppStreamingActivity.class.getName());

    /** Interface to listen running applications change on virtual display. */
    public interface RunningAppsChangedListener {
        /**
         * Notifies the running applications change.
         */
        void onRunningAppsChanged(ArraySet<Integer> runningUids);
    }

    /** Interface to react to activity changes on the virtual display. */
    public interface ActivityListener {

@@ -93,6 +84,9 @@ public class GenericWindowPolicyController extends DisplayWindowPolicyController

        /** Returns true when an intent should be intercepted */
        boolean shouldInterceptIntent(@NonNull Intent intent);

        /** Called when the set of running apps on this display changes. */
        void onRunningAppsChanged(int displayId, @NonNull ArraySet<Integer> runningUids);
    }

    /**
@@ -135,10 +129,6 @@ public class GenericWindowPolicyController extends DisplayWindowPolicyController
    private final ArraySet<Integer> mRunningUids = new ArraySet<>();
    @NonNull private final ActivityListener mActivityListener;
    private final Handler mHandler = new Handler(Looper.getMainLooper());
    @NonNull
    @GuardedBy("mGenericWindowPolicyControllerLock")
    private final ArraySet<RunningAppsChangedListener> mRunningAppsChangedListeners =
            new ArraySet<>();
    @NonNull private final Set<String> mDisplayCategories;

    @GuardedBy("mGenericWindowPolicyControllerLock")
@@ -279,20 +269,6 @@ public class GenericWindowPolicyController extends DisplayWindowPolicyController
        }
    }

    /** Register a listener for running applications changes. */
    public void registerRunningAppsChangedListener(@NonNull RunningAppsChangedListener listener) {
        synchronized (mGenericWindowPolicyControllerLock) {
            mRunningAppsChangedListeners.add(listener);
        }
    }

    /** Unregister a listener for running applications changes. */
    public void unregisterRunningAppsChangedListener(@NonNull RunningAppsChangedListener listener) {
        synchronized (mGenericWindowPolicyControllerLock) {
            mRunningAppsChangedListeners.remove(listener);
        }
    }

    @Override
    public boolean canActivityBeLaunched(@NonNull ActivityInfo activityInfo,
            @Nullable Intent intent, @WindowConfiguration.WindowingMode int windowingMode,
@@ -421,18 +397,12 @@ public class GenericWindowPolicyController extends DisplayWindowPolicyController
            mRunningUids.clear();
            mRunningUids.addAll(runningUids);
            int displayId = waitAndGetDisplayId();
            if (mRunningUids.isEmpty() && displayId != INVALID_DISPLAY) {
                // Post callback on the main thread so it doesn't block activity launching
                mHandler.post(() -> mActivityListener.onDisplayEmpty(displayId));
            }
            if (!mRunningAppsChangedListeners.isEmpty()) {
                final ArraySet<RunningAppsChangedListener> listeners =
                        new ArraySet<>(mRunningAppsChangedListeners);
                mHandler.post(() -> {
                    for (RunningAppsChangedListener listener : listeners) {
                        listener.onRunningAppsChanged(runningUids);
            if (displayId == INVALID_DISPLAY) {
                return;
            }
                });
            mHandler.post(() -> mActivityListener.onRunningAppsChanged(displayId, runningUids));
            if (mRunningUids.isEmpty()) {
                mHandler.post(() -> mActivityListener.onDisplayEmpty(displayId));
            }
        }
    }
@@ -496,11 +466,4 @@ public class GenericWindowPolicyController extends DisplayWindowPolicyController
        // or disallowed and the exemptions contain the component.
        return allowedByDefault != exemptions.contains(component);
    }

    @VisibleForTesting
    int getRunningAppsChangedListenersSizeForTesting() {
        synchronized (mGenericWindowPolicyControllerLock) {
            return mRunningAppsChangedListeners.size();
        }
    }
}
+45 −29
Original line number Diff line number Diff line
@@ -35,7 +35,6 @@ import static android.companion.virtual.VirtualDeviceParams.POLICY_TYPE_RECENTS;

import android.annotation.NonNull;
import android.annotation.Nullable;
import android.annotation.RequiresPermission;
import android.annotation.StringRes;
import android.annotation.UserIdInt;
import android.app.Activity;
@@ -116,7 +115,6 @@ import com.android.internal.app.BlockedAppStreamingActivity;
import com.android.modules.expresslog.Counter;
import com.android.server.LocalServices;
import com.android.server.UiModeManagerInternal;
import com.android.server.companion.virtual.GenericWindowPolicyController.RunningAppsChangedListener;
import com.android.server.companion.virtual.audio.VirtualAudioController;
import com.android.server.companion.virtual.camera.VirtualCameraController;
import com.android.server.inputmethod.InputMethodManagerInternal;
@@ -129,10 +127,8 @@ import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.Set;
import java.util.function.Consumer;

final class VirtualDeviceImpl extends IVirtualDevice.Stub
        implements IBinder.DeathRecipient, RunningAppsChangedListener {
final class VirtualDeviceImpl extends IVirtualDevice.Stub implements IBinder.DeathRecipient {

    private static final String TAG = "VirtualDeviceImpl";

@@ -219,8 +215,12 @@ final class VirtualDeviceImpl extends IVirtualDevice.Stub
    private final PowerManager mPowerManager;
    @GuardedBy("mIntentInterceptors")
    private final Map<IBinder, IntentFilter> mIntentInterceptors = new ArrayMap<>();
    @NonNull
    private final Consumer<ArraySet<Integer>> mRunningAppsChangedCallback;

    // Mapping from displayId to all UIDs running on that display.
    @GuardedBy("mVirtualDeviceLock")
    private final SparseArray<ArraySet<Integer>> mRunningUids = new SparseArray<>();
    @GuardedBy("mVirtualDeviceLock")
    private ArraySet<Integer> mAllRunningUids = new ArraySet<>();

    // The default setting for showing the pointer on new displays.
    @GuardedBy("mVirtualDeviceLock")
@@ -378,6 +378,39 @@ final class VirtualDeviceImpl extends IVirtualDevice.Stub
                return hasInterceptedIntent;
            }
        }

        @SuppressWarnings("AndroidFrameworkRequiresPermission")
        @Override
        public void onRunningAppsChanged(int displayId, @NonNull ArraySet<Integer> runningUids) {
            final ArraySet<Integer> newAllUids;
            synchronized (mVirtualDeviceLock) {
                if (Objects.equals(runningUids, mRunningUids.get(displayId))) {
                    return;
                }
                if (runningUids.isEmpty()) {
                    mRunningUids.remove(displayId);
                } else {
                    mRunningUids.put(displayId, runningUids);
                }

                newAllUids = new ArraySet<>();
                for (int i = 0; i < mRunningUids.size(); i++) {
                    newAllUids.addAll(mRunningUids.valueAt(i));
                }
                if (newAllUids.equals(mAllRunningUids)) {
                    return;
                }
                mAllRunningUids = newAllUids;
            }

            mService.onRunningAppsChanged(mDeviceId, newAllUids);
            if (mVirtualAudioController != null) {
                mVirtualAudioController.onRunningAppsChanged(newAllUids);
            }
            if (mCameraAccessController != null) {
                mCameraAccessController.blockCameraAccessIfNeeded(newAllUids);
            }
        }
    }

    VirtualDeviceImpl(
@@ -392,7 +425,6 @@ final class VirtualDeviceImpl extends IVirtualDevice.Stub
            PendingTrampolineCallback pendingTrampolineCallback,
            IVirtualDeviceActivityListener activityListener,
            IVirtualDeviceSoundEffectListener soundEffectListener,
            Consumer<ArraySet<Integer>> runningAppsChangedCallback,
            VirtualDeviceParams params) {
        this(
                context,
@@ -407,7 +439,6 @@ final class VirtualDeviceImpl extends IVirtualDevice.Stub
                pendingTrampolineCallback,
                activityListener,
                soundEffectListener,
                runningAppsChangedCallback,
                params,
                DisplayManagerGlobal.getInstance(),
                isVirtualCameraEnabled()
@@ -433,7 +464,6 @@ final class VirtualDeviceImpl extends IVirtualDevice.Stub
            PendingTrampolineCallback pendingTrampolineCallback,
            IVirtualDeviceActivityListener activityListener,
            IVirtualDeviceSoundEffectListener soundEffectListener,
            Consumer<ArraySet<Integer>> runningAppsChangedCallback,
            VirtualDeviceParams params,
            DisplayManagerGlobal displayManager,
            VirtualCameraController virtualCameraController,
@@ -451,7 +481,6 @@ final class VirtualDeviceImpl extends IVirtualDevice.Stub
        mPendingTrampolineCallback = pendingTrampolineCallback;
        mActivityListener = activityListener;
        mSoundEffectListener = soundEffectListener;
        mRunningAppsChangedCallback = runningAppsChangedCallback;
        mOwnerUid = attributionSource.getUid();
        mDeviceId = deviceId;
        mAppToken = token;
@@ -876,15 +905,6 @@ final class VirtualDeviceImpl extends IVirtualDevice.Stub
        close();
    }

    @Override
    @RequiresPermission(android.Manifest.permission.CAMERA_INJECT_EXTERNAL_CAMERA)
    public void onRunningAppsChanged(ArraySet<Integer> runningUids) {
        if (mCameraAccessController != null) {
            mCameraAccessController.blockCameraAccessIfNeeded(runningUids);
        }
        mRunningAppsChangedCallback.accept(runningUids);
    }

    @VisibleForTesting
    VirtualAudioController getVirtualAudioControllerForTesting() {
        return mVirtualAudioController;
@@ -899,10 +919,7 @@ final class VirtualDeviceImpl extends IVirtualDevice.Stub
            checkDisplayOwnedByVirtualDeviceLocked(displayId);
            if (mVirtualAudioController == null) {
                mVirtualAudioController = new VirtualAudioController(mContext, mAttributionSource);
                GenericWindowPolicyController gwpc =
                        mVirtualDisplays.get(displayId).getWindowPolicyController();
                mVirtualAudioController.startListening(gwpc, routingCallback,
                        configChangedCallback);
                mVirtualAudioController.startListening(routingCallback, configChangedCallback);
            }
        }
    }
@@ -1387,7 +1404,6 @@ final class VirtualDeviceImpl extends IVirtualDevice.Stub
            showPointer = mDefaultShowPointerIcon;
        }
        displayWrapper.acquireWakeLock();
        gwpc.registerRunningAppsChangedListener(/* listener= */ this);

        Binder.withCleanCallingIdentity(() -> {
            mInputController.setMouseScalingEnabled(false, displayId);
@@ -1499,8 +1515,7 @@ final class VirtualDeviceImpl extends IVirtualDevice.Stub
     * This is callback invoked by VirtualDeviceManagerService when VirtualDisplay was released
     * by DisplayManager (most probably caused by someone calling VirtualDisplay.close()).
     * At this point, the display is already released, but we still need to release the
     * corresponding wakeLock and unregister the RunningAppsChangedListener from corresponding
     * WindowPolicyController.
     * corresponding wakeLock.
     *
     * Note that when the display is destroyed during VirtualDeviceImpl.close() call,
     * this callback won't be invoked because the display is removed from
@@ -1604,8 +1619,9 @@ final class VirtualDeviceImpl extends IVirtualDevice.Stub
     */
    private void releaseOwnedVirtualDisplayResources(VirtualDisplayWrapper virtualDisplayWrapper) {
        virtualDisplayWrapper.releaseWakeLock();
        virtualDisplayWrapper.getWindowPolicyController().unregisterRunningAppsChangedListener(
                this);
        // Notify the clients that nothing is running on this display anymore.
        mActivityListenerAdapter.onRunningAppsChanged(
                virtualDisplayWrapper.getDisplayId(), new ArraySet<>());
        // UiModeManagerService keeps all UI mode overrides in a map, so this call effectively
        // removes the entry for this display.
        mUiModeManagerInternal.setDisplayUiMode(
+37 −81
Original line number Diff line number Diff line
@@ -171,17 +171,18 @@ public class VirtualDeviceManagerService extends SystemService {
    private final RemoteCallbackList<IVirtualDeviceListener> mVirtualDeviceListeners =
            new RemoteCallbackList<>();

    /**
     * Mapping from device IDs to virtual devices.
     */
    @GuardedBy("mVirtualDeviceManagerLock")
    private final SparseArray<VirtualDeviceImpl> mVirtualDevices = new SparseArray<>();
    private final ArrayList<VirtualDeviceManagerInternal.AppsOnVirtualDeviceListener>
            mAppsOnVirtualDeviceListeners = new ArrayList<>();
    @GuardedBy("mVirtualDeviceManagerLock")
    private final ArrayList<Consumer<String>> mPersistentDeviceIdRemovedListeners =
            new ArrayList<>();

    /**
     * Mapping from device IDs to app UIDs running on the corresponding virtual device.
     * Mapping from device IDs to virtual devices.
     */
    @GuardedBy("mVirtualDeviceManagerLock")
    private final SparseArray<ArraySet<Integer>> mAppsOnVirtualDevices = new SparseArray<>();
    private final SparseArray<VirtualDeviceImpl> mVirtualDevices = new SparseArray<>();

    public VirtualDeviceManagerService(Context context) {
        super(context);
@@ -292,16 +293,31 @@ public class VirtualDeviceManagerService extends SystemService {
    }

    @VisibleForTesting
    void notifyRunningAppsChanged(int deviceId, ArraySet<Integer> uids) {
    void onRunningAppsChanged(int deviceId, @NonNull ArraySet<Integer> runningUids) {
        final List<VirtualDeviceManagerInternal.AppsOnVirtualDeviceListener> listeners;
        synchronized (mVirtualDeviceManagerLock) {
            if (!mVirtualDevices.contains(deviceId)) {
                Slog.e(TAG, "notifyRunningAppsChanged called for unknown deviceId:" + deviceId
                        + " (maybe it was recently closed?)");
                return;
            listeners = List.copyOf(mAppsOnVirtualDeviceListeners);
        }
            mAppsOnVirtualDevices.put(deviceId, uids);
        mHandler.post(() -> {
            for (int i = 0; i < listeners.size(); ++i) {
                listeners.get(i).onAppsRunningOnVirtualDeviceChanged(deviceId, runningUids);
            }
        mLocalService.onAppsOnVirtualDeviceChanged();
        });
    }

    @VisibleForTesting
    void onPersistentDeviceIdsRemoved(Set<String> removedPersistentDeviceIds) {
        final List<Consumer<String>> listeners;
        synchronized (mVirtualDeviceManagerLock) {
            listeners = List.copyOf(mPersistentDeviceIdRemovedListeners);
        }
        mHandler.post(() -> {
            for (String persistentDeviceId : removedPersistentDeviceIds) {
                for (int i = 0; i < listeners.size(); ++i) {
                    listeners.get(i).accept(persistentDeviceId);
                }
            }
        });
    }

    @VisibleForTesting
@@ -322,8 +338,6 @@ public class VirtualDeviceManagerService extends SystemService {
            if (!mVirtualDevices.contains(deviceId)) {
                return false;
            }

            mAppsOnVirtualDevices.remove(deviceId);
            mVirtualDevices.remove(deviceId);
        }

@@ -370,7 +384,7 @@ public class VirtualDeviceManagerService extends SystemService {
        }

        if (!removedPersistentDeviceIds.isEmpty()) {
            mLocalService.onPersistentDeviceIdsRemoved(removedPersistentDeviceIds);
            onPersistentDeviceIdsRemoved(removedPersistentDeviceIds);
        }
    }

@@ -496,12 +510,10 @@ public class VirtualDeviceManagerService extends SystemService {
                    getCameraAccessController(userHandle, params,
                            attributionSource.getPackageName());
            final int deviceId = sNextUniqueIndex.getAndIncrement();
            final Consumer<ArraySet<Integer>> runningAppsChangedCallback =
                    runningUids -> notifyRunningAppsChanged(deviceId, runningUids);
            VirtualDeviceImpl virtualDevice = new VirtualDeviceImpl(getContext(), associationInfo,
                    VirtualDeviceManagerService.this, mVirtualDeviceLog, token, attributionSource,
                    deviceId, cameraAccessController, mPendingTrampolineCallback, activityListener,
                    soundEffectListener, runningAppsChangedCallback, params);
                    soundEffectListener, params);
            Counter.logIncrement("virtual_devices.value_virtual_devices_created_count");

            synchronized (mVirtualDeviceManagerLock) {
@@ -733,15 +745,6 @@ public class VirtualDeviceManagerService extends SystemService {
    }

    private final class LocalService extends VirtualDeviceManagerInternal {
        @GuardedBy("mVirtualDeviceManagerLock")
        private final ArrayList<AppsOnVirtualDeviceListener> mAppsOnVirtualDeviceListeners =
                new ArrayList<>();
        @GuardedBy("mVirtualDeviceManagerLock")
        private final ArrayList<Consumer<String>> mPersistentDeviceIdRemovedListeners =
                new ArrayList<>();

        @GuardedBy("mVirtualDeviceManagerLock")
        private final ArraySet<Integer> mAllUidsOnVirtualDevice = new ArraySet<>();

        @Override
        public @NonNull VirtualDeviceManager.VirtualDevice createVirtualDevice(
@@ -808,50 +811,6 @@ public class VirtualDeviceManagerService extends SystemService {
            }
        }

        @Override
        public void onAppsOnVirtualDeviceChanged() {
            ArraySet<Integer> latestRunningUids = new ArraySet<>();
            final AppsOnVirtualDeviceListener[] listeners;
            synchronized (mVirtualDeviceManagerLock) {
                int size = mAppsOnVirtualDevices.size();
                for (int i = 0; i < size; i++) {
                    latestRunningUids.addAll(mAppsOnVirtualDevices.valueAt(i));
                }
                if (!mAllUidsOnVirtualDevice.equals(latestRunningUids)) {
                    mAllUidsOnVirtualDevice.clear();
                    mAllUidsOnVirtualDevice.addAll(latestRunningUids);
                    listeners =
                            mAppsOnVirtualDeviceListeners.toArray(
                                    new AppsOnVirtualDeviceListener[0]);
                } else {
                    listeners = null;
                }
            }
            if (listeners != null) {
                mHandler.post(() -> {
                    for (AppsOnVirtualDeviceListener listener : listeners) {
                        listener.onAppsOnAnyVirtualDeviceChanged(latestRunningUids);
                    }
                });
            }
        }

        @Override
        public void onPersistentDeviceIdsRemoved(Set<String> removedPersistentDeviceIds) {
            final List<Consumer<String>> persistentDeviceIdRemovedListeners;
            synchronized (mVirtualDeviceManagerLock) {
                persistentDeviceIdRemovedListeners = List.copyOf(
                        mPersistentDeviceIdRemovedListeners);
            }
            mHandler.post(() -> {
                for (String persistentDeviceId : removedPersistentDeviceIds) {
                    for (Consumer<String> listener : persistentDeviceIdRemovedListeners) {
                        listener.accept(persistentDeviceId);
                    }
                }
            });
        }

        @Override
        public void onAuthenticationPrompt(int uid) {
            ArrayList<VirtualDeviceImpl> virtualDevicesSnapshot = getVirtualDevicesSnapshot();
@@ -872,17 +831,14 @@ public class VirtualDeviceManagerService extends SystemService {
        @Nullable
        public LocaleList getPreferredLocaleListForUid(int uid) {
            // TODO: b/263188984 support the case where an app is running on multiple VDs
            VirtualDeviceImpl virtualDevice = null;
            synchronized (mVirtualDeviceManagerLock) {
                for (int i = 0; i < mAppsOnVirtualDevices.size(); i++) {
                    if (mAppsOnVirtualDevices.valueAt(i).contains(uid)) {
                        int deviceId = mAppsOnVirtualDevices.keyAt(i);
                        virtualDevice = mVirtualDevices.get(deviceId);
                        break;
                    }
            ArrayList<VirtualDeviceImpl> virtualDevicesSnapshot = getVirtualDevicesSnapshot();
            for (int i = 0; i < virtualDevicesSnapshot.size(); i++) {
                VirtualDeviceImpl virtualDevice = virtualDevicesSnapshot.get(i);
                if (virtualDevice.isAppRunningOnVirtualDevice(uid)) {
                    return virtualDevice.getDeviceLocaleList();
                }
            }
            return virtualDevice == null ? null : virtualDevice.getDeviceLocaleList();
            return null;
        }

        @Override
+16 −15

File changed.

Preview size limit exceeded, changes collapsed.

Loading