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.content.ComponentName; 20 import android.os.RemoteException; 21 import android.view.IPinnedTaskListener; 22 import android.view.WindowManagerGlobal; 23 24 import androidx.annotation.BinderThread; 25 26 import com.android.wm.shell.common.ShellExecutor; 27 28 import java.util.ArrayList; 29 30 /** 31 * PinnedStackListener that simply forwards all calls to each listener added via 32 * {@link #addListener}. This is necessary since calling 33 * {@link com.android.server.wm.WindowManagerService#registerPinnedTaskListener} replaces any 34 * previously set listener. 35 */ 36 public class PinnedStackListenerForwarder { 37 38 private final IPinnedTaskListener mListenerImpl = new PinnedTaskListenerImpl(); 39 private final ShellExecutor mMainExecutor; 40 private final ArrayList<PinnedTaskListener> mListeners = new ArrayList<>(); 41 PinnedStackListenerForwarder(ShellExecutor mainExecutor)42 public PinnedStackListenerForwarder(ShellExecutor mainExecutor) { 43 mMainExecutor = mainExecutor; 44 } 45 46 /** Adds a listener to receive updates from the WindowManagerService. */ addListener(PinnedTaskListener listener)47 public void addListener(PinnedTaskListener listener) { 48 mListeners.add(listener); 49 } 50 51 /** Removes a listener so it will no longer receive updates from the WindowManagerService. */ removeListener(PinnedTaskListener listener)52 public void removeListener(PinnedTaskListener listener) { 53 mListeners.remove(listener); 54 } 55 register(int displayId)56 public void register(int displayId) throws RemoteException { 57 WindowManagerGlobal.getWindowManagerService().registerPinnedTaskListener( 58 displayId, mListenerImpl); 59 } 60 onMovementBoundsChanged(boolean fromImeAdjustment)61 private void onMovementBoundsChanged(boolean fromImeAdjustment) { 62 for (PinnedTaskListener listener : mListeners) { 63 listener.onMovementBoundsChanged(fromImeAdjustment); 64 } 65 } 66 onImeVisibilityChanged(boolean imeVisible, int imeHeight)67 private void onImeVisibilityChanged(boolean imeVisible, int imeHeight) { 68 for (PinnedTaskListener listener : mListeners) { 69 listener.onImeVisibilityChanged(imeVisible, imeHeight); 70 } 71 } 72 onActivityHidden(ComponentName componentName)73 private void onActivityHidden(ComponentName componentName) { 74 for (PinnedTaskListener listener : mListeners) { 75 listener.onActivityHidden(componentName); 76 } 77 } 78 79 @BinderThread 80 private class PinnedTaskListenerImpl extends IPinnedTaskListener.Stub { 81 @Override onMovementBoundsChanged(boolean fromImeAdjustment)82 public void onMovementBoundsChanged(boolean fromImeAdjustment) { 83 mMainExecutor.execute(() -> { 84 PinnedStackListenerForwarder.this.onMovementBoundsChanged(fromImeAdjustment); 85 }); 86 } 87 88 @Override onImeVisibilityChanged(boolean imeVisible, int imeHeight)89 public void onImeVisibilityChanged(boolean imeVisible, int imeHeight) { 90 mMainExecutor.execute(() -> { 91 PinnedStackListenerForwarder.this.onImeVisibilityChanged(imeVisible, imeHeight); 92 }); 93 } 94 95 @Override onActivityHidden(ComponentName componentName)96 public void onActivityHidden(ComponentName componentName) { 97 mMainExecutor.execute(() -> { 98 PinnedStackListenerForwarder.this.onActivityHidden(componentName); 99 }); 100 } 101 } 102 103 /** 104 * A counterpart of {@link IPinnedTaskListener} with empty implementations. 105 * Subclasses can ignore those methods they do not intend to take action upon. 106 */ 107 public static class PinnedTaskListener { onMovementBoundsChanged(boolean fromImeAdjustment)108 public void onMovementBoundsChanged(boolean fromImeAdjustment) {} 109 onImeVisibilityChanged(boolean imeVisible, int imeHeight)110 public void onImeVisibilityChanged(boolean imeVisible, int imeHeight) {} 111 onActivityHidden(ComponentName componentName)112 public void onActivityHidden(ComponentName componentName) {} 113 } 114 } 115