diff options
| author | 2021-11-03 03:04:18 +0000 | |
|---|---|---|
| committer | 2021-11-03 03:04:18 +0000 | |
| commit | 3e90f3b5be9dbc36846b78601d6d5b0a48e28ce7 (patch) | |
| tree | ef88abeef1d26797ae2c47a0cda9fcdf5f5ac4bd | |
| parent | 43f59bb11b9cc930f7812626d1cb9cf2d757f7bf (diff) | |
| parent | 9f7ea0a38fd82ef464d998273f772245b67f0ff9 (diff) | |
Merge "Abstract out common code for managing a single instance remote callback" into sc-v2-dev
7 files changed, 189 insertions, 156 deletions
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/common/SingleInstanceRemoteListener.java b/libs/WindowManager/Shell/src/com/android/wm/shell/common/SingleInstanceRemoteListener.java new file mode 100644 index 000000000000..b77ac8a2b951 --- /dev/null +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/common/SingleInstanceRemoteListener.java @@ -0,0 +1,123 @@ +/* + * Copyright (C) 2021 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.wm.shell.common; + +import android.os.IBinder; +import android.os.IInterface; +import android.os.RemoteException; +import android.util.Slog; + +import androidx.annotation.BinderThread; + +import java.util.function.Consumer; + +/** + * Manages the lifecycle of a single instance of a remote listener, including the clean up if the + * remote process dies. All calls on this class should happen on the main shell thread. + * + * @param <C> The controller (must be RemoteCallable) + * @param <L> The remote listener interface type + */ +public class SingleInstanceRemoteListener<C extends RemoteCallable, L extends IInterface> { + private static final String TAG = SingleInstanceRemoteListener.class.getSimpleName(); + + /** + * Simple callable interface that throws a remote exception. + */ + public interface RemoteCall<L> { + void accept(L l) throws RemoteException; + } + + private final C mCallableController; + private final Consumer<C> mOnRegisterCallback; + private final Consumer<C> mOnUnregisterCallback; + + L mListener; + + private final IBinder.DeathRecipient mListenerDeathRecipient = + new IBinder.DeathRecipient() { + @Override + @BinderThread + public void binderDied() { + final C callableController = mCallableController; + mCallableController.getRemoteCallExecutor().execute(() -> { + mListener = null; + mOnUnregisterCallback.accept(callableController); + }); + } + }; + + /** + * @param onRegisterCallback Callback when register() is called (same thread) + * @param onUnregisterCallback Callback when unregister() is called (same thread as unregister() + * or the callableController.getRemoteCallbackExecutor() thread) + */ + public SingleInstanceRemoteListener(C callableController, + Consumer<C> onRegisterCallback, + Consumer<C> onUnregisterCallback) { + mCallableController = callableController; + mOnRegisterCallback = onRegisterCallback; + mOnUnregisterCallback = onUnregisterCallback; + } + + /** + * Registers this listener, storing a reference to it and calls the provided method in the + * constructor. + */ + public void register(L listener) { + if (mListener != null) { + mListener.asBinder().unlinkToDeath(mListenerDeathRecipient, 0 /* flags */); + } + if (listener != null) { + try { + listener.asBinder().linkToDeath(mListenerDeathRecipient, 0 /* flags */); + } catch (RemoteException e) { + Slog.e(TAG, "Failed to link to death"); + return; + } + } + mListener = listener; + mOnRegisterCallback.accept(mCallableController); + } + + /** + * Unregisters this listener, removing all references to it and calls the provided method in the + * constructor. + */ + public void unregister() { + if (mListener != null) { + mListener.asBinder().unlinkToDeath(mListenerDeathRecipient, 0 /* flags */); + } + mListener = null; + mOnUnregisterCallback.accept(mCallableController); + } + + /** + * Safely wraps a call to the remote listener. + */ + public void call(RemoteCall<L> handler) { + if (mListener == null) { + Slog.e(TAG, "Failed remote call on null listener"); + return; + } + try { + handler.accept(mListener); + } catch (RemoteException e) { + Slog.e(TAG, "Failed remote call", e); + } + } +}
\ No newline at end of file diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/pip/phone/PipController.java b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/phone/PipController.java index 8e5c5c52cb3f..51eea370b98d 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/pip/phone/PipController.java +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/phone/PipController.java @@ -43,7 +43,6 @@ import android.content.pm.ActivityInfo; import android.content.pm.ParceledListSlice; import android.content.res.Configuration; import android.graphics.Rect; -import android.os.IBinder; import android.os.RemoteException; import android.os.UserHandle; import android.os.UserManager; @@ -69,6 +68,7 @@ import com.android.wm.shell.common.DisplayController; import com.android.wm.shell.common.DisplayLayout; import com.android.wm.shell.common.RemoteCallable; import com.android.wm.shell.common.ShellExecutor; +import com.android.wm.shell.common.SingleInstanceRemoteListener; import com.android.wm.shell.common.TaskStackListenerCallback; import com.android.wm.shell.common.TaskStackListenerImpl; import com.android.wm.shell.onehanded.OneHandedController; @@ -117,13 +117,28 @@ public class PipController implements PipTransitionController.PipTransitionCallb private final Rect mTmpInsetBounds = new Rect(); private boolean mIsInFixedRotation; - private IPipAnimationListener mPinnedStackAnimationRecentsCallback; + private PipAnimationListener mPinnedStackAnimationRecentsCallback; protected PhonePipMenuController mMenuController; protected PipTaskOrganizer mPipTaskOrganizer; protected PinnedStackListenerForwarder.PinnedTaskListener mPinnedTaskListener = new PipControllerPinnedTaskListener(); + private interface PipAnimationListener { + /** + * Notifies the listener that the Pip animation is started. + */ + void onPipAnimationStarted(); + + /** + * Notifies the listener about PiP round corner radius changes. + * Listener can expect an immediate callback the first time they attach. + * + * @param cornerRadius the pixel value of the corner radius, zero means it's disabled. + */ + void onPipCornerRadiusChanged(int cornerRadius); + } + /** * Handler for display rotation changes. */ @@ -551,7 +566,7 @@ public class PipController implements PipTransitionController.PipTransitionCallb animationType == PipAnimationController.ANIM_TYPE_BOUNDS); } - private void setPinnedStackAnimationListener(IPipAnimationListener callback) { + private void setPinnedStackAnimationListener(PipAnimationListener callback) { mPinnedStackAnimationRecentsCallback = callback; onPipCornerRadiusChanged(); } @@ -560,11 +575,7 @@ public class PipController implements PipTransitionController.PipTransitionCallb if (mPinnedStackAnimationRecentsCallback != null) { final int cornerRadius = mContext.getResources().getDimensionPixelSize(R.dimen.pip_corner_radius); - try { - mPinnedStackAnimationRecentsCallback.onPipCornerRadiusChanged(cornerRadius); - } catch (RemoteException e) { - Log.e(TAG, "Failed to call onPipCornerRadiusChanged", e); - } + mPinnedStackAnimationRecentsCallback.onPipCornerRadiusChanged(cornerRadius); } } @@ -623,11 +634,7 @@ public class PipController implements PipTransitionController.PipTransitionCallb // Disable touches while the animation is running mTouchHandler.setTouchEnabled(false); if (mPinnedStackAnimationRecentsCallback != null) { - try { - mPinnedStackAnimationRecentsCallback.onPipAnimationStarted(); - } catch (RemoteException e) { - Log.e(TAG, "Failed to call onPinnedStackAnimationStarted()", e); - } + mPinnedStackAnimationRecentsCallback.onPipAnimationStarted(); } } @@ -866,22 +873,25 @@ public class PipController implements PipTransitionController.PipTransitionCallb @BinderThread private static class IPipImpl extends IPip.Stub { private PipController mController; - private IPipAnimationListener mListener; - private final IBinder.DeathRecipient mListenerDeathRecipient = - new IBinder.DeathRecipient() { - @Override - @BinderThread - public void binderDied() { - final PipController controller = mController; - controller.getRemoteCallExecutor().execute(() -> { - mListener = null; - controller.setPinnedStackAnimationListener(null); - }); - } - }; + private final SingleInstanceRemoteListener<PipController, + IPipAnimationListener> mListener; + private final PipAnimationListener mPipAnimationListener = new PipAnimationListener() { + @Override + public void onPipAnimationStarted() { + mListener.call(l -> l.onPipAnimationStarted()); + } + + @Override + public void onPipCornerRadiusChanged(int cornerRadius) { + mListener.call(l -> l.onPipCornerRadiusChanged(cornerRadius)); + } + }; IPipImpl(PipController controller) { mController = controller; + mListener = new SingleInstanceRemoteListener<>(mController, + c -> c.setPinnedStackAnimationListener(mPipAnimationListener), + c -> c.setPinnedStackAnimationListener(null)); } /** @@ -925,23 +935,11 @@ public class PipController implements PipTransitionController.PipTransitionCallb public void setPinnedStackAnimationListener(IPipAnimationListener listener) { executeRemoteCallWithTaskPermission(mController, "setPinnedStackAnimationListener", (controller) -> { - if (mListener != null) { - // Reset the old death recipient - mListener.asBinder().unlinkToDeath(mListenerDeathRecipient, - 0 /* flags */); - } if (listener != null) { - // Register the death recipient for the new listener to clear the listener - try { - listener.asBinder().linkToDeath(mListenerDeathRecipient, - 0 /* flags */); - } catch (RemoteException e) { - Slog.e(TAG, "Failed to link to death"); - return; - } + mListener.register(listener); + } else { + mListener.unregister(); } - mListener = listener; - controller.setPinnedStackAnimationListener(listener); }); } } diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/SplitScreenController.java b/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/SplitScreenController.java index 36f140614deb..14a6574e51a7 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/SplitScreenController.java +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/SplitScreenController.java @@ -34,7 +34,6 @@ import android.content.Intent; import android.content.pm.LauncherApps; import android.graphics.Rect; import android.os.Bundle; -import android.os.IBinder; import android.os.RemoteException; import android.os.UserHandle; import android.util.ArrayMap; @@ -61,6 +60,7 @@ import com.android.wm.shell.common.DisplayImeController; import com.android.wm.shell.common.DisplayInsetsController; import com.android.wm.shell.common.RemoteCallable; import com.android.wm.shell.common.ShellExecutor; +import com.android.wm.shell.common.SingleInstanceRemoteListener; import com.android.wm.shell.common.SyncTransactionQueue; import com.android.wm.shell.common.TransactionPool; import com.android.wm.shell.common.annotations.ExternalThread; @@ -433,46 +433,26 @@ public class SplitScreenController implements DragAndDropPolicy.Starter, @BinderThread private static class ISplitScreenImpl extends ISplitScreen.Stub { private SplitScreenController mController; - private ISplitScreenListener mListener; + private final SingleInstanceRemoteListener<SplitScreenController, + ISplitScreenListener> mListener; private final SplitScreen.SplitScreenListener mSplitScreenListener = new SplitScreen.SplitScreenListener() { @Override public void onStagePositionChanged(int stage, int position) { - try { - if (mListener != null) { - mListener.onStagePositionChanged(stage, position); - } - } catch (RemoteException e) { - Slog.e(TAG, "onStagePositionChanged", e); - } + mListener.call(l -> l.onStagePositionChanged(stage, position)); } @Override public void onTaskStageChanged(int taskId, int stage, boolean visible) { - try { - if (mListener != null) { - mListener.onTaskStageChanged(taskId, stage, visible); - } - } catch (RemoteException e) { - Slog.e(TAG, "onTaskStageChanged", e); - } - } - }; - private final IBinder.DeathRecipient mListenerDeathRecipient = - new IBinder.DeathRecipient() { - @Override - @BinderThread - public void binderDied() { - final SplitScreenController controller = mController; - controller.getRemoteCallExecutor().execute(() -> { - mListener = null; - controller.unregisterSplitScreenListener(mSplitScreenListener); - }); + mListener.call(l -> l.onTaskStageChanged(taskId, stage, visible)); } }; public ISplitScreenImpl(SplitScreenController controller) { mController = controller; + mListener = new SingleInstanceRemoteListener<>(controller, + c -> c.registerSplitScreenListener(mSplitScreenListener), + c -> c.unregisterSplitScreenListener(mSplitScreenListener)); } /** @@ -485,36 +465,13 @@ public class SplitScreenController implements DragAndDropPolicy.Starter, @Override public void registerSplitScreenListener(ISplitScreenListener listener) { executeRemoteCallWithTaskPermission(mController, "registerSplitScreenListener", - (controller) -> { - if (mListener != null) { - mListener.asBinder().unlinkToDeath(mListenerDeathRecipient, - 0 /* flags */); - } - if (listener != null) { - try { - listener.asBinder().linkToDeath(mListenerDeathRecipient, - 0 /* flags */); - } catch (RemoteException e) { - Slog.e(TAG, "Failed to link to death"); - return; - } - } - mListener = listener; - controller.registerSplitScreenListener(mSplitScreenListener); - }); + (controller) -> mListener.register(listener)); } @Override public void unregisterSplitScreenListener(ISplitScreenListener listener) { executeRemoteCallWithTaskPermission(mController, "unregisterSplitScreenListener", - (controller) -> { - if (mListener != null) { - mListener.asBinder().unlinkToDeath(mListenerDeathRecipient, - 0 /* flags */); - } - mListener = null; - controller.unregisterSplitScreenListener(mSplitScreenListener); - }); + (controller) -> mListener.unregister()); } @Override diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/startingsurface/StartingWindowController.java b/libs/WindowManager/Shell/src/com/android/wm/shell/startingsurface/StartingWindowController.java index a86e07a5602d..e98a3e87c0b7 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/startingsurface/StartingWindowController.java +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/startingsurface/StartingWindowController.java @@ -46,6 +46,7 @@ import com.android.internal.util.function.TriConsumer; import com.android.launcher3.icons.IconProvider; import com.android.wm.shell.common.RemoteCallable; import com.android.wm.shell.common.ShellExecutor; +import com.android.wm.shell.common.SingleInstanceRemoteListener; import com.android.wm.shell.common.TransactionPool; /** @@ -237,24 +238,19 @@ public class StartingWindowController implements RemoteCallable<StartingWindowCo @BinderThread private static class IStartingWindowImpl extends IStartingWindow.Stub { private StartingWindowController mController; - private IStartingWindowListener mListener; + private SingleInstanceRemoteListener<StartingWindowController, + IStartingWindowListener> mListener; private final TriConsumer<Integer, Integer, Integer> mStartingWindowListener = - this::notifyIStartingWindowListener; - private final IBinder.DeathRecipient mListenerDeathRecipient = - new IBinder.DeathRecipient() { - @Override - @BinderThread - public void binderDied() { - final StartingWindowController controller = mController; - controller.getRemoteCallExecutor().execute(() -> { - mListener = null; - controller.setStartingWindowListener(null); - }); - } + (taskId, supportedType, startingWindowBackgroundColor) -> { + mListener.call(l -> l.onTaskLaunching(taskId, supportedType, + startingWindowBackgroundColor)); }; public IStartingWindowImpl(StartingWindowController controller) { mController = controller; + mListener = new SingleInstanceRemoteListener<>(controller, + c -> c.setStartingWindowListener(mStartingWindowListener), + c -> c.setStartingWindowListener(null)); } /** @@ -268,36 +264,12 @@ public class StartingWindowController implements RemoteCallable<StartingWindowCo public void setStartingWindowListener(IStartingWindowListener listener) { executeRemoteCallWithTaskPermission(mController, "setStartingWindowListener", (controller) -> { - if (mListener != null) { - // Reset the old death recipient - mListener.asBinder().unlinkToDeath(mListenerDeathRecipient, - 0 /* flags */); - } if (listener != null) { - try { - listener.asBinder().linkToDeath(mListenerDeathRecipient, - 0 /* flags */); - } catch (RemoteException e) { - Slog.e(TAG, "Failed to link to death"); - return; - } + mListener.register(listener); + } else { + mListener.unregister(); } - mListener = listener; - controller.setStartingWindowListener(mStartingWindowListener); }); } - - private void notifyIStartingWindowListener(int taskId, int supportedType, - int startingWindowBackgroundColor) { - if (mListener == null) { - return; - } - - try { - mListener.onTaskLaunching(taskId, supportedType, startingWindowBackgroundColor); - } catch (RemoteException e) { - Slog.e(TAG, "Failed to notify task launching", e); - } - } } } diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/transition/ShellTransitions.java b/libs/WindowManager/Shell/src/com/android/wm/shell/transition/ShellTransitions.java index 802d25f66340..b34049d4ec42 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/transition/ShellTransitions.java +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/transition/ShellTransitions.java @@ -38,11 +38,11 @@ public interface ShellTransitions { /** * Registers a remote transition. */ - void registerRemote(@NonNull TransitionFilter filter, - @NonNull RemoteTransition remoteTransition); + default void registerRemote(@NonNull TransitionFilter filter, + @NonNull RemoteTransition remoteTransition) {} /** * Unregisters a remote transition. */ - void unregisterRemote(@NonNull RemoteTransition remoteTransition); + default void unregisterRemote(@NonNull RemoteTransition remoteTransition) {} } diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/transition/Transitions.java b/libs/WindowManager/Shell/src/com/android/wm/shell/transition/Transitions.java index c36983189a71..804e449decf8 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/transition/Transitions.java +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/transition/Transitions.java @@ -171,24 +171,6 @@ public class Transitions implements RemoteCallable<Transitions> { } } - /** Create an empty/non-registering transitions object for system-ui tests. */ - @VisibleForTesting - public static ShellTransitions createEmptyForTesting() { - return new ShellTransitions() { - @Override - public void registerRemote(@androidx.annotation.NonNull TransitionFilter filter, - @androidx.annotation.NonNull RemoteTransition remoteTransition) { - // Do nothing - } - - @Override - public void unregisterRemote( - @androidx.annotation.NonNull RemoteTransition remoteTransition) { - // Do nothing - } - }; - } - /** Register this transition handler with Core */ public void register(ShellTaskOrganizer taskOrganizer) { if (mPlayerImpl == null) return; diff --git a/packages/SystemUI/src/com/android/systemui/SystemUIFactory.java b/packages/SystemUI/src/com/android/systemui/SystemUIFactory.java index c64f416f9672..f4f99b7b8d39 100644 --- a/packages/SystemUI/src/com/android/systemui/SystemUIFactory.java +++ b/packages/SystemUI/src/com/android/systemui/SystemUIFactory.java @@ -30,6 +30,7 @@ import com.android.systemui.dagger.SysUIComponent; import com.android.systemui.dagger.WMComponent; import com.android.systemui.navigationbar.gestural.BackGestureTfClassifierProvider; import com.android.systemui.screenshot.ScreenshotNotificationSmartActionsProvider; +import com.android.wm.shell.transition.ShellTransitions; import com.android.wm.shell.transition.Transitions; import java.util.Optional; @@ -133,7 +134,7 @@ public class SystemUIFactory { .setShellCommandHandler(Optional.ofNullable(null)) .setAppPairs(Optional.ofNullable(null)) .setTaskViewFactory(Optional.ofNullable(null)) - .setTransitions(Transitions.createEmptyForTesting()) + .setTransitions(new ShellTransitions() {}) .setDisplayAreaHelper(Optional.ofNullable(null)) .setStartingSurface(Optional.ofNullable(null)) .setTaskSurfaceHelper(Optional.ofNullable(null)); |