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

Commit 911c53c3 authored by Jan Sebechlebsky's avatar Jan Sebechlebsky
Browse files

Synchronize access to listeners in VDM.

Listeners are accessed from Binder thread when dispatching the
events, however registering / unregistering listeners is done
from different thread - this cl adds locks to prevent race condition
while unregistering / registering listeners while callback is being
dispatched.

Bug: 263231559
Test: atest CtsVirtualDevicesTestCases
Change-Id: I236dddcb25e406d5281a85da7d90bc13159b5a1f
parent babc0ff0
Loading
Loading
Loading
Loading
+35 −16
Original line number Diff line number Diff line
@@ -361,8 +361,12 @@ public final class VirtualDeviceManager {
        private final Context mContext;
        private final IVirtualDeviceManager mService;
        private final IVirtualDevice mVirtualDevice;
        private final Object mActivityListenersLock = new Object();
        @GuardedBy("mActivityListenersLock")
        private final ArrayMap<ActivityListener, ActivityListenerDelegate> mActivityListeners =
                new ArrayMap<>();
        private final Object mIntentInterceptorListenersLock = new Object();
        @GuardedBy("mIntentInterceptorListenersLock")
        private final ArrayMap<IntentInterceptorCallback,
                     VirtualIntentInterceptorDelegate> mIntentInterceptorListeners =
                new ArrayMap<>();
@@ -377,10 +381,12 @@ public final class VirtualDeviceManager {
                    public void onTopActivityChanged(int displayId, ComponentName topActivity) {
                        final long token = Binder.clearCallingIdentity();
                        try {
                            synchronized (mActivityListenersLock) {
                                for (int i = 0; i < mActivityListeners.size(); i++) {
                                    mActivityListeners.valueAt(i)
                                            .onTopActivityChanged(displayId, topActivity);
                                }
                            }
                        } finally {
                            Binder.restoreCallingIdentity(token);
                        }
@@ -390,9 +396,11 @@ public final class VirtualDeviceManager {
                    public void onDisplayEmpty(int displayId) {
                        final long token = Binder.clearCallingIdentity();
                        try {
                            synchronized (mActivityListenersLock) {
                                for (int i = 0; i < mActivityListeners.size(); i++) {
                                    mActivityListeners.valueAt(i).onDisplayEmpty(displayId);
                                }
                            }
                        } finally {
                            Binder.restoreCallingIdentity(token);
                        }
@@ -960,7 +968,11 @@ public final class VirtualDeviceManager {
         */
        public void addActivityListener(
                @CallbackExecutor @NonNull Executor executor, @NonNull ActivityListener listener) {
            mActivityListeners.put(listener, new ActivityListenerDelegate(listener, executor));
            final ActivityListenerDelegate delegate = new ActivityListenerDelegate(
                    Objects.requireNonNull(listener), Objects.requireNonNull(executor));
            synchronized (mActivityListenersLock) {
                mActivityListeners.put(listener, delegate);
            }
        }

        /**
@@ -971,7 +983,9 @@ public final class VirtualDeviceManager {
         * @see #addActivityListener(Executor, ActivityListener)
         */
        public void removeActivityListener(@NonNull ActivityListener listener) {
            mActivityListeners.remove(listener);
            synchronized (mActivityListenersLock) {
                mActivityListeners.remove(Objects.requireNonNull(listener));
            }
        }

        /**
@@ -999,7 +1013,7 @@ public final class VirtualDeviceManager {
         */
        public void removeSoundEffectListener(@NonNull SoundEffectListener soundEffectListener) {
            synchronized (mSoundEffectListenersLock) {
                mSoundEffectListeners.remove(soundEffectListener);
                mSoundEffectListeners.remove(Objects.requireNonNull(soundEffectListener));
            }
        }

@@ -1029,8 +1043,10 @@ public final class VirtualDeviceManager {
            } catch (RemoteException e) {
                throw e.rethrowFromSystemServer();
            }
            synchronized (mIntentInterceptorListenersLock) {
                mIntentInterceptorListeners.put(interceptorCallback, delegate);
            }
        }

        /**
         * Unregisters the intent interceptorCallback previously registered with
@@ -1040,14 +1056,17 @@ public final class VirtualDeviceManager {
        public void unregisterIntentInterceptor(
                    @NonNull IntentInterceptorCallback interceptorCallback) {
            Objects.requireNonNull(interceptorCallback);
            final VirtualIntentInterceptorDelegate delegate =
                    mIntentInterceptorListeners.get(interceptorCallback);
            final VirtualIntentInterceptorDelegate delegate;
            synchronized (mIntentInterceptorListenersLock) {
                delegate = mIntentInterceptorListeners.remove(interceptorCallback);
            }
            if (delegate != null) {
                try {
                    mVirtualDevice.unregisterIntentInterceptor(delegate);
                } catch (RemoteException e) {
                    throw e.rethrowFromSystemServer();
                }
            mIntentInterceptorListeners.remove(interceptorCallback);
            }
        }
    }