1 /* 2 * Copyright (C) 2019 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 package com.android.wm.shell.pip; 18 19 import android.app.RemoteAction; 20 import android.content.ComponentName; 21 import android.content.pm.ParceledListSlice; 22 import android.os.RemoteException; 23 import android.view.IPinnedTaskListener; 24 import android.view.WindowManagerGlobal; 25 26 import androidx.annotation.BinderThread; 27 28 import com.android.wm.shell.common.ShellExecutor; 29 30 import java.util.ArrayList; 31 32 /** 33 * PinnedStackListener that simply forwards all calls to each listener added via 34 * {@link #addListener}. This is necessary since calling 35 * {@link com.android.server.wm.WindowManagerService#registerPinnedTaskListener} replaces any 36 * previously set listener. 37 */ 38 public class PinnedStackListenerForwarder { 39 40 private final IPinnedTaskListener mListenerImpl = new PinnedTaskListenerImpl(); 41 private final ShellExecutor mMainExecutor; 42 private final ArrayList<PinnedTaskListener> mListeners = new ArrayList<>(); 43 PinnedStackListenerForwarder(ShellExecutor mainExecutor)44 public PinnedStackListenerForwarder(ShellExecutor mainExecutor) { 45 mMainExecutor = mainExecutor; 46 } 47 48 /** Adds a listener to receive updates from the WindowManagerService. */ addListener(PinnedTaskListener listener)49 public void addListener(PinnedTaskListener listener) { 50 mListeners.add(listener); 51 } 52 53 /** Removes a listener so it will no longer receive updates from the WindowManagerService. */ removeListener(PinnedTaskListener listener)54 public void removeListener(PinnedTaskListener listener) { 55 mListeners.remove(listener); 56 } 57 register(int displayId)58 public void register(int displayId) throws RemoteException { 59 WindowManagerGlobal.getWindowManagerService().registerPinnedTaskListener( 60 displayId, mListenerImpl); 61 } 62 onMovementBoundsChanged(boolean fromImeAdjustment)63 private void onMovementBoundsChanged(boolean fromImeAdjustment) { 64 for (PinnedTaskListener listener : mListeners) { 65 listener.onMovementBoundsChanged(fromImeAdjustment); 66 } 67 } 68 onImeVisibilityChanged(boolean imeVisible, int imeHeight)69 private void onImeVisibilityChanged(boolean imeVisible, int imeHeight) { 70 for (PinnedTaskListener listener : mListeners) { 71 listener.onImeVisibilityChanged(imeVisible, imeHeight); 72 } 73 } 74 onActionsChanged(ParceledListSlice<RemoteAction> actions)75 private void onActionsChanged(ParceledListSlice<RemoteAction> actions) { 76 for (PinnedTaskListener listener : mListeners) { 77 listener.onActionsChanged(actions); 78 } 79 } 80 onActivityHidden(ComponentName componentName)81 private void onActivityHidden(ComponentName componentName) { 82 for (PinnedTaskListener listener : mListeners) { 83 listener.onActivityHidden(componentName); 84 } 85 } 86 onAspectRatioChanged(float aspectRatio)87 private void onAspectRatioChanged(float aspectRatio) { 88 for (PinnedTaskListener listener : mListeners) { 89 listener.onAspectRatioChanged(aspectRatio); 90 } 91 } 92 93 @BinderThread 94 private class PinnedTaskListenerImpl extends IPinnedTaskListener.Stub { 95 @Override onMovementBoundsChanged(boolean fromImeAdjustment)96 public void onMovementBoundsChanged(boolean fromImeAdjustment) { 97 mMainExecutor.execute(() -> { 98 PinnedStackListenerForwarder.this.onMovementBoundsChanged(fromImeAdjustment); 99 }); 100 } 101 102 @Override onImeVisibilityChanged(boolean imeVisible, int imeHeight)103 public void onImeVisibilityChanged(boolean imeVisible, int imeHeight) { 104 mMainExecutor.execute(() -> { 105 PinnedStackListenerForwarder.this.onImeVisibilityChanged(imeVisible, imeHeight); 106 }); 107 } 108 109 @Override onActionsChanged(ParceledListSlice<RemoteAction> actions)110 public void onActionsChanged(ParceledListSlice<RemoteAction> actions) { 111 mMainExecutor.execute(() -> { 112 PinnedStackListenerForwarder.this.onActionsChanged(actions); 113 }); 114 } 115 116 @Override onActivityHidden(ComponentName componentName)117 public void onActivityHidden(ComponentName componentName) { 118 mMainExecutor.execute(() -> { 119 PinnedStackListenerForwarder.this.onActivityHidden(componentName); 120 }); 121 } 122 123 @Override onAspectRatioChanged(float aspectRatio)124 public void onAspectRatioChanged(float aspectRatio) { 125 mMainExecutor.execute(() -> { 126 PinnedStackListenerForwarder.this.onAspectRatioChanged(aspectRatio); 127 }); 128 } 129 } 130 131 /** 132 * A counterpart of {@link IPinnedTaskListener} with empty implementations. 133 * Subclasses can ignore those methods they do not intend to take action upon. 134 */ 135 public static class PinnedTaskListener { onMovementBoundsChanged(boolean fromImeAdjustment)136 public void onMovementBoundsChanged(boolean fromImeAdjustment) {} 137 onImeVisibilityChanged(boolean imeVisible, int imeHeight)138 public void onImeVisibilityChanged(boolean imeVisible, int imeHeight) {} 139 onActionsChanged(ParceledListSlice<RemoteAction> actions)140 public void onActionsChanged(ParceledListSlice<RemoteAction> actions) {} 141 onActivityHidden(ComponentName componentName)142 public void onActivityHidden(ComponentName componentName) {} 143 onAspectRatioChanged(float aspectRatio)144 public void onAspectRatioChanged(float aspectRatio) {} 145 } 146 } 147