blob: 3db21d28009ff753b125114fa8d9101b1ba86cfc [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
18import android.car.CarAppFocusManager;
19import android.car.IAppFocus;
20import android.car.IAppFocusListener;
Vitalii Tomkivd15d8872016-10-04 14:08:56 -070021import android.car.IAppFocusOwnershipCallback;
Vitalii Tomkiv46371472016-05-23 16:55:22 -070022import android.content.Context;
23import android.os.Binder;
24import android.os.Handler;
25import android.os.HandlerThread;
26import android.os.Looper;
27import android.os.Message;
28import android.os.RemoteException;
29import android.util.Log;
30
31import java.io.PrintWriter;
32import java.util.HashMap;
33import java.util.HashSet;
Pavel Maltsev0477e292016-05-27 12:22:36 -070034import java.util.Map;
Vitalii Tomkiv46371472016-05-23 16:55:22 -070035import java.util.Set;
Pavel Maltsev0477e292016-05-27 12:22:36 -070036import java.util.concurrent.CopyOnWriteArrayList;
Vitalii Tomkiv46371472016-05-23 16:55:22 -070037
38/**
39 * App focus service ensures only one instance of application type is active at a time.
40 */
41public class AppFocusService extends IAppFocus.Stub implements CarServiceBase,
Vitalii Tomkivd15d8872016-10-04 14:08:56 -070042 BinderInterfaceContainer.BinderEventHandler<IAppFocusOwnershipCallback> {
Vitalii Tomkiv1b1247b2016-09-30 11:27:19 -070043 private static final boolean DBG = false;
Vitalii Tomkiv46371472016-05-23 16:55:22 -070044 private static final boolean DBG_EVENT = false;
45
Vitalii Tomkiv8c7f2972016-07-11 15:42:04 -070046 private final SystemActivityMonitoringService mSystemActivityMonitoringService;
Vitalii Tomkiv46371472016-05-23 16:55:22 -070047 private final ClientHolder mAllChangeClients;
48 private final OwnershipClientHolder mAllOwnershipClients;
49 /** K: appType, V: client owning it */
50 private final HashMap<Integer, OwnershipClientInfo> mFocusOwners = new HashMap<>();
51 private final Set<Integer> mActiveAppTypes = new HashSet<>();
Vitalii Tomkivd15d8872016-10-04 14:08:56 -070052 private final CopyOnWriteArrayList<FocusOwnershipCallback> mFocusOwnershipCallbacks =
Pavel Maltsev0477e292016-05-27 12:22:36 -070053 new CopyOnWriteArrayList<>();
Vitalii Tomkiv46371472016-05-23 16:55:22 -070054 private final BinderInterfaceContainer.BinderEventHandler<IAppFocusListener>
Pavel Maltsev0477e292016-05-27 12:22:36 -070055 mAllBinderEventHandler = bInterface -> { /* nothing to do.*/ };
Vitalii Tomkiv46371472016-05-23 16:55:22 -070056
Pavel Maltsevddbff982017-03-22 14:49:02 -070057 private DispatchHandler mDispatchHandler;
58 private HandlerThread mHandlerThread;
59
Vitalii Tomkiv8c7f2972016-07-11 15:42:04 -070060 public AppFocusService(Context context,
61 SystemActivityMonitoringService systemActivityMonitoringService) {
62 mSystemActivityMonitoringService = systemActivityMonitoringService;
Vitalii Tomkiv46371472016-05-23 16:55:22 -070063 mAllChangeClients = new ClientHolder(mAllBinderEventHandler);
64 mAllOwnershipClients = new OwnershipClientHolder(this);
Vitalii Tomkiv46371472016-05-23 16:55:22 -070065 }
66
67 @Override
68 public void registerFocusListener(IAppFocusListener listener, int appType) {
69 synchronized (this) {
70 ClientInfo info = (ClientInfo) mAllChangeClients.getBinderInterface(listener);
71 if (info == null) {
72 info = new ClientInfo(mAllChangeClients, listener, Binder.getCallingUid(),
73 Binder.getCallingPid(), appType);
74 mAllChangeClients.addBinderInterface(info);
75 } else {
76 info.addAppType(appType);
77 }
78 }
79 }
80
81 @Override
82 public void unregisterFocusListener(IAppFocusListener listener, int appType) {
83 synchronized (this) {
84 ClientInfo info = (ClientInfo) mAllChangeClients.getBinderInterface(listener);
85 if (info == null) {
86 return;
87 }
88 info.removeAppType(appType);
89 if (info.getAppTypes().isEmpty()) {
90 mAllChangeClients.removeBinder(listener);
91 }
92 }
93 }
94
95 @Override
96 public int[] getActiveAppTypes() {
97 synchronized (this) {
98 return toIntArray(mActiveAppTypes);
99 }
100 }
101
102 @Override
Vitalii Tomkivd15d8872016-10-04 14:08:56 -0700103 public boolean isOwningFocus(IAppFocusOwnershipCallback callback, int appType) {
Vitalii Tomkiv46371472016-05-23 16:55:22 -0700104 synchronized (this) {
105 OwnershipClientInfo info =
Vitalii Tomkivd15d8872016-10-04 14:08:56 -0700106 (OwnershipClientInfo) mAllOwnershipClients.getBinderInterface(callback);
Vitalii Tomkiv46371472016-05-23 16:55:22 -0700107 if (info == null) {
108 return false;
109 }
110 return info.getOwnedAppTypes().contains(appType);
111 }
112 }
113
114 @Override
Vitalii Tomkivd15d8872016-10-04 14:08:56 -0700115 public int requestAppFocus(IAppFocusOwnershipCallback callback, int appType) {
Vitalii Tomkiv46371472016-05-23 16:55:22 -0700116 synchronized (this) {
117 OwnershipClientInfo info =
Vitalii Tomkivd15d8872016-10-04 14:08:56 -0700118 (OwnershipClientInfo) mAllOwnershipClients.getBinderInterface(callback);
Vitalii Tomkiv46371472016-05-23 16:55:22 -0700119 if (info == null) {
Vitalii Tomkivd15d8872016-10-04 14:08:56 -0700120 info = new OwnershipClientInfo(mAllOwnershipClients, callback,
Vitalii Tomkiv46371472016-05-23 16:55:22 -0700121 Binder.getCallingUid(), Binder.getCallingPid());
122 mAllOwnershipClients.addBinderInterface(info);
123 }
124 Set<Integer> alreadyOwnedAppTypes = info.getOwnedAppTypes();
125 if (!alreadyOwnedAppTypes.contains(appType)) {
126 OwnershipClientInfo ownerInfo = mFocusOwners.get(appType);
127 if (ownerInfo != null && ownerInfo != info) {
Vitalii Tomkiv8c7f2972016-07-11 15:42:04 -0700128 if (mSystemActivityMonitoringService.isInForeground(
129 ownerInfo.getPid(), ownerInfo.getUid()) &&
130 !mSystemActivityMonitoringService.isInForeground(
131 info.getPid(), info.getUid())) {
132 Log.w(CarLog.TAG_APP_FOCUS, "Focus request failed for non-foreground app("
133 + "pid=" + info.getPid() + ", uid=" + info.getUid() + ")."
134 + "Foreground app (pid=" + ownerInfo.getPid() + ", uid="
135 + ownerInfo.getUid() + ") owns it.");
136 return CarAppFocusManager.APP_FOCUS_REQUEST_FAILED;
137 }
Vitalii Tomkiv46371472016-05-23 16:55:22 -0700138 ownerInfo.removeOwnedAppType(appType);
139 mDispatchHandler.requestAppFocusOwnershipLossDispatch(
140 ownerInfo.binderInterface, appType);
141 if (DBG) {
142 Log.i(CarLog.TAG_APP_FOCUS, "losing app type "
143 + appType + "," + ownerInfo.toString());
144 }
145 }
Pavel Maltsev0477e292016-05-27 12:22:36 -0700146 updateFocusOwner(appType, info);
Vitalii Tomkiv46371472016-05-23 16:55:22 -0700147 }
148 info.addOwnedAppType(appType);
Vitalii Tomkivd15d8872016-10-04 14:08:56 -0700149 mDispatchHandler.requestAppFocusOwnershipGrantDispatch(
150 info.binderInterface, appType);
Vitalii Tomkiv46371472016-05-23 16:55:22 -0700151 if (mActiveAppTypes.add(appType)) {
152 if (DBG) {
153 Log.i(CarLog.TAG_APP_FOCUS, "adding active app type " + appType + ","
154 + info.toString());
155 }
156 for (BinderInterfaceContainer.BinderInterface<IAppFocusListener> client :
157 mAllChangeClients.getInterfaces()) {
158 ClientInfo clientInfo = (ClientInfo) client;
159 // dispatch events only when there is change after filter and the listener
160 // is not coming from the current caller.
161 if (clientInfo.getAppTypes().contains(appType)) {
162 mDispatchHandler.requestAppFocusChangeDispatch(clientInfo.binderInterface,
163 appType, true);
164 }
165 }
166 }
167 }
Vitalii Tomkivd15d8872016-10-04 14:08:56 -0700168 return CarAppFocusManager.APP_FOCUS_REQUEST_SUCCEEDED;
Vitalii Tomkiv46371472016-05-23 16:55:22 -0700169 }
170
171 @Override
Vitalii Tomkivd15d8872016-10-04 14:08:56 -0700172 public void abandonAppFocus(IAppFocusOwnershipCallback callback, int appType) {
Vitalii Tomkiv46371472016-05-23 16:55:22 -0700173 synchronized (this) {
174 OwnershipClientInfo info =
Vitalii Tomkivd15d8872016-10-04 14:08:56 -0700175 (OwnershipClientInfo) mAllOwnershipClients.getBinderInterface(callback);
Vitalii Tomkiv46371472016-05-23 16:55:22 -0700176 if (info == null) {
177 // ignore as this client cannot have owned anything.
178 return;
179 }
180 if (!mActiveAppTypes.contains(appType)) {
181 // ignore as none of them are active;
182 return;
183 }
184 Set<Integer> currentlyOwnedAppTypes = info.getOwnedAppTypes();
185 if (!currentlyOwnedAppTypes.contains(appType)) {
186 // ignore as listener doesn't own focus.
187 return;
188 }
189 if (mFocusOwners.remove(appType) != null) {
190 mActiveAppTypes.remove(appType);
191 info.removeOwnedAppType(appType);
192 if (DBG) {
193 Log.i(CarLog.TAG_APP_FOCUS, "abandoning focus " + appType
194 + "," + info.toString());
195 }
Vitalii Tomkivd15d8872016-10-04 14:08:56 -0700196 for (FocusOwnershipCallback ownershipCallback : mFocusOwnershipCallbacks) {
197 ownershipCallback.onFocusAbandoned(appType, info.mUid, info.mPid);
Pavel Maltsevffb3fb52016-06-29 12:48:50 -0700198 }
Vitalii Tomkiv46371472016-05-23 16:55:22 -0700199 for (BinderInterfaceContainer.BinderInterface<IAppFocusListener> client :
200 mAllChangeClients.getInterfaces()) {
201 ClientInfo clientInfo = (ClientInfo) client;
202 if (clientInfo.getAppTypes().contains(appType)) {
203 mDispatchHandler.requestAppFocusChangeDispatch(clientInfo.binderInterface,
204 appType, false);
205 }
206 }
207 }
208 }
Vitalii Tomkiv46371472016-05-23 16:55:22 -0700209 }
210
211 @Override
212 public void init() {
Pavel Maltsevddbff982017-03-22 14:49:02 -0700213 synchronized (this) {
214 mHandlerThread = new HandlerThread(AppFocusService.class.getSimpleName());
215 mHandlerThread.start();
216 mDispatchHandler = new DispatchHandler(mHandlerThread.getLooper());
217 }
Vitalii Tomkiv46371472016-05-23 16:55:22 -0700218 }
219
220 @Override
221 public void release() {
222 synchronized (this) {
Pavel Maltsevddbff982017-03-22 14:49:02 -0700223 mHandlerThread.quitSafely();
224 try {
225 mHandlerThread.join(1000);
226 } catch (InterruptedException e) {
227 Log.e(CarLog.TAG_APP_FOCUS, "Timeout while waiting for handler thread to join.");
228 }
229 mDispatchHandler = null;
Vitalii Tomkiv46371472016-05-23 16:55:22 -0700230 mAllChangeClients.clear();
231 mAllOwnershipClients.clear();
232 mFocusOwners.clear();
233 mActiveAppTypes.clear();
234 }
235 }
236
237 @Override
238 public void onBinderDeath(
Vitalii Tomkivd15d8872016-10-04 14:08:56 -0700239 BinderInterfaceContainer.BinderInterface<IAppFocusOwnershipCallback> bInterface) {
Vitalii Tomkiv46371472016-05-23 16:55:22 -0700240 OwnershipClientInfo info = (OwnershipClientInfo) bInterface;
241 for (Integer appType : info.getOwnedAppTypes()) {
242 abandonAppFocus(bInterface.binderInterface, appType);
243 }
244 }
245
246 @Override
247 public void dump(PrintWriter writer) {
248 writer.println("**AppFocusService**");
249 synchronized (this) {
250 writer.println("mActiveAppTypes:" + mActiveAppTypes);
Vitalii Tomkivd15d8872016-10-04 14:08:56 -0700251 for (BinderInterfaceContainer.BinderInterface<IAppFocusOwnershipCallback> client :
Vitalii Tomkiv46371472016-05-23 16:55:22 -0700252 mAllOwnershipClients.getInterfaces()) {
253 OwnershipClientInfo clientInfo = (OwnershipClientInfo) client;
254 writer.println(clientInfo.toString());
255 }
256 }
257 }
258
259 /**
260 * Returns true if process with given uid and pid owns provided focus.
261 */
262 public boolean isFocusOwner(int uid, int pid, int appType) {
263 synchronized (this) {
264 if (mFocusOwners.containsKey(appType)) {
265 OwnershipClientInfo clientInfo = mFocusOwners.get(appType);
266 return clientInfo.getUid() == uid && clientInfo.getPid() == pid;
267 }
268 }
269 return false;
270 }
271
Pavel Maltsev0477e292016-05-27 12:22:36 -0700272 /**
273 * Defines callback functions that will be called when ownership has been changed.
274 */
Vitalii Tomkivd15d8872016-10-04 14:08:56 -0700275 public interface FocusOwnershipCallback {
Pavel Maltsevffb3fb52016-06-29 12:48:50 -0700276 void onFocusAcquired(int appType, int uid, int pid);
277 void onFocusAbandoned(int appType, int uid, int pid);
Pavel Maltsev0477e292016-05-27 12:22:36 -0700278 }
279
280 /**
Vitalii Tomkivd15d8872016-10-04 14:08:56 -0700281 * Registers callback.
Pavel Maltsev0477e292016-05-27 12:22:36 -0700282 *
283 * If any focus already acquired it will trigger
Vitalii Tomkivd15d8872016-10-04 14:08:56 -0700284 * {@link FocusOwnershipCallback#onFocusAcquired} call immediately in the same thread.
Pavel Maltsev0477e292016-05-27 12:22:36 -0700285 */
Vitalii Tomkivd15d8872016-10-04 14:08:56 -0700286 public void registerContextOwnerChangedCallback(FocusOwnershipCallback callback) {
287 mFocusOwnershipCallbacks.add(callback);
Pavel Maltsev0477e292016-05-27 12:22:36 -0700288
289 HashSet<Map.Entry<Integer, OwnershipClientInfo>> owners;
290 synchronized (this) {
291 owners = new HashSet<>(mFocusOwners.entrySet());
292 }
293
294 for (Map.Entry<Integer, OwnershipClientInfo> entry : owners) {
295 OwnershipClientInfo clientInfo = entry.getValue();
Vitalii Tomkivd15d8872016-10-04 14:08:56 -0700296 callback.onFocusAcquired(entry.getKey(), clientInfo.getUid(), clientInfo.getPid());
Pavel Maltsev0477e292016-05-27 12:22:36 -0700297 }
298 }
299
300 /**
Vitalii Tomkivd15d8872016-10-04 14:08:56 -0700301 * Unregisters provided callback.
Pavel Maltsev0477e292016-05-27 12:22:36 -0700302 */
Vitalii Tomkivd15d8872016-10-04 14:08:56 -0700303 public void unregisterContextOwnerChangedCallback(FocusOwnershipCallback callback) {
304 mFocusOwnershipCallbacks.remove(callback);
Pavel Maltsev0477e292016-05-27 12:22:36 -0700305 }
306
307 private void updateFocusOwner(int appType, OwnershipClientInfo owner) {
308 synchronized (this) {
309 mFocusOwners.put(appType, owner);
310 }
311
312 CarServiceUtils.runOnMain(() -> {
Vitalii Tomkivd15d8872016-10-04 14:08:56 -0700313 for (FocusOwnershipCallback callback : mFocusOwnershipCallbacks) {
314 callback.onFocusAcquired(appType, owner.getUid(), owner.getPid());
Pavel Maltsev0477e292016-05-27 12:22:36 -0700315 }
316 });
317 }
318
Vitalii Tomkivd15d8872016-10-04 14:08:56 -0700319 private void dispatchAppFocusOwnershipLoss(IAppFocusOwnershipCallback callback, int appType) {
Vitalii Tomkiv46371472016-05-23 16:55:22 -0700320 try {
Vitalii Tomkivd15d8872016-10-04 14:08:56 -0700321 callback.onAppFocusOwnershipLost(appType);
322 } catch (RemoteException e) {
323 }
324 }
325
326 private void dispatchAppFocusOwnershipGrant(IAppFocusOwnershipCallback callback, int appType) {
327 try {
328 callback.onAppFocusOwnershipGranted(appType);
Vitalii Tomkiv46371472016-05-23 16:55:22 -0700329 } catch (RemoteException e) {
330 }
331 }
332
333 private void dispatchAppFocusChange(IAppFocusListener listener, int appType, boolean active) {
334 try {
Jason Tholstrupd72b5352016-09-22 16:32:14 -0700335 listener.onAppFocusChanged(appType, active);
Vitalii Tomkiv46371472016-05-23 16:55:22 -0700336 } catch (RemoteException e) {
337 }
338 }
339
340 private static class ClientHolder extends BinderInterfaceContainer<IAppFocusListener> {
341 private ClientHolder(BinderEventHandler<IAppFocusListener> holder) {
342 super(holder);
343 }
344 }
345
346 private static class OwnershipClientHolder extends
Vitalii Tomkivd15d8872016-10-04 14:08:56 -0700347 BinderInterfaceContainer<IAppFocusOwnershipCallback> {
Vitalii Tomkiv46371472016-05-23 16:55:22 -0700348 private OwnershipClientHolder(AppFocusService service) {
349 super(service);
350 }
351 }
352
353 private static class ClientInfo extends
354 BinderInterfaceContainer.BinderInterface<IAppFocusListener> {
355 private final int mUid;
356 private final int mPid;
357 private final Set<Integer> mAppTypes = new HashSet<>();
358
359 private ClientInfo(ClientHolder holder, IAppFocusListener binder, int uid, int pid,
360 int appType) {
361 super(holder, binder);
362 this.mUid = uid;
363 this.mPid = pid;
364 this.mAppTypes.add(appType);
365 }
366
367 private synchronized Set<Integer> getAppTypes() {
368 return mAppTypes;
369 }
370
371 private synchronized boolean addAppType(Integer appType) {
372 return mAppTypes.add(appType);
373 }
374
375 private synchronized boolean removeAppType(Integer appType) {
376 return mAppTypes.remove(appType);
377 }
378
Vitalii Tomkiv46371472016-05-23 16:55:22 -0700379 @Override
380 public String toString() {
381 synchronized (this) {
382 return "ClientInfo{mUid=" + mUid + ",mPid=" + mPid
383 + ",appTypes=" + mAppTypes + "}";
384 }
385 }
386 }
387
388 private static class OwnershipClientInfo extends
Vitalii Tomkivd15d8872016-10-04 14:08:56 -0700389 BinderInterfaceContainer.BinderInterface<IAppFocusOwnershipCallback> {
Vitalii Tomkiv46371472016-05-23 16:55:22 -0700390 private final int mUid;
391 private final int mPid;
392 private final Set<Integer> mOwnedAppTypes = new HashSet<>();
393
Vitalii Tomkivd15d8872016-10-04 14:08:56 -0700394 private OwnershipClientInfo(OwnershipClientHolder holder, IAppFocusOwnershipCallback binder,
Vitalii Tomkiv46371472016-05-23 16:55:22 -0700395 int uid, int pid) {
396 super(holder, binder);
397 this.mUid = uid;
398 this.mPid = pid;
399 }
400
401 private synchronized Set<Integer> getOwnedAppTypes() {
402 if (DBG_EVENT) {
403 Log.i(CarLog.TAG_APP_FOCUS, "getOwnedAppTypes " + mOwnedAppTypes);
404 }
405 return mOwnedAppTypes;
406 }
407
408 private synchronized boolean addOwnedAppType(Integer appType) {
409 if (DBG_EVENT) {
410 Log.i(CarLog.TAG_APP_FOCUS, "addOwnedAppType " + appType);
411 }
412 return mOwnedAppTypes.add(appType);
413 }
414
415 private synchronized boolean removeOwnedAppType(Integer appType) {
416 if (DBG_EVENT) {
417 Log.i(CarLog.TAG_APP_FOCUS, "removeOwnedAppType " + appType);
418 }
419 return mOwnedAppTypes.remove(appType);
420 }
421
Pavel Maltsev0477e292016-05-27 12:22:36 -0700422 int getUid() {
Vitalii Tomkiv46371472016-05-23 16:55:22 -0700423 return mUid;
424 }
425
Pavel Maltsev0477e292016-05-27 12:22:36 -0700426 int getPid() {
Vitalii Tomkiv46371472016-05-23 16:55:22 -0700427 return mPid;
428 }
429
430 @Override
431 public String toString() {
432 synchronized (this) {
433 return "ClientInfo{mUid=" + mUid + ",mPid=" + mPid
434 + ",owned=" + mOwnedAppTypes + "}";
435 }
436 }
437 }
438
439 private class DispatchHandler extends Handler {
440 private static final int MSG_DISPATCH_OWNERSHIP_LOSS = 0;
Vitalii Tomkivd15d8872016-10-04 14:08:56 -0700441 private static final int MSG_DISPATCH_OWNERSHIP_GRANT = 1;
442 private static final int MSG_DISPATCH_FOCUS_CHANGE = 2;
Vitalii Tomkiv46371472016-05-23 16:55:22 -0700443
444 private DispatchHandler(Looper looper) {
445 super(looper);
446 }
447
Vitalii Tomkivd15d8872016-10-04 14:08:56 -0700448 private void requestAppFocusOwnershipLossDispatch(IAppFocusOwnershipCallback callback,
Vitalii Tomkiv46371472016-05-23 16:55:22 -0700449 int appType) {
Vitalii Tomkivd15d8872016-10-04 14:08:56 -0700450 Message msg = obtainMessage(MSG_DISPATCH_OWNERSHIP_LOSS, appType, 0, callback);
451 sendMessage(msg);
452 }
453
454 private void requestAppFocusOwnershipGrantDispatch(IAppFocusOwnershipCallback callback,
455 int appType) {
456 Message msg = obtainMessage(MSG_DISPATCH_OWNERSHIP_GRANT, appType, 0, callback);
Vitalii Tomkiv46371472016-05-23 16:55:22 -0700457 sendMessage(msg);
458 }
459
460 private void requestAppFocusChangeDispatch(IAppFocusListener listener, int appType,
461 boolean active) {
462 Message msg = obtainMessage(MSG_DISPATCH_FOCUS_CHANGE, appType, active ? 1 : 0,
463 listener);
464 sendMessage(msg);
465 }
466
467 @Override
468 public void handleMessage(Message msg) {
469 switch (msg.what) {
470 case MSG_DISPATCH_OWNERSHIP_LOSS:
Vitalii Tomkivd15d8872016-10-04 14:08:56 -0700471 dispatchAppFocusOwnershipLoss((IAppFocusOwnershipCallback) msg.obj, msg.arg1);
472 break;
473 case MSG_DISPATCH_OWNERSHIP_GRANT:
474 dispatchAppFocusOwnershipGrant((IAppFocusOwnershipCallback) msg.obj, msg.arg1);
Vitalii Tomkiv46371472016-05-23 16:55:22 -0700475 break;
476 case MSG_DISPATCH_FOCUS_CHANGE:
477 dispatchAppFocusChange((IAppFocusListener) msg.obj, msg.arg1, msg.arg2 == 1);
478 break;
Vitalii Tomkivd15d8872016-10-04 14:08:56 -0700479 default:
480 Log.e(CarLog.TAG_APP_FOCUS, "Can't dispatch message: " + msg);
Vitalii Tomkiv46371472016-05-23 16:55:22 -0700481 }
482 }
483 }
484
485 private static int[] toIntArray(Set<Integer> intSet) {
486 int[] intArr = new int[intSet.size()];
487 int index = 0;
488 for (Integer value : intSet) {
489 intArr[index++] = value;
490 }
491 return intArr;
492 }
493}