blob: e96c9a541c3f304a4d138aeb5ded224ba2ac6289 [file] [log] [blame]
Hai Zhanga4959e52019-03-06 12:21:07 -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 android.app.role;
18
Hai Zhang26f37d32019-03-06 15:58:39 -080019import android.Manifest;
20import android.annotation.CallbackExecutor;
Hai Zhanga4959e52019-03-06 12:21:07 -080021import android.annotation.NonNull;
Hai Zhang26f37d32019-03-06 15:58:39 -080022import android.annotation.RequiresPermission;
Hai Zhanga4959e52019-03-06 12:21:07 -080023import android.annotation.SystemService;
24import android.annotation.UserIdInt;
25import android.content.ComponentName;
26import android.content.Context;
27import android.content.Intent;
28import android.content.pm.PackageManager;
29import android.content.pm.ResolveInfo;
30import android.os.Binder;
31import android.os.Handler;
32import android.os.IBinder;
Hai Zhang26f37d32019-03-06 15:58:39 -080033import android.os.RemoteCallback;
Hai Zhanga4959e52019-03-06 12:21:07 -080034import android.os.RemoteException;
35import android.util.Log;
36import android.util.SparseArray;
37
38import com.android.internal.annotations.GuardedBy;
39import com.android.internal.infra.AbstractMultiplePendingRequestsRemoteService;
40import com.android.internal.infra.AbstractRemoteService;
41
Hai Zhang26f37d32019-03-06 15:58:39 -080042import java.util.concurrent.Executor;
43import java.util.function.Consumer;
44
Hai Zhanga4959e52019-03-06 12:21:07 -080045/**
46 * Interface for communicating with the role controller.
47 *
48 * @hide
49 */
50@SystemService(Context.ROLE_CONTROLLER_SERVICE)
51public class RoleControllerManager {
52
53 private static final String LOG_TAG = RoleControllerManager.class.getSimpleName();
54
55 private static final Object sRemoteServicesLock = new Object();
56 /**
57 * Global remote services (per user) used by all {@link RoleControllerManager managers}.
58 */
59 @GuardedBy("sRemoteServicesLock")
60 private static final SparseArray<RemoteService> sRemoteServices = new SparseArray<>();
61
62 @NonNull
63 private final RemoteService mRemoteService;
64
65 public RoleControllerManager(@NonNull Context context, @NonNull Handler handler) {
66 synchronized (sRemoteServicesLock) {
67 int userId = context.getUserId();
68 RemoteService remoteService = sRemoteServices.get(userId);
69 if (remoteService == null) {
70 Intent intent = new Intent(RoleControllerService.SERVICE_INTERFACE);
71 PackageManager packageManager = context.getPackageManager();
72 intent.setPackage(packageManager.getPermissionControllerPackageName());
73 ResolveInfo resolveInfo = packageManager.resolveService(intent, 0);
74
75 remoteService = new RemoteService(context.getApplicationContext(),
76 resolveInfo.getComponentInfo().getComponentName(), handler, userId);
77 sRemoteServices.put(userId, remoteService);
78 }
79 mRemoteService = remoteService;
80 }
81 }
82
83 public RoleControllerManager(@NonNull Context context) {
84 this(context, context.getMainThreadHandler());
85 }
86
87 /**
Hai Zhangf5e8ccd2019-03-06 20:12:24 -080088 * @see RoleControllerService#onGrantDefaultRoles()
Hai Zhanga4959e52019-03-06 12:21:07 -080089 */
Hai Zhangf5e8ccd2019-03-06 20:12:24 -080090 public void grantDefaultRoles(@NonNull @CallbackExecutor Executor executor,
91 @NonNull Consumer<Boolean> callback) {
92 mRemoteService.scheduleRequest(new GrantDefaultRolesRequest(mRemoteService, executor,
93 callback));
Hai Zhanga4959e52019-03-06 12:21:07 -080094 }
95
96 /**
Hai Zhangf5e8ccd2019-03-06 20:12:24 -080097 * @see RoleControllerService#onAddRoleHolder(String, String, int)
Hai Zhanga4959e52019-03-06 12:21:07 -080098 */
99 public void onAddRoleHolder(@NonNull String roleName, @NonNull String packageName,
Hai Zhangf5e8ccd2019-03-06 20:12:24 -0800100 @RoleManager.ManageHoldersFlags int flags, @NonNull RemoteCallback callback) {
Hai Zhanga4959e52019-03-06 12:21:07 -0800101 mRemoteService.scheduleRequest(new OnAddRoleHolderRequest(mRemoteService, roleName,
102 packageName, flags, callback));
103 }
104
105 /**
Hai Zhangf5e8ccd2019-03-06 20:12:24 -0800106 * @see RoleControllerService#onRemoveRoleHolder(String, String, int)
Hai Zhanga4959e52019-03-06 12:21:07 -0800107 */
108 public void onRemoveRoleHolder(@NonNull String roleName, @NonNull String packageName,
Hai Zhangf5e8ccd2019-03-06 20:12:24 -0800109 @RoleManager.ManageHoldersFlags int flags, @NonNull RemoteCallback callback) {
Hai Zhanga4959e52019-03-06 12:21:07 -0800110 mRemoteService.scheduleRequest(new OnRemoveRoleHolderRequest(mRemoteService, roleName,
111 packageName, flags, callback));
112 }
113
114 /**
Hai Zhangf5e8ccd2019-03-06 20:12:24 -0800115 * @see RoleControllerService#onClearRoleHolders(String, int)
Hai Zhanga4959e52019-03-06 12:21:07 -0800116 */
117 public void onClearRoleHolders(@NonNull String roleName,
Hai Zhangf5e8ccd2019-03-06 20:12:24 -0800118 @RoleManager.ManageHoldersFlags int flags, @NonNull RemoteCallback callback) {
Hai Zhanga4959e52019-03-06 12:21:07 -0800119 mRemoteService.scheduleRequest(new OnClearRoleHoldersRequest(mRemoteService, roleName,
120 flags, callback));
121 }
122
123 /**
124 * @see RoleControllerService#onSmsKillSwitchToggled(boolean)
125 */
126 public void onSmsKillSwitchToggled(boolean enabled) {
127 mRemoteService.scheduleAsyncRequest(new OnSmsKillSwitchToggledRequest(enabled));
128 }
129
130 /**
Hai Zhang26f37d32019-03-06 15:58:39 -0800131 * @see RoleControllerService#onIsApplicationQualifiedForRole(String, String)
132 */
133 @RequiresPermission(Manifest.permission.MANAGE_ROLE_HOLDERS)
134 public void isApplicationQualifiedForRole(@NonNull String roleName, @NonNull String packageName,
135 @NonNull @CallbackExecutor Executor executor, @NonNull Consumer<Boolean> callback) {
136 mRemoteService.scheduleRequest(new IsApplicationQualifiedForRoleRequest(mRemoteService,
137 roleName, packageName, executor, callback));
138 }
139
140 /**
141 * @see RoleControllerService#onIsRoleVisible(String)
142 */
143 @RequiresPermission(Manifest.permission.MANAGE_ROLE_HOLDERS)
144 public void isRoleVisible(@NonNull String roleName,
145 @NonNull @CallbackExecutor Executor executor, @NonNull Consumer<Boolean> callback) {
146 mRemoteService.scheduleRequest(new IsRoleVisibleRequest(mRemoteService, roleName, executor,
147 callback));
148 }
149
150 /**
Hai Zhanga4959e52019-03-06 12:21:07 -0800151 * Connection to the remote service.
152 */
153 private static final class RemoteService extends AbstractMultiplePendingRequestsRemoteService<
154 RemoteService, IRoleController> {
155
156 private static final long UNBIND_DELAY_MILLIS = 15 * 1000;
157 private static final long REQUEST_TIMEOUT_MILLIS = 15 * 1000;
158
159 /**
160 * Create a connection to the remote service
161 *
162 * @param context the context to use
163 * @param componentName the component of the service to connect to
164 * @param handler the handler for binding service and callbacks
165 * @param userId the user whom remote service should be connected as
166 */
167 RemoteService(@NonNull Context context, @NonNull ComponentName componentName,
168 @NonNull Handler handler, @UserIdInt int userId) {
169 super(context, RoleControllerService.SERVICE_INTERFACE, componentName, userId,
170 service -> Log.e(LOG_TAG, "RemoteService " + service + " died"), handler, false,
171 false, 1);
172 }
173
174 /**
175 * @return The default handler used by this service.
176 */
177 @NonNull
178 public Handler getHandler() {
179 return mHandler;
180 }
181
182 @Override
183 protected @NonNull IRoleController getServiceInterface(@NonNull IBinder binder) {
184 return IRoleController.Stub.asInterface(binder);
185 }
186
187 @Override
188 protected long getTimeoutIdleBindMillis() {
189 return UNBIND_DELAY_MILLIS;
190 }
191
192 @Override
193 protected long getRemoteRequestMillis() {
194 return REQUEST_TIMEOUT_MILLIS;
195 }
196
197 @Override
198 public void scheduleRequest(
199 @NonNull BasePendingRequest<RemoteService, IRoleController> pendingRequest) {
200 super.scheduleRequest(pendingRequest);
201 }
202
203 @Override
204 public void scheduleAsyncRequest(@NonNull AsyncRequest<IRoleController> request) {
205 super.scheduleAsyncRequest(request);
206 }
207 }
208
209 /**
Hai Zhangf5e8ccd2019-03-06 20:12:24 -0800210 * Request for {@link #grantDefaultRoles(Executor, Consumer)}.
Hai Zhanga4959e52019-03-06 12:21:07 -0800211 */
Hai Zhangf5e8ccd2019-03-06 20:12:24 -0800212 private static final class GrantDefaultRolesRequest
Hai Zhanga4959e52019-03-06 12:21:07 -0800213 extends AbstractRemoteService.PendingRequest<RemoteService, IRoleController> {
214
215 @NonNull
Hai Zhangf5e8ccd2019-03-06 20:12:24 -0800216 private final Executor mExecutor;
217 @NonNull
218 private final Consumer<Boolean> mCallback;
Hai Zhanga4959e52019-03-06 12:21:07 -0800219
220 @NonNull
Hai Zhangf5e8ccd2019-03-06 20:12:24 -0800221 private final RemoteCallback mRemoteCallback;
Hai Zhanga4959e52019-03-06 12:21:07 -0800222
Hai Zhangf5e8ccd2019-03-06 20:12:24 -0800223 private GrantDefaultRolesRequest(@NonNull RemoteService service,
224 @NonNull @CallbackExecutor Executor executor, @NonNull Consumer<Boolean> callback) {
Hai Zhanga4959e52019-03-06 12:21:07 -0800225 super(service);
226
Hai Zhangf5e8ccd2019-03-06 20:12:24 -0800227 mExecutor = executor;
Hai Zhanga4959e52019-03-06 12:21:07 -0800228 mCallback = callback;
229
Hai Zhangf5e8ccd2019-03-06 20:12:24 -0800230 mRemoteCallback = new RemoteCallback(result -> mExecutor.execute(() -> {
231 long token = Binder.clearCallingIdentity();
232 try {
233 boolean successful = result != null;
234 mCallback.accept(successful);
235 } finally {
236 Binder.restoreCallingIdentity(token);
237 finish();
Hai Zhanga4959e52019-03-06 12:21:07 -0800238 }
Hai Zhangf5e8ccd2019-03-06 20:12:24 -0800239 }));
Hai Zhanga4959e52019-03-06 12:21:07 -0800240 }
241
242 @Override
243 protected void onTimeout(@NonNull RemoteService remoteService) {
Hai Zhangf5e8ccd2019-03-06 20:12:24 -0800244 mExecutor.execute(() -> mCallback.accept(false));
Hai Zhanga4959e52019-03-06 12:21:07 -0800245 }
246
247 @Override
248 public void run() {
249 try {
Hai Zhangf5e8ccd2019-03-06 20:12:24 -0800250 getService().getServiceInterface().grantDefaultRoles(mRemoteCallback);
Hai Zhanga4959e52019-03-06 12:21:07 -0800251 } catch (RemoteException e) {
Hai Zhangf5e8ccd2019-03-06 20:12:24 -0800252 Log.e(LOG_TAG, "Error calling grantDefaultRoles()", e);
Hai Zhanga4959e52019-03-06 12:21:07 -0800253 }
254 }
255 }
256
257 /**
Hai Zhangf5e8ccd2019-03-06 20:12:24 -0800258 * Request for {@link #onAddRoleHolder(String, String, int, RemoteCallback)}.
Hai Zhanga4959e52019-03-06 12:21:07 -0800259 */
260 private static final class OnAddRoleHolderRequest
261 extends AbstractRemoteService.PendingRequest<RemoteService, IRoleController> {
262
263 @NonNull
264 private final String mRoleName;
265 @NonNull
266 private final String mPackageName;
267 @RoleManager.ManageHoldersFlags
268 private final int mFlags;
269 @NonNull
Hai Zhangf5e8ccd2019-03-06 20:12:24 -0800270 private final RemoteCallback mCallback;
Hai Zhanga4959e52019-03-06 12:21:07 -0800271
272 @NonNull
Hai Zhangf5e8ccd2019-03-06 20:12:24 -0800273 private final RemoteCallback mRemoteCallback;
Hai Zhanga4959e52019-03-06 12:21:07 -0800274
275 private OnAddRoleHolderRequest(@NonNull RemoteService service, @NonNull String roleName,
276 @NonNull String packageName, @RoleManager.ManageHoldersFlags int flags,
Hai Zhangf5e8ccd2019-03-06 20:12:24 -0800277 @NonNull RemoteCallback callback) {
Hai Zhanga4959e52019-03-06 12:21:07 -0800278 super(service);
279
280 mRoleName = roleName;
281 mPackageName = packageName;
282 mFlags = flags;
283 mCallback = callback;
284
Hai Zhangf5e8ccd2019-03-06 20:12:24 -0800285 mRemoteCallback = new RemoteCallback(result -> {
286 long token = Binder.clearCallingIdentity();
287 try {
288 mCallback.sendResult(result);
289 } finally {
290 Binder.restoreCallingIdentity(token);
291 finish();
Hai Zhanga4959e52019-03-06 12:21:07 -0800292 }
Hai Zhangf5e8ccd2019-03-06 20:12:24 -0800293 });
Hai Zhanga4959e52019-03-06 12:21:07 -0800294 }
295
296 @Override
297 protected void onTimeout(@NonNull RemoteService remoteService) {
Hai Zhangf5e8ccd2019-03-06 20:12:24 -0800298 mCallback.sendResult(null);
Hai Zhanga4959e52019-03-06 12:21:07 -0800299 }
300
301 @Override
302 public void run() {
303 try {
304 getService().getServiceInterface().onAddRoleHolder(mRoleName, mPackageName, mFlags,
305 mRemoteCallback);
306 } catch (RemoteException e) {
307 Log.e(LOG_TAG, "Error calling onAddRoleHolder()", e);
308 }
309 }
310 }
311
312 /**
Hai Zhangf5e8ccd2019-03-06 20:12:24 -0800313 * Request for {@link #onRemoveRoleHolder(String, String, int, RemoteCallback)}.
Hai Zhanga4959e52019-03-06 12:21:07 -0800314 */
315 private static final class OnRemoveRoleHolderRequest
316 extends AbstractRemoteService.PendingRequest<RemoteService, IRoleController> {
317
318 @NonNull
319 private final String mRoleName;
320 @NonNull
321 private final String mPackageName;
322 @RoleManager.ManageHoldersFlags
323 private final int mFlags;
324 @NonNull
Hai Zhangf5e8ccd2019-03-06 20:12:24 -0800325 private final RemoteCallback mCallback;
Hai Zhanga4959e52019-03-06 12:21:07 -0800326
327 @NonNull
Hai Zhangf5e8ccd2019-03-06 20:12:24 -0800328 private final RemoteCallback mRemoteCallback;
Hai Zhanga4959e52019-03-06 12:21:07 -0800329
330 private OnRemoveRoleHolderRequest(@NonNull RemoteService service, @NonNull String roleName,
331 @NonNull String packageName, @RoleManager.ManageHoldersFlags int flags,
Hai Zhangf5e8ccd2019-03-06 20:12:24 -0800332 @NonNull RemoteCallback callback) {
Hai Zhanga4959e52019-03-06 12:21:07 -0800333 super(service);
334
335 mRoleName = roleName;
336 mPackageName = packageName;
337 mFlags = flags;
338 mCallback = callback;
339
Hai Zhangf5e8ccd2019-03-06 20:12:24 -0800340 mRemoteCallback = new RemoteCallback(result -> {
341 long token = Binder.clearCallingIdentity();
342 try {
343 mCallback.sendResult(result);
344 } finally {
345 Binder.restoreCallingIdentity(token);
346 finish();
Hai Zhanga4959e52019-03-06 12:21:07 -0800347 }
Hai Zhangf5e8ccd2019-03-06 20:12:24 -0800348 });
Hai Zhanga4959e52019-03-06 12:21:07 -0800349 }
350
351 @Override
352 protected void onTimeout(@NonNull RemoteService remoteService) {
Hai Zhangf5e8ccd2019-03-06 20:12:24 -0800353 mCallback.sendResult(null);
Hai Zhanga4959e52019-03-06 12:21:07 -0800354 }
355
356 @Override
357 public void run() {
358 try {
359 getService().getServiceInterface().onRemoveRoleHolder(mRoleName, mPackageName,
360 mFlags, mRemoteCallback);
361 } catch (RemoteException e) {
362 Log.e(LOG_TAG, "Error calling onRemoveRoleHolder()", e);
363 }
364 }
365 }
366
367 /**
Hai Zhangf5e8ccd2019-03-06 20:12:24 -0800368 * Request for {@link #onClearRoleHolders(String, int, RemoteCallback)}.
Hai Zhanga4959e52019-03-06 12:21:07 -0800369 */
370 private static final class OnClearRoleHoldersRequest
371 extends AbstractRemoteService.PendingRequest<RemoteService, IRoleController> {
372
373 @NonNull
374 private final String mRoleName;
375 @RoleManager.ManageHoldersFlags
376 private final int mFlags;
377 @NonNull
Hai Zhangf5e8ccd2019-03-06 20:12:24 -0800378 private final RemoteCallback mCallback;
Hai Zhanga4959e52019-03-06 12:21:07 -0800379
380 @NonNull
Hai Zhangf5e8ccd2019-03-06 20:12:24 -0800381 private final RemoteCallback mRemoteCallback;
Hai Zhanga4959e52019-03-06 12:21:07 -0800382
383 private OnClearRoleHoldersRequest(@NonNull RemoteService service, @NonNull String roleName,
Hai Zhangf5e8ccd2019-03-06 20:12:24 -0800384 @RoleManager.ManageHoldersFlags int flags, @NonNull RemoteCallback callback) {
Hai Zhanga4959e52019-03-06 12:21:07 -0800385 super(service);
386
387 mRoleName = roleName;
388 mFlags = flags;
389 mCallback = callback;
390
Hai Zhangf5e8ccd2019-03-06 20:12:24 -0800391 mRemoteCallback = new RemoteCallback(result -> {
392 long token = Binder.clearCallingIdentity();
393 try {
394 mCallback.sendResult(result);
395 } finally {
396 Binder.restoreCallingIdentity(token);
397 finish();
Hai Zhanga4959e52019-03-06 12:21:07 -0800398 }
Hai Zhangf5e8ccd2019-03-06 20:12:24 -0800399 });
Hai Zhanga4959e52019-03-06 12:21:07 -0800400 }
401
402 @Override
403 protected void onTimeout(@NonNull RemoteService remoteService) {
Hai Zhangf5e8ccd2019-03-06 20:12:24 -0800404 mCallback.sendResult(null);
Hai Zhanga4959e52019-03-06 12:21:07 -0800405 }
406
407 @Override
408 public void run() {
409 try {
410 getService().getServiceInterface().onClearRoleHolders(mRoleName, mFlags,
411 mRemoteCallback);
412 } catch (RemoteException e) {
413 Log.e(LOG_TAG, "Error calling onClearRoleHolders()", e);
414 }
415 }
416 }
417
418 /**
419 * Request for {@link #onSmsKillSwitchToggled(boolean)}
420 */
421 private static final class OnSmsKillSwitchToggledRequest
422 implements AbstractRemoteService.AsyncRequest<IRoleController> {
423
424 private final boolean mEnabled;
425
426 private OnSmsKillSwitchToggledRequest(boolean enabled) {
427 mEnabled = enabled;
428 }
429
430 @Override
431 public void run(@NonNull IRoleController service) {
432 try {
433 service.onSmsKillSwitchToggled(mEnabled);
434 } catch (RemoteException e) {
435 Log.e(LOG_TAG, "Error calling onSmsKillSwitchToggled()", e);
436 }
437 }
438 }
Hai Zhang26f37d32019-03-06 15:58:39 -0800439
440 /**
441 * Request for {@link #isApplicationQualifiedForRole(String, String, Executor, Consumer)}
442 */
443 private static final class IsApplicationQualifiedForRoleRequest extends
444 AbstractRemoteService.PendingRequest<RemoteService, IRoleController> {
445
446 @NonNull
447 private final String mRoleName;
448 @NonNull
449 private final String mPackageName;
450 @NonNull
451 private final Executor mExecutor;
452 @NonNull
453 private final Consumer<Boolean> mCallback;
454
455 @NonNull
456 private final RemoteCallback mRemoteCallback;
457
458 private IsApplicationQualifiedForRoleRequest(@NonNull RemoteService service,
459 @NonNull String roleName, @NonNull String packageName,
460 @CallbackExecutor @NonNull Executor executor, @NonNull Consumer<Boolean> callback) {
461 super(service);
462
463 mRoleName = roleName;
464 mPackageName = packageName;
465 mExecutor = executor;
466 mCallback = callback;
467
468 mRemoteCallback = new RemoteCallback(result -> mExecutor.execute(() -> {
469 long token = Binder.clearCallingIdentity();
470 try {
Hai Zhangf5e8ccd2019-03-06 20:12:24 -0800471 boolean qualified = result != null;
Hai Zhang26f37d32019-03-06 15:58:39 -0800472 mCallback.accept(qualified);
473 } finally {
474 Binder.restoreCallingIdentity(token);
475 finish();
476 }
477 }));
478 }
479
480 @Override
481 protected void onTimeout(RemoteService remoteService) {
482 mExecutor.execute(() -> mCallback.accept(false));
483 }
484
485 @Override
486 public void run() {
487 try {
488 getService().getServiceInterface().isApplicationQualifiedForRole(mRoleName,
489 mPackageName, mRemoteCallback);
490 } catch (RemoteException e) {
491 Log.e(LOG_TAG, "Error calling isApplicationQualifiedForRole()", e);
492 }
493 }
494 }
495
496 /**
497 * Request for {@link #isRoleVisible(String, Executor, Consumer)}
498 */
499 private static final class IsRoleVisibleRequest
500 extends AbstractRemoteService.PendingRequest<RemoteService, IRoleController> {
501
502 @NonNull
503 private final String mRoleName;
504 @NonNull
505 private final Executor mExecutor;
506 @NonNull
507 private final Consumer<Boolean> mCallback;
508
509 @NonNull
510 private final RemoteCallback mRemoteCallback;
511
512 private IsRoleVisibleRequest(@NonNull RemoteService service, @NonNull String roleName,
513 @CallbackExecutor @NonNull Executor executor, @NonNull Consumer<Boolean> callback) {
514 super(service);
515
516 mRoleName = roleName;
517 mExecutor = executor;
518 mCallback = callback;
519
520 mRemoteCallback = new RemoteCallback(result -> mExecutor.execute(() -> {
521 long token = Binder.clearCallingIdentity();
522 try {
Hai Zhangf5e8ccd2019-03-06 20:12:24 -0800523 boolean visible = result != null;
Hai Zhang26f37d32019-03-06 15:58:39 -0800524 mCallback.accept(visible);
525 } finally {
526 Binder.restoreCallingIdentity(token);
527 finish();
528 }
529 }));
530 }
531
532 @Override
533 protected void onTimeout(RemoteService remoteService) {
534 mExecutor.execute(() -> mCallback.accept(false));
535 }
536
537 @Override
538 public void run() {
539 try {
540 getService().getServiceInterface().isRoleVisible(mRoleName, mRemoteCallback);
541 } catch (RemoteException e) {
542 Log.e(LOG_TAG, "Error calling isRoleVisible()", e);
543 }
544 }
545 }
Hai Zhanga4959e52019-03-06 12:21:07 -0800546}