summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
author Winson Chung <winsonc@google.com> 2021-11-03 03:04:18 +0000
committer Android (Google) Code Review <android-gerrit@google.com> 2021-11-03 03:04:18 +0000
commit3e90f3b5be9dbc36846b78601d6d5b0a48e28ce7 (patch)
treeef88abeef1d26797ae2c47a0cda9fcdf5f5ac4bd
parent43f59bb11b9cc930f7812626d1cb9cf2d757f7bf (diff)
parent9f7ea0a38fd82ef464d998273f772245b67f0ff9 (diff)
Merge "Abstract out common code for managing a single instance remote callback" into sc-v2-dev
-rw-r--r--libs/WindowManager/Shell/src/com/android/wm/shell/common/SingleInstanceRemoteListener.java123
-rw-r--r--libs/WindowManager/Shell/src/com/android/wm/shell/pip/phone/PipController.java80
-rw-r--r--libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/SplitScreenController.java63
-rw-r--r--libs/WindowManager/Shell/src/com/android/wm/shell/startingsurface/StartingWindowController.java52
-rw-r--r--libs/WindowManager/Shell/src/com/android/wm/shell/transition/ShellTransitions.java6
-rw-r--r--libs/WindowManager/Shell/src/com/android/wm/shell/transition/Transitions.java18
-rw-r--r--packages/SystemUI/src/com/android/systemui/SystemUIFactory.java3
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));