blob: 6b1c7b413532baab8550162bb2c3cd5e7e917825 [file] [log] [blame]
Vitalii Tomkiv46371472016-05-23 16:55:22 -07001/*
2 * Copyright (C) 2015 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 */
16package com.android.car;
17
Roberto Perez9fed5f62021-07-10 00:48:15 +000018import android.car.Car;
Vitalii Tomkiv46371472016-05-23 16:55:22 -070019import android.car.CarAppFocusManager;
20import android.car.IAppFocus;
21import android.car.IAppFocusListener;
Vitalii Tomkivd15d8872016-10-04 14:08:56 -070022import android.car.IAppFocusOwnershipCallback;
Vitalii Tomkiv46371472016-05-23 16:55:22 -070023import android.content.Context;
Roberto Perez9fed5f62021-07-10 00:48:15 +000024import android.content.PermissionChecker;
25import android.content.pm.PackageManager;
Vitalii Tomkiv46371472016-05-23 16:55:22 -070026import android.os.Binder;
27import android.os.Handler;
28import android.os.HandlerThread;
29import android.os.Looper;
30import android.os.Message;
31import android.os.RemoteException;
Antonio Kantek9f689542019-12-05 15:44:59 -080032import android.util.ArraySet;
Felipe Leme176a5fd2021-01-20 15:48:33 -080033import android.util.IndentingPrintWriter;
Eric Jeongbd5fb562020-12-21 13:49:40 -080034import android.util.Slog;
Antonio Kantek9f689542019-12-05 15:44:59 -080035import android.util.SparseArray;
Vitalii Tomkiv46371472016-05-23 16:55:22 -070036
Antonio Kantek9f689542019-12-05 15:44:59 -080037import com.android.internal.annotations.GuardedBy;
tadvana3b9ed202019-07-17 19:21:28 -070038import com.android.internal.annotations.VisibleForTesting;
39
Keun young Parkb241d022020-04-20 20:31:34 -070040import java.lang.ref.WeakReference;
Antonio Kantek9f689542019-12-05 15:44:59 -080041import java.util.ArrayList;
Roberto Perez9fed5f62021-07-10 00:48:15 +000042import java.util.Arrays;
Antonio Kantek9f689542019-12-05 15:44:59 -080043import java.util.Collections;
44import java.util.List;
Vitalii Tomkiv46371472016-05-23 16:55:22 -070045import java.util.Set;
46
47/**
48 * App focus service ensures only one instance of application type is active at a time.
49 */
50public class AppFocusService extends IAppFocus.Stub implements CarServiceBase,
Vitalii Tomkivd15d8872016-10-04 14:08:56 -070051 BinderInterfaceContainer.BinderEventHandler<IAppFocusOwnershipCallback> {
Vitalii Tomkiv1b1247b2016-09-30 11:27:19 -070052 private static final boolean DBG = false;
Vitalii Tomkiv46371472016-05-23 16:55:22 -070053 private static final boolean DBG_EVENT = false;
54
Vitalii Tomkiv8c7f2972016-07-11 15:42:04 -070055 private final SystemActivityMonitoringService mSystemActivityMonitoringService;
Antonio Kantek9f689542019-12-05 15:44:59 -080056
57 private final Object mLock = new Object();
58
Keun young Parka7bdd592020-04-15 17:57:40 -070059 @VisibleForTesting
Antonio Kantek9f689542019-12-05 15:44:59 -080060 @GuardedBy("mLock")
Keun young Parka7bdd592020-04-15 17:57:40 -070061 final ClientHolder mAllChangeClients;
Antonio Kantek9f689542019-12-05 15:44:59 -080062
Keun young Parka7bdd592020-04-15 17:57:40 -070063 @VisibleForTesting
Antonio Kantek9f689542019-12-05 15:44:59 -080064 @GuardedBy("mLock")
Keun young Parka7bdd592020-04-15 17:57:40 -070065 final OwnershipClientHolder mAllOwnershipClients;
Antonio Kantek9f689542019-12-05 15:44:59 -080066
Vitalii Tomkiv46371472016-05-23 16:55:22 -070067 /** K: appType, V: client owning it */
Antonio Kantek9f689542019-12-05 15:44:59 -080068 @GuardedBy("mLock")
69 private final SparseArray<OwnershipClientInfo> mFocusOwners = new SparseArray<>();
70
71 @GuardedBy("mLock")
72 private final Set<Integer> mActiveAppTypes = new ArraySet<>();
73
74 @GuardedBy("mLock")
75 private final List<FocusOwnershipCallback> mFocusOwnershipCallbacks = new ArrayList<>();
76
Vitalii Tomkiv46371472016-05-23 16:55:22 -070077 private final BinderInterfaceContainer.BinderEventHandler<IAppFocusListener>
Pavel Maltsev0477e292016-05-27 12:22:36 -070078 mAllBinderEventHandler = bInterface -> { /* nothing to do.*/ };
Vitalii Tomkiv46371472016-05-23 16:55:22 -070079
Keun young Parkb241d022020-04-20 20:31:34 -070080 private final HandlerThread mHandlerThread = CarServiceUtils.getHandlerThread(
81 getClass().getSimpleName());
82 private final DispatchHandler mDispatchHandler = new DispatchHandler(mHandlerThread.getLooper(),
83 this);
Roberto Perez9fed5f62021-07-10 00:48:15 +000084 private final Context mContext;
Pavel Maltsevddbff982017-03-22 14:49:02 -070085
Vitalii Tomkiv8c7f2972016-07-11 15:42:04 -070086 public AppFocusService(Context context,
87 SystemActivityMonitoringService systemActivityMonitoringService) {
Roberto Perez9fed5f62021-07-10 00:48:15 +000088 mContext = context;
Vitalii Tomkiv8c7f2972016-07-11 15:42:04 -070089 mSystemActivityMonitoringService = systemActivityMonitoringService;
Vitalii Tomkiv46371472016-05-23 16:55:22 -070090 mAllChangeClients = new ClientHolder(mAllBinderEventHandler);
91 mAllOwnershipClients = new OwnershipClientHolder(this);
Vitalii Tomkiv46371472016-05-23 16:55:22 -070092 }
93
94 @Override
95 public void registerFocusListener(IAppFocusListener listener, int appType) {
Antonio Kantek9f689542019-12-05 15:44:59 -080096 synchronized (mLock) {
Vitalii Tomkiv46371472016-05-23 16:55:22 -070097 ClientInfo info = (ClientInfo) mAllChangeClients.getBinderInterface(listener);
98 if (info == null) {
99 info = new ClientInfo(mAllChangeClients, listener, Binder.getCallingUid(),
100 Binder.getCallingPid(), appType);
101 mAllChangeClients.addBinderInterface(info);
102 } else {
103 info.addAppType(appType);
104 }
105 }
106 }
107
108 @Override
109 public void unregisterFocusListener(IAppFocusListener listener, int appType) {
Antonio Kantek9f689542019-12-05 15:44:59 -0800110 synchronized (mLock) {
Vitalii Tomkiv46371472016-05-23 16:55:22 -0700111 ClientInfo info = (ClientInfo) mAllChangeClients.getBinderInterface(listener);
112 if (info == null) {
113 return;
114 }
115 info.removeAppType(appType);
116 if (info.getAppTypes().isEmpty()) {
117 mAllChangeClients.removeBinder(listener);
118 }
119 }
120 }
121
122 @Override
123 public int[] getActiveAppTypes() {
Antonio Kantek9f689542019-12-05 15:44:59 -0800124 synchronized (mLock) {
125 return mActiveAppTypes.stream().mapToInt(Integer::intValue).toArray();
Vitalii Tomkiv46371472016-05-23 16:55:22 -0700126 }
127 }
128
129 @Override
Roberto Perez9fed5f62021-07-10 00:48:15 +0000130 public List<String> getAppTypeOwner(@CarAppFocusManager.AppFocusType int appType) {
131 OwnershipClientInfo owner;
132 synchronized (mLock) {
133 owner = mFocusOwners.get(appType);
134 }
135 if (owner == null) {
136 return null;
137 }
138 String[] packageNames = mContext.getPackageManager().getPackagesForUid(owner.getUid());
139 if (packageNames == null) {
140 return null;
141 }
142 return Arrays.asList(packageNames);
143 }
144
145 @Override
Vitalii Tomkivd15d8872016-10-04 14:08:56 -0700146 public boolean isOwningFocus(IAppFocusOwnershipCallback callback, int appType) {
Antonio Kantek9f689542019-12-05 15:44:59 -0800147 OwnershipClientInfo info;
148 synchronized (mLock) {
149 info = (OwnershipClientInfo) mAllOwnershipClients.getBinderInterface(callback);
Vitalii Tomkiv46371472016-05-23 16:55:22 -0700150 }
Antonio Kantek9f689542019-12-05 15:44:59 -0800151 if (info == null) {
152 return false;
153 }
154 return info.getOwnedAppTypes().contains(appType);
Vitalii Tomkiv46371472016-05-23 16:55:22 -0700155 }
156
157 @Override
Vitalii Tomkivd15d8872016-10-04 14:08:56 -0700158 public int requestAppFocus(IAppFocusOwnershipCallback callback, int appType) {
Antonio Kantek9f689542019-12-05 15:44:59 -0800159 synchronized (mLock) {
Vitalii Tomkiv46371472016-05-23 16:55:22 -0700160 OwnershipClientInfo info =
Vitalii Tomkivd15d8872016-10-04 14:08:56 -0700161 (OwnershipClientInfo) mAllOwnershipClients.getBinderInterface(callback);
Vitalii Tomkiv46371472016-05-23 16:55:22 -0700162 if (info == null) {
Vitalii Tomkivd15d8872016-10-04 14:08:56 -0700163 info = new OwnershipClientInfo(mAllOwnershipClients, callback,
Vitalii Tomkiv46371472016-05-23 16:55:22 -0700164 Binder.getCallingUid(), Binder.getCallingPid());
165 mAllOwnershipClients.addBinderInterface(info);
166 }
167 Set<Integer> alreadyOwnedAppTypes = info.getOwnedAppTypes();
168 if (!alreadyOwnedAppTypes.contains(appType)) {
169 OwnershipClientInfo ownerInfo = mFocusOwners.get(appType);
170 if (ownerInfo != null && ownerInfo != info) {
Roberto Perez9fed5f62021-07-10 00:48:15 +0000171 // Allow receiving focus if the requester has a foreground activity OR if the
172 // requester is privileged service.
173 if (isInForeground(ownerInfo) && !isInForeground(info)
174 && !hasPrivilegedPermission()) {
Eric Jeongbd5fb562020-12-21 13:49:40 -0800175 Slog.w(CarLog.TAG_APP_FOCUS, "Focus request failed for non-foreground app("
Antonio Kantek6af8e982020-04-10 19:11:51 -0700176 + "pid=" + info.getPid() + ", uid=" + info.getUid() + ")."
177 + "Foreground app (pid=" + ownerInfo.getPid() + ", uid="
178 + ownerInfo.getUid() + ") owns it.");
Vitalii Tomkiv8c7f2972016-07-11 15:42:04 -0700179 return CarAppFocusManager.APP_FOCUS_REQUEST_FAILED;
180 }
Vitalii Tomkiv46371472016-05-23 16:55:22 -0700181 ownerInfo.removeOwnedAppType(appType);
182 mDispatchHandler.requestAppFocusOwnershipLossDispatch(
183 ownerInfo.binderInterface, appType);
184 if (DBG) {
Eric Jeongbd5fb562020-12-21 13:49:40 -0800185 Slog.i(CarLog.TAG_APP_FOCUS, "losing app type "
Keun young Park5dcf3272020-06-03 15:01:30 -0700186 + appType + "," + ownerInfo);
Vitalii Tomkiv46371472016-05-23 16:55:22 -0700187 }
188 }
Yuncheol Heo2be288a2021-03-02 15:19:31 -0800189 mFocusOwners.put(appType, info);
190 dispatchAcquireFocusOwnerLocked(appType, info, mFocusOwnershipCallbacks);
Vitalii Tomkiv46371472016-05-23 16:55:22 -0700191 }
192 info.addOwnedAppType(appType);
Vitalii Tomkivd15d8872016-10-04 14:08:56 -0700193 mDispatchHandler.requestAppFocusOwnershipGrantDispatch(
194 info.binderInterface, appType);
Keun young Park5dcf3272020-06-03 15:01:30 -0700195 mActiveAppTypes.add(appType);
196 if (DBG) {
Eric Jeongbd5fb562020-12-21 13:49:40 -0800197 Slog.i(CarLog.TAG_APP_FOCUS, "updating active app type " + appType + ","
Keun young Park5dcf3272020-06-03 15:01:30 -0700198 + info);
199 }
200 // Always dispatch.
201 for (BinderInterfaceContainer.BinderInterface<IAppFocusListener> client :
202 mAllChangeClients.getInterfaces()) {
203 ClientInfo clientInfo = (ClientInfo) client;
204 // dispatch events only when there is change after filter and the listener
205 // is not coming from the current caller.
206 if (clientInfo.getAppTypes().contains(appType)) {
207 mDispatchHandler.requestAppFocusChangeDispatch(clientInfo.binderInterface,
208 appType, true);
Vitalii Tomkiv46371472016-05-23 16:55:22 -0700209 }
210 }
211 }
Vitalii Tomkivd15d8872016-10-04 14:08:56 -0700212 return CarAppFocusManager.APP_FOCUS_REQUEST_SUCCEEDED;
Vitalii Tomkiv46371472016-05-23 16:55:22 -0700213 }
214
Roberto Perez9fed5f62021-07-10 00:48:15 +0000215 private boolean isInForeground(OwnershipClientInfo info) {
216 return mSystemActivityMonitoringService.isInForeground(info.getPid(), info.getUid());
217 }
218
219 private boolean hasPrivilegedPermission() {
220 return mContext.checkCallingOrSelfPermission(Car.PERMISSION_CAR_DISPLAY_IN_CLUSTER)
221 == PermissionChecker.PERMISSION_GRANTED;
222 }
223
Vitalii Tomkiv46371472016-05-23 16:55:22 -0700224 @Override
Vitalii Tomkivd15d8872016-10-04 14:08:56 -0700225 public void abandonAppFocus(IAppFocusOwnershipCallback callback, int appType) {
Antonio Kantek9f689542019-12-05 15:44:59 -0800226 synchronized (mLock) {
Vitalii Tomkiv46371472016-05-23 16:55:22 -0700227 OwnershipClientInfo info =
Vitalii Tomkivd15d8872016-10-04 14:08:56 -0700228 (OwnershipClientInfo) mAllOwnershipClients.getBinderInterface(callback);
Vitalii Tomkiv46371472016-05-23 16:55:22 -0700229 if (info == null) {
230 // ignore as this client cannot have owned anything.
231 return;
232 }
233 if (!mActiveAppTypes.contains(appType)) {
234 // ignore as none of them are active;
235 return;
236 }
237 Set<Integer> currentlyOwnedAppTypes = info.getOwnedAppTypes();
238 if (!currentlyOwnedAppTypes.contains(appType)) {
239 // ignore as listener doesn't own focus.
240 return;
241 }
Saeid Farivar Asanjane03f3612021-04-20 18:27:53 -0700242 // Because this code will run as part of unit tests on older platform, we can't use
243 // APIs such as {@link SparseArray#contains} that are added with API 30.
244 if (mFocusOwners.indexOfKey(appType) >= 0) {
Antonio Kantek9f689542019-12-05 15:44:59 -0800245 mFocusOwners.remove(appType);
Vitalii Tomkiv46371472016-05-23 16:55:22 -0700246 mActiveAppTypes.remove(appType);
247 info.removeOwnedAppType(appType);
248 if (DBG) {
Eric Jeongbd5fb562020-12-21 13:49:40 -0800249 Slog.i(CarLog.TAG_APP_FOCUS, "abandoning focus " + appType + "," + info);
Vitalii Tomkiv46371472016-05-23 16:55:22 -0700250 }
Yuncheol Heo2be288a2021-03-02 15:19:31 -0800251 dispatchAbandonFocusOwnerLocked(appType, info, mFocusOwnershipCallbacks);
Vitalii Tomkiv46371472016-05-23 16:55:22 -0700252 for (BinderInterfaceContainer.BinderInterface<IAppFocusListener> client :
253 mAllChangeClients.getInterfaces()) {
254 ClientInfo clientInfo = (ClientInfo) client;
255 if (clientInfo.getAppTypes().contains(appType)) {
256 mDispatchHandler.requestAppFocusChangeDispatch(clientInfo.binderInterface,
257 appType, false);
258 }
259 }
260 }
261 }
Vitalii Tomkiv46371472016-05-23 16:55:22 -0700262 }
263
264 @Override
265 public void init() {
Keun young Parka7bdd592020-04-15 17:57:40 -0700266 // nothing to do
Vitalii Tomkiv46371472016-05-23 16:55:22 -0700267 }
268
tadvana3b9ed202019-07-17 19:21:28 -0700269 @VisibleForTesting
270 public Looper getLooper() {
Keun young Parkb241d022020-04-20 20:31:34 -0700271 return mHandlerThread.getLooper();
272
tadvana3b9ed202019-07-17 19:21:28 -0700273 }
274
Vitalii Tomkiv46371472016-05-23 16:55:22 -0700275 @Override
276 public void release() {
Antonio Kantek9f689542019-12-05 15:44:59 -0800277 synchronized (mLock) {
Vitalii Tomkiv46371472016-05-23 16:55:22 -0700278 mAllChangeClients.clear();
279 mAllOwnershipClients.clear();
280 mFocusOwners.clear();
281 mActiveAppTypes.clear();
282 }
283 }
284
285 @Override
286 public void onBinderDeath(
Vitalii Tomkivd15d8872016-10-04 14:08:56 -0700287 BinderInterfaceContainer.BinderInterface<IAppFocusOwnershipCallback> bInterface) {
Vitalii Tomkiv46371472016-05-23 16:55:22 -0700288 OwnershipClientInfo info = (OwnershipClientInfo) bInterface;
Antonio Kantek9f689542019-12-05 15:44:59 -0800289 synchronized (mLock) {
290 for (Integer appType : info.getOwnedAppTypes()) {
291 abandonAppFocus(bInterface.binderInterface, appType);
292 }
Vitalii Tomkiv46371472016-05-23 16:55:22 -0700293 }
294 }
295
296 @Override
Felipe Leme176a5fd2021-01-20 15:48:33 -0800297 public void dump(IndentingPrintWriter writer) {
Vitalii Tomkiv46371472016-05-23 16:55:22 -0700298 writer.println("**AppFocusService**");
Antonio Kantek9f689542019-12-05 15:44:59 -0800299 synchronized (mLock) {
Vitalii Tomkiv46371472016-05-23 16:55:22 -0700300 writer.println("mActiveAppTypes:" + mActiveAppTypes);
Vitalii Tomkivd15d8872016-10-04 14:08:56 -0700301 for (BinderInterfaceContainer.BinderInterface<IAppFocusOwnershipCallback> client :
Vitalii Tomkiv46371472016-05-23 16:55:22 -0700302 mAllOwnershipClients.getInterfaces()) {
303 OwnershipClientInfo clientInfo = (OwnershipClientInfo) client;
Keun young Park5dcf3272020-06-03 15:01:30 -0700304 writer.println(clientInfo);
Vitalii Tomkiv46371472016-05-23 16:55:22 -0700305 }
306 }
307 }
308
309 /**
310 * Returns true if process with given uid and pid owns provided focus.
311 */
312 public boolean isFocusOwner(int uid, int pid, int appType) {
Antonio Kantek9f689542019-12-05 15:44:59 -0800313 synchronized (mLock) {
Saeid Farivar Asanjane03f3612021-04-20 18:27:53 -0700314 // Because this code will run as part of unit tests on older platform, we can't use
315 // APIs such as {@link SparseArray#contains} that are added with API 30.
316 if (mFocusOwners.indexOfKey(appType) >= 0) {
Vitalii Tomkiv46371472016-05-23 16:55:22 -0700317 OwnershipClientInfo clientInfo = mFocusOwners.get(appType);
318 return clientInfo.getUid() == uid && clientInfo.getPid() == pid;
319 }
320 }
321 return false;
322 }
323
Pavel Maltsev0477e292016-05-27 12:22:36 -0700324 /**
325 * Defines callback functions that will be called when ownership has been changed.
326 */
Vitalii Tomkivd15d8872016-10-04 14:08:56 -0700327 public interface FocusOwnershipCallback {
Pavel Maltsevffb3fb52016-06-29 12:48:50 -0700328 void onFocusAcquired(int appType, int uid, int pid);
329 void onFocusAbandoned(int appType, int uid, int pid);
Pavel Maltsev0477e292016-05-27 12:22:36 -0700330 }
331
332 /**
Vitalii Tomkivd15d8872016-10-04 14:08:56 -0700333 * Registers callback.
Pavel Maltsev0477e292016-05-27 12:22:36 -0700334 *
335 * If any focus already acquired it will trigger
Vitalii Tomkivd15d8872016-10-04 14:08:56 -0700336 * {@link FocusOwnershipCallback#onFocusAcquired} call immediately in the same thread.
Pavel Maltsev0477e292016-05-27 12:22:36 -0700337 */
Vitalii Tomkivd15d8872016-10-04 14:08:56 -0700338 public void registerContextOwnerChangedCallback(FocusOwnershipCallback callback) {
Antonio Kantek9f689542019-12-05 15:44:59 -0800339 SparseArray<OwnershipClientInfo> owners;
340 synchronized (mLock) {
341 mFocusOwnershipCallbacks.add(callback);
342 owners = mFocusOwners.clone();
Pavel Maltsev0477e292016-05-27 12:22:36 -0700343 }
Antonio Kantek9f689542019-12-05 15:44:59 -0800344 for (int idx = 0; idx < owners.size(); idx++) {
345 int key = owners.keyAt(idx);
346 OwnershipClientInfo clientInfo = owners.valueAt(idx);
347 callback.onFocusAcquired(key, clientInfo.getUid(), clientInfo.getPid());
Pavel Maltsev0477e292016-05-27 12:22:36 -0700348 }
349 }
350
351 /**
Vitalii Tomkivd15d8872016-10-04 14:08:56 -0700352 * Unregisters provided callback.
Pavel Maltsev0477e292016-05-27 12:22:36 -0700353 */
Vitalii Tomkivd15d8872016-10-04 14:08:56 -0700354 public void unregisterContextOwnerChangedCallback(FocusOwnershipCallback callback) {
Antonio Kantek9f689542019-12-05 15:44:59 -0800355 synchronized (mLock) {
356 mFocusOwnershipCallbacks.remove(callback);
357 }
Pavel Maltsev0477e292016-05-27 12:22:36 -0700358 }
359
Yuncheol Heo2be288a2021-03-02 15:19:31 -0800360 private void dispatchAcquireFocusOwnerLocked(int appType, OwnershipClientInfo owner,
361 List<FocusOwnershipCallback> focusOwnershipCallbacks) {
362 // Dispatches each callback separately, not to make the copy of mFocusOwnershipCallbacks.
363 for (int i = focusOwnershipCallbacks.size() - 1; i >= 0; --i) {
364 FocusOwnershipCallback callback = focusOwnershipCallbacks.get(i);
365 mDispatchHandler.post(
366 () -> callback.onFocusAcquired(appType, owner.getUid(), owner.getPid()));
367 }
368 }
369
370 private void dispatchAbandonFocusOwnerLocked(int appType, OwnershipClientInfo owner,
371 List<FocusOwnershipCallback> focusOwnershipCallbacks) {
372 // Dispatches each callback separately, not to make the copy of mFocusOwnershipCallbacks.
373 for (int i = focusOwnershipCallbacks.size() - 1; i >= 0; --i) {
374 FocusOwnershipCallback callback = focusOwnershipCallbacks.get(i);
375 mDispatchHandler.post(
376 () -> callback.onFocusAbandoned(appType, owner.getUid(), owner.getPid()));
377 }
Pavel Maltsev0477e292016-05-27 12:22:36 -0700378 }
379
Vitalii Tomkivd15d8872016-10-04 14:08:56 -0700380 private void dispatchAppFocusOwnershipLoss(IAppFocusOwnershipCallback callback, int appType) {
Vitalii Tomkiv46371472016-05-23 16:55:22 -0700381 try {
Vitalii Tomkivd15d8872016-10-04 14:08:56 -0700382 callback.onAppFocusOwnershipLost(appType);
383 } catch (RemoteException e) {
384 }
385 }
386
387 private void dispatchAppFocusOwnershipGrant(IAppFocusOwnershipCallback callback, int appType) {
388 try {
389 callback.onAppFocusOwnershipGranted(appType);
Vitalii Tomkiv46371472016-05-23 16:55:22 -0700390 } catch (RemoteException e) {
391 }
392 }
393
394 private void dispatchAppFocusChange(IAppFocusListener listener, int appType, boolean active) {
395 try {
Jason Tholstrupd72b5352016-09-22 16:32:14 -0700396 listener.onAppFocusChanged(appType, active);
Vitalii Tomkiv46371472016-05-23 16:55:22 -0700397 } catch (RemoteException e) {
398 }
399 }
400
Keun young Parka7bdd592020-04-15 17:57:40 -0700401 @VisibleForTesting
402 static class ClientHolder extends BinderInterfaceContainer<IAppFocusListener> {
Vitalii Tomkiv46371472016-05-23 16:55:22 -0700403 private ClientHolder(BinderEventHandler<IAppFocusListener> holder) {
404 super(holder);
405 }
406 }
407
Keun young Parka7bdd592020-04-15 17:57:40 -0700408 @VisibleForTesting
409 static class OwnershipClientHolder extends
Vitalii Tomkivd15d8872016-10-04 14:08:56 -0700410 BinderInterfaceContainer<IAppFocusOwnershipCallback> {
Vitalii Tomkiv46371472016-05-23 16:55:22 -0700411 private OwnershipClientHolder(AppFocusService service) {
412 super(service);
413 }
414 }
415
Antonio Kantek9f689542019-12-05 15:44:59 -0800416 private class ClientInfo extends
Vitalii Tomkiv46371472016-05-23 16:55:22 -0700417 BinderInterfaceContainer.BinderInterface<IAppFocusListener> {
418 private final int mUid;
419 private final int mPid;
Antonio Kantek9f689542019-12-05 15:44:59 -0800420
421 @GuardedBy("AppFocusService.mLock")
422 private final Set<Integer> mAppTypes = new ArraySet<>();
Vitalii Tomkiv46371472016-05-23 16:55:22 -0700423
424 private ClientInfo(ClientHolder holder, IAppFocusListener binder, int uid, int pid,
425 int appType) {
426 super(holder, binder);
427 this.mUid = uid;
428 this.mPid = pid;
429 this.mAppTypes.add(appType);
430 }
431
Antonio Kantek9f689542019-12-05 15:44:59 -0800432 private Set<Integer> getAppTypes() {
433 synchronized (mLock) {
434 return Collections.unmodifiableSet(mAppTypes);
435 }
Vitalii Tomkiv46371472016-05-23 16:55:22 -0700436 }
437
Antonio Kantek9f689542019-12-05 15:44:59 -0800438 private boolean addAppType(Integer appType) {
439 synchronized (mLock) {
440 return mAppTypes.add(appType);
441 }
Vitalii Tomkiv46371472016-05-23 16:55:22 -0700442 }
443
Antonio Kantek9f689542019-12-05 15:44:59 -0800444 private boolean removeAppType(Integer appType) {
445 synchronized (mLock) {
446 return mAppTypes.remove(appType);
447 }
Vitalii Tomkiv46371472016-05-23 16:55:22 -0700448 }
449
Vitalii Tomkiv46371472016-05-23 16:55:22 -0700450 @Override
451 public String toString() {
Antonio Kantek9f689542019-12-05 15:44:59 -0800452 synchronized (mLock) {
Vitalii Tomkiv46371472016-05-23 16:55:22 -0700453 return "ClientInfo{mUid=" + mUid + ",mPid=" + mPid
454 + ",appTypes=" + mAppTypes + "}";
455 }
456 }
457 }
458
Antonio Kantek9f689542019-12-05 15:44:59 -0800459 private class OwnershipClientInfo extends
Vitalii Tomkivd15d8872016-10-04 14:08:56 -0700460 BinderInterfaceContainer.BinderInterface<IAppFocusOwnershipCallback> {
Vitalii Tomkiv46371472016-05-23 16:55:22 -0700461 private final int mUid;
462 private final int mPid;
Antonio Kantek9f689542019-12-05 15:44:59 -0800463
464 @GuardedBy("AppFocusService.mLock")
465 private final Set<Integer> mOwnedAppTypes = new ArraySet<>();
Vitalii Tomkiv46371472016-05-23 16:55:22 -0700466
Vitalii Tomkivd15d8872016-10-04 14:08:56 -0700467 private OwnershipClientInfo(OwnershipClientHolder holder, IAppFocusOwnershipCallback binder,
Vitalii Tomkiv46371472016-05-23 16:55:22 -0700468 int uid, int pid) {
469 super(holder, binder);
470 this.mUid = uid;
471 this.mPid = pid;
472 }
473
Antonio Kantek9f689542019-12-05 15:44:59 -0800474 private Set<Integer> getOwnedAppTypes() {
Vitalii Tomkiv46371472016-05-23 16:55:22 -0700475 if (DBG_EVENT) {
Eric Jeongbd5fb562020-12-21 13:49:40 -0800476 Slog.i(CarLog.TAG_APP_FOCUS, "getOwnedAppTypes " + mOwnedAppTypes);
Vitalii Tomkiv46371472016-05-23 16:55:22 -0700477 }
Antonio Kantek9f689542019-12-05 15:44:59 -0800478 synchronized (mLock) {
479 return Collections.unmodifiableSet(mOwnedAppTypes);
480 }
Vitalii Tomkiv46371472016-05-23 16:55:22 -0700481 }
482
Antonio Kantek9f689542019-12-05 15:44:59 -0800483 private boolean addOwnedAppType(Integer appType) {
Vitalii Tomkiv46371472016-05-23 16:55:22 -0700484 if (DBG_EVENT) {
Eric Jeongbd5fb562020-12-21 13:49:40 -0800485 Slog.i(CarLog.TAG_APP_FOCUS, "addOwnedAppType " + appType);
Vitalii Tomkiv46371472016-05-23 16:55:22 -0700486 }
Antonio Kantek9f689542019-12-05 15:44:59 -0800487 synchronized (mLock) {
488 return mOwnedAppTypes.add(appType);
489 }
Vitalii Tomkiv46371472016-05-23 16:55:22 -0700490 }
491
Antonio Kantek9f689542019-12-05 15:44:59 -0800492 private boolean removeOwnedAppType(Integer appType) {
Vitalii Tomkiv46371472016-05-23 16:55:22 -0700493 if (DBG_EVENT) {
Eric Jeongbd5fb562020-12-21 13:49:40 -0800494 Slog.i(CarLog.TAG_APP_FOCUS, "removeOwnedAppType " + appType);
Vitalii Tomkiv46371472016-05-23 16:55:22 -0700495 }
Antonio Kantek9f689542019-12-05 15:44:59 -0800496 synchronized (mLock) {
497 return mOwnedAppTypes.remove(appType);
498 }
Vitalii Tomkiv46371472016-05-23 16:55:22 -0700499 }
500
Pavel Maltsev0477e292016-05-27 12:22:36 -0700501 int getUid() {
Vitalii Tomkiv46371472016-05-23 16:55:22 -0700502 return mUid;
503 }
504
Pavel Maltsev0477e292016-05-27 12:22:36 -0700505 int getPid() {
Vitalii Tomkiv46371472016-05-23 16:55:22 -0700506 return mPid;
507 }
508
509 @Override
510 public String toString() {
Antonio Kantek9f689542019-12-05 15:44:59 -0800511 synchronized (mLock) {
Vitalii Tomkiv46371472016-05-23 16:55:22 -0700512 return "ClientInfo{mUid=" + mUid + ",mPid=" + mPid
513 + ",owned=" + mOwnedAppTypes + "}";
514 }
515 }
516 }
517
Keun young Parkb241d022020-04-20 20:31:34 -0700518 private static final class DispatchHandler extends Handler {
Mayank Garg72c71d22021-02-03 23:54:45 -0800519 private static final String TAG = CarLog.tagFor(AppFocusService.class);
Keun young Parkb241d022020-04-20 20:31:34 -0700520
Vitalii Tomkiv46371472016-05-23 16:55:22 -0700521 private static final int MSG_DISPATCH_OWNERSHIP_LOSS = 0;
Vitalii Tomkivd15d8872016-10-04 14:08:56 -0700522 private static final int MSG_DISPATCH_OWNERSHIP_GRANT = 1;
523 private static final int MSG_DISPATCH_FOCUS_CHANGE = 2;
Vitalii Tomkiv46371472016-05-23 16:55:22 -0700524
Keun young Parkb241d022020-04-20 20:31:34 -0700525 private final WeakReference<AppFocusService> mService;
526
527 private DispatchHandler(Looper looper, AppFocusService service) {
Vitalii Tomkiv46371472016-05-23 16:55:22 -0700528 super(looper);
Keun young Parkb241d022020-04-20 20:31:34 -0700529 mService = new WeakReference<AppFocusService>(service);
Vitalii Tomkiv46371472016-05-23 16:55:22 -0700530 }
531
Vitalii Tomkivd15d8872016-10-04 14:08:56 -0700532 private void requestAppFocusOwnershipLossDispatch(IAppFocusOwnershipCallback callback,
Vitalii Tomkiv46371472016-05-23 16:55:22 -0700533 int appType) {
Vitalii Tomkivd15d8872016-10-04 14:08:56 -0700534 Message msg = obtainMessage(MSG_DISPATCH_OWNERSHIP_LOSS, appType, 0, callback);
535 sendMessage(msg);
536 }
537
538 private void requestAppFocusOwnershipGrantDispatch(IAppFocusOwnershipCallback callback,
539 int appType) {
540 Message msg = obtainMessage(MSG_DISPATCH_OWNERSHIP_GRANT, appType, 0, callback);
Vitalii Tomkiv46371472016-05-23 16:55:22 -0700541 sendMessage(msg);
542 }
543
544 private void requestAppFocusChangeDispatch(IAppFocusListener listener, int appType,
545 boolean active) {
546 Message msg = obtainMessage(MSG_DISPATCH_FOCUS_CHANGE, appType, active ? 1 : 0,
547 listener);
548 sendMessage(msg);
549 }
550
551 @Override
552 public void handleMessage(Message msg) {
Keun young Parkb241d022020-04-20 20:31:34 -0700553 AppFocusService service = mService.get();
554 if (service == null) {
Eric Jeongbd5fb562020-12-21 13:49:40 -0800555 Slog.i(TAG, "handleMessage null service");
Keun young Parkb241d022020-04-20 20:31:34 -0700556 return;
557 }
Vitalii Tomkiv46371472016-05-23 16:55:22 -0700558 switch (msg.what) {
559 case MSG_DISPATCH_OWNERSHIP_LOSS:
Keun young Parkb241d022020-04-20 20:31:34 -0700560 service.dispatchAppFocusOwnershipLoss((IAppFocusOwnershipCallback) msg.obj,
561 msg.arg1);
Vitalii Tomkivd15d8872016-10-04 14:08:56 -0700562 break;
563 case MSG_DISPATCH_OWNERSHIP_GRANT:
Keun young Parkb241d022020-04-20 20:31:34 -0700564 service.dispatchAppFocusOwnershipGrant((IAppFocusOwnershipCallback) msg.obj,
565 msg.arg1);
Vitalii Tomkiv46371472016-05-23 16:55:22 -0700566 break;
567 case MSG_DISPATCH_FOCUS_CHANGE:
Keun young Parkb241d022020-04-20 20:31:34 -0700568 service.dispatchAppFocusChange((IAppFocusListener) msg.obj, msg.arg1,
569 msg.arg2 == 1);
Vitalii Tomkiv46371472016-05-23 16:55:22 -0700570 break;
Vitalii Tomkivd15d8872016-10-04 14:08:56 -0700571 default:
Eric Jeongbd5fb562020-12-21 13:49:40 -0800572 Slog.e(CarLog.TAG_APP_FOCUS, "Can't dispatch message: " + msg);
Vitalii Tomkiv46371472016-05-23 16:55:22 -0700573 }
574 }
575 }
Vitalii Tomkiv46371472016-05-23 16:55:22 -0700576}