blob: 17d3066bd37a9bd62a8c64f83087ec65916c8d9e [file] [log] [blame]
Hai Zhangb7776682018-09-25 15:10:57 -07001/*
2 * Copyright (C) 2018 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.role;
18
19import android.Manifest;
20import android.annotation.CheckResult;
Eugene Suslad469fc12018-11-20 17:09:07 -080021import android.annotation.MainThread;
Hai Zhangb7776682018-09-25 15:10:57 -070022import android.annotation.NonNull;
23import android.annotation.Nullable;
24import android.annotation.UserIdInt;
Hai Zhang31d06ba2018-12-06 18:14:42 -080025import android.annotation.WorkerThread;
Hai Zhangb7776682018-09-25 15:10:57 -070026import android.app.ActivityManager;
27import android.app.AppOpsManager;
Hai Zhang31d06ba2018-12-06 18:14:42 -080028import android.app.role.IOnRoleHoldersChangedListener;
Hai Zhangb7776682018-09-25 15:10:57 -070029import android.app.role.IRoleManager;
30import android.app.role.IRoleManagerCallback;
31import android.app.role.RoleManager;
32import android.content.BroadcastReceiver;
33import android.content.Context;
34import android.content.Intent;
35import android.content.IntentFilter;
Hongming Jin08496b02019-01-25 13:41:52 -080036import android.content.PermissionChecker;
37import android.content.pm.PackageManager;
38import android.content.pm.PackageManager.NameNotFoundException;
Eugene Suslaabdefba2018-11-09 18:06:43 -080039import android.content.pm.PackageManagerInternal;
40import android.content.pm.Signature;
Eugene Susla34969062019-01-29 11:02:02 -080041import android.database.ContentObserver;
Hongming Jin08496b02019-01-25 13:41:52 -080042import android.database.CursorWindow;
Eugene Susla34969062019-01-29 11:02:02 -080043import android.net.Uri;
Eugene Susla4ab95112018-12-17 14:45:11 -080044import android.os.Binder;
Hongming Jin08496b02019-01-25 13:41:52 -080045import android.os.Bundle;
Hai Zhang31d06ba2018-12-06 18:14:42 -080046import android.os.Handler;
Hongming Jin08496b02019-01-25 13:41:52 -080047import android.os.RemoteCallback;
Hai Zhang31d06ba2018-12-06 18:14:42 -080048import android.os.RemoteCallbackList;
49import android.os.RemoteException;
Jeff Sharkey6260c582018-11-27 13:05:15 -070050import android.os.ResultReceiver;
51import android.os.ShellCallback;
Hai Zhangb7776682018-09-25 15:10:57 -070052import android.os.UserHandle;
53import android.os.UserManagerInternal;
Eugene Susla34969062019-01-29 11:02:02 -080054import android.provider.Settings;
Hongming Jin08496b02019-01-25 13:41:52 -080055import android.service.sms.FinancialSmsService;
56import android.telephony.IFinancialSmsCallback;
Hai Zhangb7776682018-09-25 15:10:57 -070057import android.text.TextUtils;
Philip P. Moltmann70b42ae2019-01-29 16:24:19 -080058import android.util.ArrayMap;
Hai Zhangb7776682018-09-25 15:10:57 -070059import android.util.ArraySet;
Eugene Suslaabdefba2018-11-09 18:06:43 -080060import android.util.PackageUtils;
Hai Zhangb7776682018-09-25 15:10:57 -070061import android.util.Slog;
62import android.util.SparseArray;
Hai Zhang33456fb2018-12-05 17:30:35 -080063import android.util.proto.ProtoOutputStream;
Hai Zhangb7776682018-09-25 15:10:57 -070064
65import com.android.internal.annotations.GuardedBy;
Hai Zhang33456fb2018-12-05 17:30:35 -080066import com.android.internal.util.ArrayUtils;
Eugene Suslaabdefba2018-11-09 18:06:43 -080067import com.android.internal.util.BitUtils;
68import com.android.internal.util.CollectionUtils;
Hai Zhang33456fb2018-12-05 17:30:35 -080069import com.android.internal.util.DumpUtils;
Eugene Suslaabdefba2018-11-09 18:06:43 -080070import com.android.internal.util.FunctionalUtils;
Hai Zhang33456fb2018-12-05 17:30:35 -080071import com.android.internal.util.IndentingPrintWriter;
Hai Zhangb7776682018-09-25 15:10:57 -070072import com.android.internal.util.Preconditions;
Hai Zhang33456fb2018-12-05 17:30:35 -080073import com.android.internal.util.dump.DualDumpOutputStream;
Hai Zhang31d06ba2018-12-06 18:14:42 -080074import com.android.internal.util.function.pooled.PooledLambda;
75import com.android.server.FgThread;
Hai Zhangb7776682018-09-25 15:10:57 -070076import com.android.server.LocalServices;
77import com.android.server.SystemService;
78
Eugene Suslaabdefba2018-11-09 18:06:43 -080079import java.io.ByteArrayOutputStream;
Jeff Sharkey6260c582018-11-27 13:05:15 -070080import java.io.FileDescriptor;
Hai Zhang33456fb2018-12-05 17:30:35 -080081import java.io.PrintWriter;
Hai Zhangb7776682018-09-25 15:10:57 -070082import java.util.ArrayList;
83import java.util.Collections;
84import java.util.List;
Hai Zhang458cedb2018-12-03 15:41:11 -080085import java.util.Objects;
Eugene Suslaa4200f822018-11-09 18:06:43 -080086import java.util.concurrent.CompletableFuture;
87import java.util.concurrent.ExecutionException;
88import java.util.concurrent.TimeUnit;
89import java.util.concurrent.TimeoutException;
Hai Zhangb7776682018-09-25 15:10:57 -070090
91/**
92 * Service for role management.
93 *
94 * @see RoleManager
95 */
Hai Zhang31d06ba2018-12-06 18:14:42 -080096public class RoleManagerService extends SystemService implements RoleUserState.Callback {
Hai Zhangb7776682018-09-25 15:10:57 -070097
98 private static final String LOG_TAG = RoleManagerService.class.getSimpleName();
99
100 @NonNull
101 private final UserManagerInternal mUserManagerInternal;
102 @NonNull
103 private final AppOpsManager mAppOpsManager;
104
105 @NonNull
106 private final Object mLock = new Object();
107
Eugene Susla4ab95112018-12-17 14:45:11 -0800108 @NonNull
109 private final RoleHoldersResolver mLegacyRoleResolver;
110
111 /** @see #getRoleHolders(String, int) */
112 public interface RoleHoldersResolver {
113 /** @return a list of packages that hold a given role for a given user */
Hai Zhang8be463f2019-02-11 16:44:45 -0800114 @NonNull
115 List<String> getRoleHolders(@NonNull String roleName, @UserIdInt int userId);
Eugene Susla4ab95112018-12-17 14:45:11 -0800116 }
117
Hai Zhangb7776682018-09-25 15:10:57 -0700118 /**
119 * Maps user id to its state.
120 */
121 @GuardedBy("mLock")
122 @NonNull
123 private final SparseArray<RoleUserState> mUserStates = new SparseArray<>();
124
125 /**
126 * Maps user id to its controller service.
127 */
128 @GuardedBy("mLock")
129 @NonNull
130 private final SparseArray<RemoteRoleControllerService> mControllerServices =
131 new SparseArray<>();
132
Hai Zhang31d06ba2018-12-06 18:14:42 -0800133 /**
134 * Maps user id to its list of listeners.
135 */
136 @GuardedBy("mLock")
137 @NonNull
138 private final SparseArray<RemoteCallbackList<IOnRoleHoldersChangedListener>> mListeners =
139 new SparseArray<>();
140
141 @NonNull
142 private final Handler mListenerHandler = FgThread.getHandler();
143
Eugene Susla4ab95112018-12-17 14:45:11 -0800144 public RoleManagerService(@NonNull Context context,
145 @NonNull RoleHoldersResolver legacyRoleResolver) {
Hai Zhangb7776682018-09-25 15:10:57 -0700146 super(context);
147
Eugene Susla4ab95112018-12-17 14:45:11 -0800148 mLegacyRoleResolver = legacyRoleResolver;
149
Hai Zhangb7776682018-09-25 15:10:57 -0700150 mUserManagerInternal = LocalServices.getService(UserManagerInternal.class);
151 mAppOpsManager = context.getSystemService(AppOpsManager.class);
152
Hai Zhang85fd0622019-02-01 14:06:04 -0800153 LocalServices.addService(RoleManagerInternal.class, new Internal());
154
155 PackageManagerInternal packageManagerInternal = LocalServices.getService(
156 PackageManagerInternal.class);
157 packageManagerInternal.setDefaultBrowserProvider(new DefaultBrowserProvider());
Hai Zhang8be463f2019-02-11 16:44:45 -0800158 packageManagerInternal.setDefaultHomeProvider(new DefaultHomeProvider());
Philip P. Moltmann70b42ae2019-01-29 16:24:19 -0800159
Hai Zhangb7776682018-09-25 15:10:57 -0700160 registerUserRemovedReceiver();
161 }
162
163 private void registerUserRemovedReceiver() {
164 IntentFilter intentFilter = new IntentFilter();
165 intentFilter.addAction(Intent.ACTION_USER_REMOVED);
166 getContext().registerReceiverAsUser(new BroadcastReceiver() {
167 @Override
Hai Zhang458cedb2018-12-03 15:41:11 -0800168 public void onReceive(@NonNull Context context, @NonNull Intent intent) {
Hai Zhangb7776682018-09-25 15:10:57 -0700169 if (TextUtils.equals(intent.getAction(), Intent.ACTION_USER_REMOVED)) {
170 int userId = intent.getIntExtra(Intent.EXTRA_USER_HANDLE, 0);
171 onRemoveUser(userId);
172 }
173 }
174 }, UserHandle.ALL, intentFilter, null, null);
175 }
176
177 @Override
178 public void onStart() {
179 publishBinderService(Context.ROLE_SERVICE, new Stub());
Eugene Suslad469fc12018-11-20 17:09:07 -0800180
Eugene Susla6d4922722018-11-08 16:25:28 -0800181 //TODO add watch for new user creation and run default grants for them
Eugene Suslad469fc12018-11-20 17:09:07 -0800182
183 IntentFilter intentFilter = new IntentFilter();
184 intentFilter.addAction(Intent.ACTION_PACKAGE_CHANGED);
185 intentFilter.addAction(Intent.ACTION_PACKAGE_ADDED);
186 intentFilter.addAction(Intent.ACTION_PACKAGE_REMOVED);
187 intentFilter.addDataScheme("package");
188 intentFilter.setPriority(IntentFilter.SYSTEM_HIGH_PRIORITY);
189 getContext().registerReceiverAsUser(new BroadcastReceiver() {
190 @Override
191 public void onReceive(Context context, Intent intent) {
192 int userId = UserHandle.getUserId(intent.getIntExtra(Intent.EXTRA_UID, -1));
193 if (RemoteRoleControllerService.DEBUG) {
194 Slog.i(LOG_TAG,
195 "Packages changed - re-running initial grants for user " + userId);
196 }
197 performInitialGrantsIfNecessary(userId);
198 }
Hai Zhanga5d86322019-02-15 18:06:51 -0800199 }, UserHandle.ALL, intentFilter, null, null);
Eugene Susla34969062019-01-29 11:02:02 -0800200
201 getContext().getContentResolver().registerContentObserver(
202 Settings.Global.getUriFor(Settings.Global.SMS_ACCESS_RESTRICTION_ENABLED), false,
203 new ContentObserver(getContext().getMainThreadHandler()) {
204 @Override
205 public void onChange(boolean selfChange, Uri uri, int userId) {
Eugene Susla95cd4bf2019-02-05 14:41:24 -0800206 boolean killSwitchEnabled = Settings.Global.getInt(
207 getContext().getContentResolver(),
208 Settings.Global.SMS_ACCESS_RESTRICTION_ENABLED, 0) == 1;
209 for (int user : mUserManagerInternal.getUserIds()) {
210 if (mUserManagerInternal.isUserRunning(user)) {
211 getOrCreateControllerService(user)
212 .onSmsKillSwitchToggled(killSwitchEnabled);
213 }
214 }
Eugene Susla34969062019-01-29 11:02:02 -0800215 }
216 }, UserHandle.USER_ALL);
Hai Zhangb7776682018-09-25 15:10:57 -0700217 }
218
219 @Override
220 public void onStartUser(@UserIdInt int userId) {
Eugene Suslad469fc12018-11-20 17:09:07 -0800221 performInitialGrantsIfNecessary(userId);
222 }
223
224 @MainThread
225 private void performInitialGrantsIfNecessary(@UserIdInt int userId) {
Eugene Suslaabdefba2018-11-09 18:06:43 -0800226 RoleUserState userState;
Hai Zhangcdc85c52018-12-06 13:56:55 -0800227 userState = getOrCreateUserState(userId);
Eugene Susla4ab95112018-12-17 14:45:11 -0800228
Eugene Suslaabdefba2018-11-09 18:06:43 -0800229 String packagesHash = computeComponentStateHash(userId);
Hai Zhangcdc85c52018-12-06 13:56:55 -0800230 String oldPackagesHash = userState.getPackagesHash();
Hai Zhang33456fb2018-12-05 17:30:35 -0800231 boolean needGrant = !Objects.equals(packagesHash, oldPackagesHash);
Eugene Suslaabdefba2018-11-09 18:06:43 -0800232 if (needGrant) {
Eugene Susla4ab95112018-12-17 14:45:11 -0800233
234 //TODO gradually add more role migrations statements here for remaining roles
235 // Make sure to implement LegacyRoleResolutionPolicy#getRoleHolders
236 // for a given role before adding a migration statement for it here
237 migrateRoleIfNecessary(RoleManager.ROLE_SMS, userId);
Philip P. Moltmann5d894502019-01-17 10:31:00 -0800238 migrateRoleIfNecessary(RoleManager.ROLE_ASSISTANT, userId);
Eugene Susla92b88c72019-01-11 13:31:20 -0800239 migrateRoleIfNecessary(RoleManager.ROLE_DIALER, userId);
Hongming Jin910cd7b2019-01-23 11:19:07 -0800240 migrateRoleIfNecessary(RoleManager.ROLE_EMERGENCY, userId);
Eugene Susla4ab95112018-12-17 14:45:11 -0800241
Eugene Suslaabdefba2018-11-09 18:06:43 -0800242 // Some vital packages state has changed since last role grant
243 // Run grants again
Eugene Susla6d4922722018-11-08 16:25:28 -0800244 Slog.i(LOG_TAG, "Granting default permissions...");
Eugene Suslaa4200f822018-11-09 18:06:43 -0800245 CompletableFuture<Void> result = new CompletableFuture<>();
Hai Zhangcdc85c52018-12-06 13:56:55 -0800246 getOrCreateControllerService(userId).onGrantDefaultRoles(
Eugene Suslaa4200f822018-11-09 18:06:43 -0800247 new IRoleManagerCallback.Stub() {
248 @Override
249 public void onSuccess() {
250 result.complete(null);
251 }
Eugene Suslaa4200f822018-11-09 18:06:43 -0800252 @Override
253 public void onFailure() {
254 result.completeExceptionally(new RuntimeException());
255 }
256 });
257 try {
258 result.get(5, TimeUnit.SECONDS);
Hai Zhangcdc85c52018-12-06 13:56:55 -0800259 userState.setPackagesHash(packagesHash);
Eugene Suslaa4200f822018-11-09 18:06:43 -0800260 } catch (InterruptedException | ExecutionException | TimeoutException e) {
261 Slog.e(LOG_TAG, "Failed to grant defaults for user " + userId, e);
262 }
Eugene Suslaabdefba2018-11-09 18:06:43 -0800263 } else if (RemoteRoleControllerService.DEBUG) {
264 Slog.i(LOG_TAG, "Already ran grants for package state " + packagesHash);
Hai Zhangb7776682018-09-25 15:10:57 -0700265 }
266 }
267
Eugene Susla4ab95112018-12-17 14:45:11 -0800268 private void migrateRoleIfNecessary(String role, @UserIdInt int userId) {
269 // Any role for which we have a record are already migrated
270 RoleUserState userState = getOrCreateUserState(userId);
271 if (!userState.isRoleAvailable(role)) {
Eugene Susla4ab95112018-12-17 14:45:11 -0800272 List<String> roleHolders = mLegacyRoleResolver.getRoleHolders(role, userId);
Hai Zhang7876adb2019-01-15 21:18:41 -0800273 if (roleHolders.isEmpty()) {
274 return;
275 }
Eugene Susla4ab95112018-12-17 14:45:11 -0800276 Slog.i(LOG_TAG, "Migrating " + role + ", legacy holders: " + roleHolders);
Hai Zhang7876adb2019-01-15 21:18:41 -0800277 userState.addRoleName(role);
Eugene Susla4ab95112018-12-17 14:45:11 -0800278 int size = roleHolders.size();
279 for (int i = 0; i < size; i++) {
280 userState.addRoleHolder(role, roleHolders.get(i));
281 }
282 }
283 }
284
Hai Zhang458cedb2018-12-03 15:41:11 -0800285 @Nullable
Hai Zhang31d06ba2018-12-06 18:14:42 -0800286 private static String computeComponentStateHash(@UserIdInt int userId) {
Eugene Suslaabdefba2018-11-09 18:06:43 -0800287 PackageManagerInternal pm = LocalServices.getService(PackageManagerInternal.class);
288 ByteArrayOutputStream out = new ByteArrayOutputStream();
289
290 pm.forEachPackage(FunctionalUtils.uncheckExceptions(pkg -> {
291 out.write(pkg.packageName.getBytes());
292 out.write(BitUtils.toBytes(pkg.getLongVersionCode()));
293 out.write(pm.getApplicationEnabledState(pkg.packageName, userId));
294
295 ArraySet<String> enabledComponents =
296 pm.getEnabledComponents(pkg.packageName, userId);
297 int numComponents = CollectionUtils.size(enabledComponents);
298 for (int i = 0; i < numComponents; i++) {
299 out.write(enabledComponents.valueAt(i).getBytes());
300 }
301
302 ArraySet<String> disabledComponents =
303 pm.getDisabledComponents(pkg.packageName, userId);
304 numComponents = CollectionUtils.size(disabledComponents);
305 for (int i = 0; i < numComponents; i++) {
306 out.write(disabledComponents.valueAt(i).getBytes());
307 }
308 for (Signature signature : pkg.mSigningDetails.signatures) {
309 out.write(signature.toByteArray());
310 }
311 }));
312
313 return PackageUtils.computeSha256Digest(out.toByteArray());
314 }
315
Hai Zhangb7776682018-09-25 15:10:57 -0700316 @NonNull
Hai Zhangcdc85c52018-12-06 13:56:55 -0800317 private RoleUserState getOrCreateUserState(@UserIdInt int userId) {
318 synchronized (mLock) {
319 RoleUserState userState = mUserStates.get(userId);
320 if (userState == null) {
Hai Zhang31d06ba2018-12-06 18:14:42 -0800321 userState = new RoleUserState(userId, this);
Hai Zhangcdc85c52018-12-06 13:56:55 -0800322 mUserStates.put(userId, userState);
323 }
324 return userState;
Hai Zhangb7776682018-09-25 15:10:57 -0700325 }
Hai Zhangb7776682018-09-25 15:10:57 -0700326 }
327
Hai Zhangb7776682018-09-25 15:10:57 -0700328 @NonNull
Hai Zhangcdc85c52018-12-06 13:56:55 -0800329 private RemoteRoleControllerService getOrCreateControllerService(@UserIdInt int userId) {
330 synchronized (mLock) {
331 RemoteRoleControllerService controllerService = mControllerServices.get(userId);
332 if (controllerService == null) {
333 controllerService = new RemoteRoleControllerService(userId, getContext());
334 mControllerServices.put(userId, controllerService);
335 }
336 return controllerService;
Hai Zhangb7776682018-09-25 15:10:57 -0700337 }
Hai Zhangb7776682018-09-25 15:10:57 -0700338 }
339
Hai Zhang31d06ba2018-12-06 18:14:42 -0800340 @Nullable
341 private RemoteCallbackList<IOnRoleHoldersChangedListener> getListeners(@UserIdInt int userId) {
342 synchronized (mLock) {
343 return mListeners.get(userId);
344 }
345 }
346
347 @NonNull
348 private RemoteCallbackList<IOnRoleHoldersChangedListener> getOrCreateListeners(
349 @UserIdInt int userId) {
350 synchronized (mLock) {
351 RemoteCallbackList<IOnRoleHoldersChangedListener> listeners = mListeners.get(userId);
352 if (listeners == null) {
353 listeners = new RemoteCallbackList<>();
354 mListeners.put(userId, listeners);
355 }
356 return listeners;
357 }
358 }
359
Hai Zhangb7776682018-09-25 15:10:57 -0700360 private void onRemoveUser(@UserIdInt int userId) {
Hai Zhang31d06ba2018-12-06 18:14:42 -0800361 RemoteCallbackList<IOnRoleHoldersChangedListener> listeners;
Hai Zhangcdc85c52018-12-06 13:56:55 -0800362 RoleUserState userState;
Hai Zhangb7776682018-09-25 15:10:57 -0700363 synchronized (mLock) {
Hai Zhang31d06ba2018-12-06 18:14:42 -0800364 listeners = mListeners.removeReturnOld(userId);
Hai Zhangb7776682018-09-25 15:10:57 -0700365 mControllerServices.remove(userId);
Hai Zhangcdc85c52018-12-06 13:56:55 -0800366 userState = mUserStates.removeReturnOld(userId);
367 }
Hai Zhang31d06ba2018-12-06 18:14:42 -0800368 if (listeners != null) {
369 listeners.kill();
370 }
Hai Zhangcdc85c52018-12-06 13:56:55 -0800371 if (userState != null) {
372 userState.destroy();
Hai Zhangb7776682018-09-25 15:10:57 -0700373 }
374 }
375
Hai Zhang31d06ba2018-12-06 18:14:42 -0800376 @Override
377 public void onRoleHoldersChanged(@NonNull String roleName, @UserIdInt int userId) {
378 mListenerHandler.sendMessage(PooledLambda.obtainMessage(
379 RoleManagerService::notifyRoleHoldersChanged, this, roleName, userId));
380 }
381
382 @WorkerThread
383 private void notifyRoleHoldersChanged(@NonNull String roleName, @UserIdInt int userId) {
384 RemoteCallbackList<IOnRoleHoldersChangedListener> listeners = getListeners(userId);
Philip P. Moltmann3c4a4802019-01-17 10:31:00 -0800385 if (listeners != null) {
386 notifyRoleHoldersChangedForListeners(listeners, roleName, userId);
Hai Zhang31d06ba2018-12-06 18:14:42 -0800387 }
388
Hai Zhang85fd0622019-02-01 14:06:04 -0800389 RemoteCallbackList<IOnRoleHoldersChangedListener> allUsersListeners = getListeners(
Philip P. Moltmann3c4a4802019-01-17 10:31:00 -0800390 UserHandle.USER_ALL);
Hai Zhang85fd0622019-02-01 14:06:04 -0800391 if (allUsersListeners != null) {
392 notifyRoleHoldersChangedForListeners(allUsersListeners, roleName, userId);
Philip P. Moltmann3c4a4802019-01-17 10:31:00 -0800393 }
394 }
395
396 @WorkerThread
397 private void notifyRoleHoldersChangedForListeners(
398 @NonNull RemoteCallbackList<IOnRoleHoldersChangedListener> listeners,
399 @NonNull String roleName, @UserIdInt int userId) {
Hai Zhang31d06ba2018-12-06 18:14:42 -0800400 int broadcastCount = listeners.beginBroadcast();
401 try {
402 for (int i = 0; i < broadcastCount; i++) {
403 IOnRoleHoldersChangedListener listener = listeners.getBroadcastItem(i);
404 try {
405 listener.onRoleHoldersChanged(roleName, userId);
406 } catch (RemoteException e) {
407 Slog.e(LOG_TAG, "Error calling OnRoleHoldersChangedListener", e);
408 }
409 }
410 } finally {
411 listeners.finishBroadcast();
412 }
413 }
414
Hai Zhangb7776682018-09-25 15:10:57 -0700415 private class Stub extends IRoleManager.Stub {
416
417 @Override
418 public boolean isRoleAvailable(@NonNull String roleName) {
419 Preconditions.checkStringNotEmpty(roleName, "roleName cannot be null or empty");
420
421 int userId = UserHandle.getUserId(getCallingUid());
Hai Zhang85fd0622019-02-01 14:06:04 -0800422 return getOrCreateUserState(userId).isRoleAvailable(roleName);
Hai Zhangb7776682018-09-25 15:10:57 -0700423 }
424
425 @Override
426 public boolean isRoleHeld(@NonNull String roleName, @NonNull String packageName) {
427 Preconditions.checkStringNotEmpty(roleName, "roleName cannot be null or empty");
428 Preconditions.checkStringNotEmpty(packageName, "packageName cannot be null or empty");
429 int callingUid = getCallingUid();
430 mAppOpsManager.checkPackage(callingUid, packageName);
431
432 int userId = UserHandle.getUserId(callingUid);
Hai Zhang85fd0622019-02-01 14:06:04 -0800433 ArraySet<String> roleHolders = getOrCreateUserState(userId).getRoleHolders(roleName);
Hai Zhangb7776682018-09-25 15:10:57 -0700434 if (roleHolders == null) {
435 return false;
436 }
437 return roleHolders.contains(packageName);
438 }
439
440 @NonNull
441 @Override
442 public List<String> getRoleHoldersAsUser(@NonNull String roleName, @UserIdInt int userId) {
443 Preconditions.checkStringNotEmpty(roleName, "roleName cannot be null or empty");
444 if (!mUserManagerInternal.exists(userId)) {
445 Slog.e(LOG_TAG, "user " + userId + " does not exist");
446 return Collections.emptyList();
447 }
Hai Zhang85fd0622019-02-01 14:06:04 -0800448 userId = handleIncomingUser(userId, false, "getRoleHoldersAsUser");
Hai Zhangb7776682018-09-25 15:10:57 -0700449 getContext().enforceCallingOrSelfPermission(Manifest.permission.MANAGE_ROLE_HOLDERS,
450 "getRoleHoldersAsUser");
451
Hai Zhang85fd0622019-02-01 14:06:04 -0800452 ArraySet<String> roleHolders = getOrCreateUserState(userId).getRoleHolders(roleName);
Hai Zhangb7776682018-09-25 15:10:57 -0700453 if (roleHolders == null) {
454 return Collections.emptyList();
455 }
456 return new ArrayList<>(roleHolders);
457 }
458
Hai Zhangb7776682018-09-25 15:10:57 -0700459 @Override
460 public void addRoleHolderAsUser(@NonNull String roleName, @NonNull String packageName,
Hai Zhang71d70362019-02-04 16:17:38 -0800461 @RoleManager.ManageHoldersFlags int flags, @UserIdInt int userId,
462 @NonNull IRoleManagerCallback callback) {
Hai Zhangb7776682018-09-25 15:10:57 -0700463 Preconditions.checkStringNotEmpty(roleName, "roleName cannot be null or empty");
464 Preconditions.checkStringNotEmpty(packageName, "packageName cannot be null or empty");
465 Preconditions.checkNotNull(callback, "callback cannot be null");
466 if (!mUserManagerInternal.exists(userId)) {
467 Slog.e(LOG_TAG, "user " + userId + " does not exist");
468 return;
469 }
Hai Zhang85fd0622019-02-01 14:06:04 -0800470 userId = handleIncomingUser(userId, false, "addRoleHolderAsUser");
Hai Zhangb7776682018-09-25 15:10:57 -0700471 getContext().enforceCallingOrSelfPermission(Manifest.permission.MANAGE_ROLE_HOLDERS,
472 "addRoleHolderAsUser");
473
Hai Zhang71d70362019-02-04 16:17:38 -0800474 getOrCreateControllerService(userId).onAddRoleHolder(roleName, packageName, flags,
475 callback);
Hai Zhangb7776682018-09-25 15:10:57 -0700476 }
477
478 @Override
479 public void removeRoleHolderAsUser(@NonNull String roleName, @NonNull String packageName,
Hai Zhang71d70362019-02-04 16:17:38 -0800480 @RoleManager.ManageHoldersFlags int flags, @UserIdInt int userId,
481 @NonNull IRoleManagerCallback callback) {
Hai Zhangb7776682018-09-25 15:10:57 -0700482 Preconditions.checkStringNotEmpty(roleName, "roleName cannot be null or empty");
483 Preconditions.checkStringNotEmpty(packageName, "packageName cannot be null or empty");
484 Preconditions.checkNotNull(callback, "callback cannot be null");
485 if (!mUserManagerInternal.exists(userId)) {
486 Slog.e(LOG_TAG, "user " + userId + " does not exist");
487 return;
488 }
Hai Zhang85fd0622019-02-01 14:06:04 -0800489 userId = handleIncomingUser(userId, false, "removeRoleHolderAsUser");
Hai Zhangb7776682018-09-25 15:10:57 -0700490 getContext().enforceCallingOrSelfPermission(Manifest.permission.MANAGE_ROLE_HOLDERS,
491 "removeRoleHolderAsUser");
492
Hai Zhang71d70362019-02-04 16:17:38 -0800493 getOrCreateControllerService(userId).onRemoveRoleHolder(roleName, packageName, flags,
Hai Zhangb7776682018-09-25 15:10:57 -0700494 callback);
495 }
496
497 @Override
Hai Zhang71d70362019-02-04 16:17:38 -0800498 public void clearRoleHoldersAsUser(@NonNull String roleName,
499 @RoleManager.ManageHoldersFlags int flags, @UserIdInt int userId,
Hai Zhangb7776682018-09-25 15:10:57 -0700500 @NonNull IRoleManagerCallback callback) {
501 Preconditions.checkStringNotEmpty(roleName, "roleName cannot be null or empty");
502 Preconditions.checkNotNull(callback, "callback cannot be null");
503 if (!mUserManagerInternal.exists(userId)) {
504 Slog.e(LOG_TAG, "user " + userId + " does not exist");
505 return;
506 }
Hai Zhang85fd0622019-02-01 14:06:04 -0800507 userId = handleIncomingUser(userId, false, "clearRoleHoldersAsUser");
Hai Zhangb7776682018-09-25 15:10:57 -0700508 getContext().enforceCallingOrSelfPermission(Manifest.permission.MANAGE_ROLE_HOLDERS,
509 "clearRoleHoldersAsUser");
Hai Zhang87ed09a2018-10-22 10:43:31 -0700510
Hai Zhang71d70362019-02-04 16:17:38 -0800511 getOrCreateControllerService(userId).onClearRoleHolders(roleName, flags, callback);
Hai Zhangb7776682018-09-25 15:10:57 -0700512 }
513
Hai Zhang87ed09a2018-10-22 10:43:31 -0700514 @Override
Hai Zhang31d06ba2018-12-06 18:14:42 -0800515 public void addOnRoleHoldersChangedListenerAsUser(
516 @NonNull IOnRoleHoldersChangedListener listener, @UserIdInt int userId) {
517 Preconditions.checkNotNull(listener, "listener cannot be null");
Philip P. Moltmann3c4a4802019-01-17 10:31:00 -0800518 if (userId != UserHandle.USER_ALL && !mUserManagerInternal.exists(userId)) {
Hai Zhang31d06ba2018-12-06 18:14:42 -0800519 Slog.e(LOG_TAG, "user " + userId + " does not exist");
520 return;
521 }
Hai Zhang85fd0622019-02-01 14:06:04 -0800522 userId = handleIncomingUser(userId, true, "addOnRoleHoldersChangedListenerAsUser");
Hai Zhang31d06ba2018-12-06 18:14:42 -0800523 getContext().enforceCallingOrSelfPermission(Manifest.permission.OBSERVE_ROLE_HOLDERS,
524 "addOnRoleHoldersChangedListenerAsUser");
525
526 RemoteCallbackList<IOnRoleHoldersChangedListener> listeners = getOrCreateListeners(
527 userId);
528 listeners.register(listener);
529 }
530
531 @Override
532 public void removeOnRoleHoldersChangedListenerAsUser(
533 @NonNull IOnRoleHoldersChangedListener listener, @UserIdInt int userId) {
534 Preconditions.checkNotNull(listener, "listener cannot be null");
Philip P. Moltmann3c4a4802019-01-17 10:31:00 -0800535 if (userId != UserHandle.USER_ALL && !mUserManagerInternal.exists(userId)) {
Hai Zhang31d06ba2018-12-06 18:14:42 -0800536 Slog.e(LOG_TAG, "user " + userId + " does not exist");
537 return;
538 }
Hai Zhang85fd0622019-02-01 14:06:04 -0800539 userId = handleIncomingUser(userId, true, "removeOnRoleHoldersChangedListenerAsUser");
Hai Zhang31d06ba2018-12-06 18:14:42 -0800540 getContext().enforceCallingOrSelfPermission(Manifest.permission.OBSERVE_ROLE_HOLDERS,
541 "removeOnRoleHoldersChangedListenerAsUser");
542
543 RemoteCallbackList<IOnRoleHoldersChangedListener> listeners = getListeners(userId);
544 if (listener == null) {
545 return;
546 }
547 listeners.unregister(listener);
548 }
549
550 @Override
Hai Zhang8e60a8f2018-11-20 11:21:09 -0800551 public void setRoleNamesFromController(@NonNull List<String> roleNames) {
552 Preconditions.checkNotNull(roleNames, "roleNames cannot be null");
553 getContext().enforceCallingOrSelfPermission(
554 RoleManager.PERMISSION_MANAGE_ROLES_FROM_CONTROLLER,
555 "setRoleNamesFromController");
556
557 int userId = UserHandle.getCallingUserId();
Hai Zhang85fd0622019-02-01 14:06:04 -0800558 getOrCreateUserState(userId).setRoleNames(roleNames);
Hai Zhang8e60a8f2018-11-20 11:21:09 -0800559 }
560
561 @Override
Hai Zhang87ed09a2018-10-22 10:43:31 -0700562 public boolean addRoleHolderFromController(@NonNull String roleName,
563 @NonNull String packageName) {
564 Preconditions.checkStringNotEmpty(roleName, "roleName cannot be null or empty");
565 Preconditions.checkStringNotEmpty(packageName, "packageName cannot be null or empty");
566 getContext().enforceCallingOrSelfPermission(
Hai Zhang8e60a8f2018-11-20 11:21:09 -0800567 RoleManager.PERMISSION_MANAGE_ROLES_FROM_CONTROLLER,
Hai Zhang87ed09a2018-10-22 10:43:31 -0700568 "addRoleHolderFromController");
569
570 int userId = UserHandle.getCallingUserId();
Hai Zhang85fd0622019-02-01 14:06:04 -0800571 return getOrCreateUserState(userId).addRoleHolder(roleName, packageName);
Hai Zhang87ed09a2018-10-22 10:43:31 -0700572 }
573
574 @Override
575 public boolean removeRoleHolderFromController(@NonNull String roleName,
576 @NonNull String packageName) {
577 Preconditions.checkStringNotEmpty(roleName, "roleName cannot be null or empty");
578 Preconditions.checkStringNotEmpty(packageName, "packageName cannot be null or empty");
579 getContext().enforceCallingOrSelfPermission(
Hai Zhang8e60a8f2018-11-20 11:21:09 -0800580 RoleManager.PERMISSION_MANAGE_ROLES_FROM_CONTROLLER,
Hai Zhang87ed09a2018-10-22 10:43:31 -0700581 "removeRoleHolderFromController");
582
583 int userId = UserHandle.getCallingUserId();
Hai Zhang85fd0622019-02-01 14:06:04 -0800584 return getOrCreateUserState(userId).removeRoleHolder(roleName, packageName);
Hai Zhang87ed09a2018-10-22 10:43:31 -0700585 }
586
Eugene Suslaa2a80322018-12-12 17:09:38 -0800587 @Override
588 public List<String> getHeldRolesFromController(@NonNull String packageName) {
589 Preconditions.checkStringNotEmpty(packageName, "packageName cannot be null or empty");
590 getContext().enforceCallingOrSelfPermission(
591 RoleManager.PERMISSION_MANAGE_ROLES_FROM_CONTROLLER,
592 "getRolesHeldFromController");
593
594 int userId = UserHandle.getCallingUserId();
Hai Zhang85fd0622019-02-01 14:06:04 -0800595 return getOrCreateUserState(userId).getHeldRoles(packageName);
Eugene Suslaa2a80322018-12-12 17:09:38 -0800596 }
597
Hai Zhangb7776682018-09-25 15:10:57 -0700598 @CheckResult
Hai Zhang85fd0622019-02-01 14:06:04 -0800599 private int handleIncomingUser(@UserIdInt int userId, boolean allowAll,
600 @NonNull String name) {
Hai Zhangb7776682018-09-25 15:10:57 -0700601 return ActivityManager.handleIncomingUser(getCallingPid(), getCallingUid(), userId,
Philip P. Moltmann3c4a4802019-01-17 10:31:00 -0800602 allowAll, true, name, null);
Hai Zhangb7776682018-09-25 15:10:57 -0700603 }
Jeff Sharkey6260c582018-11-27 13:05:15 -0700604
605 @Override
Hai Zhang458cedb2018-12-03 15:41:11 -0800606 public void onShellCommand(@Nullable FileDescriptor in, @Nullable FileDescriptor out,
607 @Nullable FileDescriptor err, @NonNull String[] args,
608 @Nullable ShellCallback callback, @NonNull ResultReceiver resultReceiver) {
609 new RoleManagerShellCommand(this).exec(this, in, out, err, args, callback,
610 resultReceiver);
Jeff Sharkey6260c582018-11-27 13:05:15 -0700611 }
Hai Zhang33456fb2018-12-05 17:30:35 -0800612
613 @Override
Eugene Susla4ab95112018-12-17 14:45:11 -0800614 public String getDefaultSmsPackage(int userId) {
615 long identity = Binder.clearCallingIdentity();
616 try {
617 return CollectionUtils.firstOrNull(
618 getRoleHoldersAsUser(RoleManager.ROLE_SMS, userId));
619 } finally {
620 Binder.restoreCallingIdentity(identity);
621 }
622 }
623
624 @Override
Hai Zhang33456fb2018-12-05 17:30:35 -0800625 protected void dump(@NonNull FileDescriptor fd, @NonNull PrintWriter fout,
626 @Nullable String[] args) {
627 if (!DumpUtils.checkDumpPermission(getContext(), LOG_TAG, fout)) {
628 return;
629 }
630
631 boolean dumpAsProto = args != null && ArrayUtils.contains(args, "--proto");
632 DualDumpOutputStream dumpOutputStream;
633 if (dumpAsProto) {
634 dumpOutputStream = new DualDumpOutputStream(new ProtoOutputStream(fd));
635 } else {
636 fout.println("ROLE MANAGER STATE (dumpsys role):");
637 dumpOutputStream = new DualDumpOutputStream(new IndentingPrintWriter(fout, " "));
638 }
639
Hai Zhangcdc85c52018-12-06 13:56:55 -0800640 int[] userIds = mUserManagerInternal.getUserIds();
641 int userIdsLength = userIds.length;
642 for (int i = 0; i < userIdsLength; i++) {
643 int userId = userIds[i];
Hai Zhang33456fb2018-12-05 17:30:35 -0800644
Hai Zhangcdc85c52018-12-06 13:56:55 -0800645 RoleUserState userState = getOrCreateUserState(userId);
646 userState.dump(dumpOutputStream, "user_states",
647 RoleManagerServiceDumpProto.USER_STATES);
Hai Zhang33456fb2018-12-05 17:30:35 -0800648 }
649
650 dumpOutputStream.flush();
651 }
Hongming Jin08496b02019-01-25 13:41:52 -0800652
653 /**
654 * Get filtered SMS messages for financial app.
655 */
656 @Override
657 public void getSmsMessagesForFinancialApp(
658 String callingPkg, Bundle params, IFinancialSmsCallback callback) {
659 int mode = PermissionChecker.checkCallingOrSelfPermission(
660 getContext(),
661 AppOpsManager.OPSTR_SMS_FINANCIAL_TRANSACTIONS);
662
663 if (mode == PermissionChecker.PERMISSION_GRANTED) {
664 FinancialSmsManager financialSmsManager = new FinancialSmsManager(getContext());
665 financialSmsManager.getSmsMessages(new RemoteCallback((result) -> {
666 CursorWindow messages = null;
667 if (result == null) {
668 Slog.w(LOG_TAG, "result is null.");
669 } else {
670 messages = result.getParcelable(FinancialSmsService.EXTRA_SMS_MSGS);
671 }
672 try {
673 callback.onGetSmsMessagesForFinancialApp(messages);
674 } catch (RemoteException e) {
675 // do nothing
676 }
677 }), params);
678 } else {
679 try {
680 callback.onGetSmsMessagesForFinancialApp(null);
681 } catch (RemoteException e) {
682 // do nothing
683 }
684 }
685 }
686
687 private int getUidForPackage(String packageName) {
688 long ident = Binder.clearCallingIdentity();
689 try {
690 return getContext().getPackageManager().getApplicationInfo(packageName,
691 PackageManager.MATCH_ANY_USER).uid;
692 } catch (NameNotFoundException nnfe) {
693 return -1;
694 } finally {
695 Binder.restoreCallingIdentity(ident);
696 }
697 }
Hai Zhangb7776682018-09-25 15:10:57 -0700698 }
Philip P. Moltmann70b42ae2019-01-29 16:24:19 -0800699
Hai Zhang85fd0622019-02-01 14:06:04 -0800700 private class Internal extends RoleManagerInternal {
Philip P. Moltmann70b42ae2019-01-29 16:24:19 -0800701
702 @NonNull
703 @Override
Hai Zhang85fd0622019-02-01 14:06:04 -0800704 public ArrayMap<String, ArraySet<String>> getRolesAndHolders(@UserIdInt int userId) {
705 return getOrCreateUserState(userId).getRolesAndHolders();
706 }
707 }
708
709 private class DefaultBrowserProvider implements PackageManagerInternal.DefaultBrowserProvider {
710
711 @Nullable
712 @Override
713 public String getDefaultBrowser(@UserIdInt int userId) {
714 return CollectionUtils.firstOrNull(getOrCreateUserState(userId).getRoleHolders(
715 RoleManager.ROLE_BROWSER));
716 }
717
718 @Override
719 public boolean setDefaultBrowser(@Nullable String packageName, @UserIdInt int userId) {
720 CompletableFuture<Void> future = new CompletableFuture<>();
721 IRoleManagerCallback callback = new IRoleManagerCallback.Stub() {
722 @Override
723 public void onSuccess() {
724 future.complete(null);
725 }
726 @Override
727 public void onFailure() {
728 future.completeExceptionally(new RuntimeException());
729 }
730 };
731 if (packageName != null) {
732 getOrCreateControllerService(userId).onAddRoleHolder(RoleManager.ROLE_BROWSER,
Hai Zhang71d70362019-02-04 16:17:38 -0800733 packageName, 0, callback);
Hai Zhang85fd0622019-02-01 14:06:04 -0800734 } else {
Hai Zhang71d70362019-02-04 16:17:38 -0800735 getOrCreateControllerService(userId).onClearRoleHolders(RoleManager.ROLE_BROWSER, 0,
Hai Zhang85fd0622019-02-01 14:06:04 -0800736 callback);
737 }
738 try {
739 future.get(5, TimeUnit.SECONDS);
740 return true;
741 } catch (InterruptedException | ExecutionException | TimeoutException e) {
742 Slog.e(LOG_TAG, "Exception while setting default browser: " + packageName, e);
743 return false;
744 }
Philip P. Moltmann70b42ae2019-01-29 16:24:19 -0800745 }
746 }
Hai Zhang8be463f2019-02-11 16:44:45 -0800747
748 private class DefaultHomeProvider implements PackageManagerInternal.DefaultHomeProvider {
749
750 @Nullable
751 @Override
752 public String getDefaultHome(@UserIdInt int userId) {
753 return CollectionUtils.firstOrNull(getOrCreateUserState(userId).getRoleHolders(
754 RoleManager.ROLE_HOME));
755 }
756
757 @Override
758 public void setDefaultHomeAsync(@Nullable String packageName, @UserIdInt int userId) {
759 IRoleManagerCallback callback = new IRoleManagerCallback.Stub() {
760 @Override
761 public void onSuccess() {}
762 @Override
763 public void onFailure() {
764 Slog.e(LOG_TAG, "Failed to set default home: " + packageName);
765 }
766 };
767 if (packageName != null) {
768 getOrCreateControllerService(userId).onAddRoleHolder(RoleManager.ROLE_HOME,
769 packageName, 0, callback);
770 } else {
771 getOrCreateControllerService(userId).onClearRoleHolders(RoleManager.ROLE_HOME, 0,
772 callback);
773 }
774 }
775 }
Hai Zhangb7776682018-09-25 15:10:57 -0700776}