blob: 5a2484735fb9cf5f2571b02c846301af0a61e162 [file] [log] [blame]
Vishnu Nair5cf253192019-11-07 15:33:20 -08001/*
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
17package com.android.server.wm;
18
Vishnu Nair5cf253192019-11-07 15:33:20 -080019
Vishnu Nairfca78472020-03-09 15:34:47 -070020import static com.android.server.wm.WindowManagerDebugConfig.TAG_WITH_CLASS_NAME;
21import static com.android.server.wm.WindowManagerDebugConfig.TAG_WM;
22
Vishnu Nairddbd2512019-11-12 14:39:43 -080023import android.annotation.Nullable;
Vishnu Nair5cf253192019-11-07 15:33:20 -080024import android.os.IBinder;
25import android.os.RemoteException;
Evan Rosky680377e2020-01-10 19:12:10 -080026import android.os.UserHandle;
Vishnu Nair5cf253192019-11-07 15:33:20 -080027import android.util.ArrayMap;
Vishnu Nairfca78472020-03-09 15:34:47 -070028import android.util.Slog;
Vishnu Nair5cf253192019-11-07 15:33:20 -080029import android.view.IWindow;
Evan Rosky680377e2020-01-10 19:12:10 -080030import android.view.InputApplicationHandle;
arthurhung03d65a72020-04-28 09:19:24 +080031import android.view.InputChannel;
Vishnu Nair5cf253192019-11-07 15:33:20 -080032
33/**
34 * Keeps track of embedded windows.
35 *
36 * If the embedded window does not receive input then Window Manager does not keep track of it.
37 * But if they do receive input, we keep track of the calling PID to blame the right app and
38 * the host window to send pointerDownOutsideFocus.
39 */
40class EmbeddedWindowController {
Vishnu Nairfca78472020-03-09 15:34:47 -070041 private static final String TAG = TAG_WITH_CLASS_NAME ? "EmbeddedWindowController" : TAG_WM;
Vishnu Nair5cf253192019-11-07 15:33:20 -080042 /* maps input token to an embedded window */
43 private ArrayMap<IBinder /*input token */, EmbeddedWindow> mWindows = new ArrayMap<>();
Vishnu Nairfca78472020-03-09 15:34:47 -070044 private final Object mGlobalLock;
45 private final ActivityTaskManagerService mAtmService;
Vishnu Nair5cf253192019-11-07 15:33:20 -080046
Vishnu Nairfca78472020-03-09 15:34:47 -070047 EmbeddedWindowController(ActivityTaskManagerService atmService) {
48 mAtmService = atmService;
49 mGlobalLock = atmService.getGlobalLock();
Vishnu Nair5cf253192019-11-07 15:33:20 -080050 }
51
Vishnu Nairddbd2512019-11-12 14:39:43 -080052 /**
53 * Adds a new embedded window.
54 *
55 * @param inputToken input channel token passed in by the embedding process when it requests
56 * the server to add an input channel to the embedded surface.
Vishnu Nairfca78472020-03-09 15:34:47 -070057 * @param window An {@link EmbeddedWindow} object to add to this controller.
Vishnu Nairddbd2512019-11-12 14:39:43 -080058 */
Vishnu Nairfca78472020-03-09 15:34:47 -070059 void add(IBinder inputToken, EmbeddedWindow window) {
Vishnu Nair5cf253192019-11-07 15:33:20 -080060 try {
Vishnu Nairfca78472020-03-09 15:34:47 -070061 mWindows.put(inputToken, window);
62 updateProcessController(window);
63 window.mClient.asBinder().linkToDeath(()-> {
64 synchronized (mGlobalLock) {
Vishnu Nair5cf253192019-11-07 15:33:20 -080065 mWindows.remove(inputToken);
66 }
67 }, 0);
68 } catch (RemoteException e) {
69 // The caller has died, remove from the map
70 mWindows.remove(inputToken);
71 }
72 }
73
Vishnu Nairfca78472020-03-09 15:34:47 -070074 /**
75 * Track the host activity in the embedding process so we can determine if the
76 * process is currently showing any UI to the user.
77 */
78 private void updateProcessController(EmbeddedWindow window) {
79 if (window.mHostActivityRecord == null) {
80 return;
81 }
82 final WindowProcessController processController =
83 mAtmService.getProcessController(window.mOwnerPid, window.mOwnerUid);
84 if (processController == null) {
85 Slog.w(TAG, "Could not find the embedding process.");
86 } else {
87 processController.addHostActivity(window.mHostActivityRecord);
88 }
89 }
90
Vishnu Nair5cf253192019-11-07 15:33:20 -080091 WindowState getHostWindow(IBinder inputToken) {
92 EmbeddedWindow embeddedWindow = mWindows.get(inputToken);
93 return embeddedWindow != null ? embeddedWindow.mHostWindowState : null;
94 }
95
Vishnu Nair5cf253192019-11-07 15:33:20 -080096 void remove(IWindow client) {
Vishnu Nairddbd2512019-11-12 14:39:43 -080097 for (int i = mWindows.size() - 1; i >= 0; i--) {
98 if (mWindows.valueAt(i).mClient.asBinder() == client.asBinder()) {
arthurhung03d65a72020-04-28 09:19:24 +080099 mWindows.removeAt(i).onRemoved();
Vishnu Nair5cf253192019-11-07 15:33:20 -0800100 return;
101 }
102 }
103 }
104
Vishnu Nairfca78472020-03-09 15:34:47 -0700105 void onWindowRemoved(WindowState host) {
Vishnu Nairddbd2512019-11-12 14:39:43 -0800106 for (int i = mWindows.size() - 1; i >= 0; i--) {
107 if (mWindows.valueAt(i).mHostWindowState == host) {
arthurhung03d65a72020-04-28 09:19:24 +0800108 mWindows.removeAt(i).onRemoved();
Vishnu Nair5cf253192019-11-07 15:33:20 -0800109 }
110 }
111 }
112
Vishnu Nairddbd2512019-11-12 14:39:43 -0800113 EmbeddedWindow get(IBinder inputToken) {
114 return mWindows.get(inputToken);
115 }
116
Vishnu Nairfca78472020-03-09 15:34:47 -0700117 void onActivityRemoved(ActivityRecord activityRecord) {
118 for (int i = mWindows.size() - 1; i >= 0; i--) {
119 final EmbeddedWindow window = mWindows.valueAt(i);
120 if (window.mHostActivityRecord == activityRecord) {
121 final WindowProcessController processController =
122 mAtmService.getProcessController(window.mOwnerPid, window.mOwnerUid);
123 if (processController != null) {
124 processController.removeHostActivity(activityRecord);
125 }
126 }
127 }
128 }
129
Vishnu Nairddbd2512019-11-12 14:39:43 -0800130 static class EmbeddedWindow {
Vishnu Nair5cf253192019-11-07 15:33:20 -0800131 final IWindow mClient;
Vishnu Nairddbd2512019-11-12 14:39:43 -0800132 @Nullable final WindowState mHostWindowState;
Vishnu Nairfca78472020-03-09 15:34:47 -0700133 @Nullable final ActivityRecord mHostActivityRecord;
Vishnu Nair5cf253192019-11-07 15:33:20 -0800134 final int mOwnerUid;
135 final int mOwnerPid;
arthurhung03d65a72020-04-28 09:19:24 +0800136 final WindowManagerService mWmService;
137 InputChannel mInputChannel;
arthurhungd3f17d72020-05-08 17:20:38 +0800138 final int mWindowType;
Vishnu Nair5cf253192019-11-07 15:33:20 -0800139
Evan Rosky680377e2020-01-10 19:12:10 -0800140 /**
141 * @param clientToken client token used to clean up the map if the embedding process dies
142 * @param hostWindowState input channel token belonging to the host window. This is needed
143 * to handle input callbacks to wm. It's used when raising ANR and
144 * when the user taps out side of the focused region on screen. This
145 * can be null if there is no host window.
146 * @param ownerUid calling uid
147 * @param ownerPid calling pid used for anr blaming
148 */
arthurhung03d65a72020-04-28 09:19:24 +0800149 EmbeddedWindow(WindowManagerService service, IWindow clientToken,
arthurhungd3f17d72020-05-08 17:20:38 +0800150 WindowState hostWindowState, int ownerUid, int ownerPid, int windowType) {
arthurhung03d65a72020-04-28 09:19:24 +0800151 mWmService = service;
Vishnu Nair5cf253192019-11-07 15:33:20 -0800152 mClient = clientToken;
153 mHostWindowState = hostWindowState;
Vishnu Nairfca78472020-03-09 15:34:47 -0700154 mHostActivityRecord = (mHostWindowState != null) ? mHostWindowState.mActivityRecord
155 : null;
Vishnu Nair5cf253192019-11-07 15:33:20 -0800156 mOwnerUid = ownerUid;
157 mOwnerPid = ownerPid;
arthurhungd3f17d72020-05-08 17:20:38 +0800158 mWindowType = windowType;
Vishnu Nair5cf253192019-11-07 15:33:20 -0800159 }
Evan Rosky680377e2020-01-10 19:12:10 -0800160
161 String getName() {
162 final String hostWindowName = (mHostWindowState != null)
163 ? mHostWindowState.getWindowTag().toString() : "Internal";
164 return "EmbeddedWindow{ u" + UserHandle.getUserId(mOwnerUid) + " " + hostWindowName
165 + "}";
166 }
167
168 InputApplicationHandle getApplicationHandle() {
169 if (mHostWindowState == null
170 || mHostWindowState.mInputWindowHandle.inputApplicationHandle == null) {
171 return null;
172 }
173 return new InputApplicationHandle(
174 mHostWindowState.mInputWindowHandle.inputApplicationHandle);
175 }
arthurhung03d65a72020-04-28 09:19:24 +0800176
177 InputChannel openInputChannel() {
178 final String name = getName();
179
180 final InputChannel[] inputChannels = InputChannel.openInputChannelPair(name);
181 mInputChannel = inputChannels[0];
182 final InputChannel clientChannel = inputChannels[1];
183 mWmService.mInputManager.registerInputChannel(mInputChannel);
184
185 if (mInputChannel.getToken() != clientChannel.getToken()) {
186 throw new IllegalStateException("Client and Server tokens are expected to"
187 + "be the same");
188 }
189
190 return clientChannel;
191 }
192
193 void onRemoved() {
194 if (mInputChannel != null) {
195 mWmService.mInputManager.unregisterInputChannel(mInputChannel);
196 mInputChannel.dispose();
197 mInputChannel = null;
198 }
199 }
Vishnu Nair5cf253192019-11-07 15:33:20 -0800200 }
201}