blob: 312761d43afd68313c193761e89049e7a5a7ea51 [file] [log] [blame]
Hai Zhangb7776682018-09-25 15:10:57 -07001/*
Hai Zhanga4959e52019-03-06 12:21:07 -08002 * Copyright (C) 2019 The Android Open Source Project
Hai Zhangb7776682018-09-25 15:10:57 -07003 *
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
Hai Zhanga4959e52019-03-06 12:21:07 -080017package android.app.role;
Hai Zhangb7776682018-09-25 15:10:57 -070018
Hai Zhang26f37d32019-03-06 15:58:39 -080019import android.Manifest;
Hai Zhangb7776682018-09-25 15:10:57 -070020import android.annotation.NonNull;
21import android.annotation.Nullable;
22import android.annotation.SystemApi;
Hai Zhangf5e8ccd2019-03-06 20:12:24 -080023import android.annotation.WorkerThread;
Hai Zhangb7776682018-09-25 15:10:57 -070024import android.app.Service;
Hai Zhangb7776682018-09-25 15:10:57 -070025import android.content.Intent;
Hai Zhangf5e8ccd2019-03-06 20:12:24 -080026import android.os.Binder;
Hai Zhang26f37d32019-03-06 15:58:39 -080027import android.os.Bundle;
Hai Zhangf5e8ccd2019-03-06 20:12:24 -080028import android.os.Handler;
29import android.os.HandlerThread;
Hai Zhangb7776682018-09-25 15:10:57 -070030import android.os.IBinder;
Hai Zhangf5e8ccd2019-03-06 20:12:24 -080031import android.os.Process;
Hai Zhang26f37d32019-03-06 15:58:39 -080032import android.os.RemoteCallback;
Hai Zhangb7776682018-09-25 15:10:57 -070033import android.os.UserHandle;
Hai Zhangb7776682018-09-25 15:10:57 -070034
35import com.android.internal.util.Preconditions;
Hai Zhangf5e8ccd2019-03-06 20:12:24 -080036import com.android.internal.util.function.pooled.PooledLambda;
Hai Zhangb7776682018-09-25 15:10:57 -070037
38import java.util.concurrent.Executor;
39
40/**
41 * Abstract base class for the role controller service.
42 * <p>
43 * Subclass should implement the business logic for role management, including enforcing role
44 * requirements and granting or revoking relevant privileges of roles. This class can only be
45 * implemented by the permission controller app which is registered in {@code PackageManager}.
46 *
47 * @hide
48 */
49@SystemApi
50public abstract class RoleControllerService extends Service {
51
Hai Zhangb7776682018-09-25 15:10:57 -070052 /**
Hai Zhanga4959e52019-03-06 12:21:07 -080053 * The {@link Intent} that must be declared as handled by the service.
Hai Zhangb7776682018-09-25 15:10:57 -070054 */
Hai Zhanga4959e52019-03-06 12:21:07 -080055 public static final String SERVICE_INTERFACE = "android.app.role.RoleControllerService";
Hai Zhangb7776682018-09-25 15:10:57 -070056
Hai Zhangf5e8ccd2019-03-06 20:12:24 -080057 private HandlerThread mWorkerThread;
58 private Handler mWorkerHandler;
59
60 @Override
61 public void onCreate() {
62 super.onCreate();
63
64 mWorkerThread = new HandlerThread(RoleControllerService.class.getSimpleName());
65 mWorkerThread.start();
66 mWorkerHandler = new Handler(mWorkerThread.getLooper());
67 }
68
69 @Override
70 public void onDestroy() {
71 super.onDestroy();
72
73 mWorkerThread.quitSafely();
74 }
75
Hai Zhangb7776682018-09-25 15:10:57 -070076 @Nullable
77 @Override
78 public final IBinder onBind(@Nullable Intent intent) {
Hai Zhanga4959e52019-03-06 12:21:07 -080079 return new IRoleController.Stub() {
80
81 @Override
Hai Zhangf5e8ccd2019-03-06 20:12:24 -080082 public void grantDefaultRoles(RemoteCallback callback) {
83 enforceCallerSystemUid("grantDefaultRoles");
84
Hai Zhanga4959e52019-03-06 12:21:07 -080085 Preconditions.checkNotNull(callback, "callback cannot be null");
Hai Zhangf5e8ccd2019-03-06 20:12:24 -080086
87 mWorkerHandler.sendMessage(PooledLambda.obtainMessage(
88 RoleControllerService::grantDefaultRoles, RoleControllerService.this,
Hai Zhanga4959e52019-03-06 12:21:07 -080089 callback));
90 }
Hai Zhangb7776682018-09-25 15:10:57 -070091
92 @Override
Hai Zhang71d70362019-02-04 16:17:38 -080093 public void onAddRoleHolder(String roleName, String packageName, int flags,
Hai Zhangf5e8ccd2019-03-06 20:12:24 -080094 RemoteCallback callback) {
95 enforceCallerSystemUid("onAddRoleHolder");
96
Hai Zhangb7776682018-09-25 15:10:57 -070097 Preconditions.checkStringNotEmpty(roleName, "roleName cannot be null or empty");
98 Preconditions.checkStringNotEmpty(packageName,
99 "packageName cannot be null or empty");
100 Preconditions.checkNotNull(callback, "callback cannot be null");
Hai Zhangf5e8ccd2019-03-06 20:12:24 -0800101
102 mWorkerHandler.sendMessage(PooledLambda.obtainMessage(
103 RoleControllerService::onAddRoleHolder, RoleControllerService.this,
104 roleName, packageName, flags, callback));
Hai Zhangb7776682018-09-25 15:10:57 -0700105 }
106
107 @Override
Hai Zhang71d70362019-02-04 16:17:38 -0800108 public void onRemoveRoleHolder(String roleName, String packageName, int flags,
Hai Zhangf5e8ccd2019-03-06 20:12:24 -0800109 RemoteCallback callback) {
110 enforceCallerSystemUid("onRemoveRoleHolder");
111
Hai Zhangb7776682018-09-25 15:10:57 -0700112 Preconditions.checkStringNotEmpty(roleName, "roleName cannot be null or empty");
113 Preconditions.checkStringNotEmpty(packageName,
114 "packageName cannot be null or empty");
115 Preconditions.checkNotNull(callback, "callback cannot be null");
Hai Zhangf5e8ccd2019-03-06 20:12:24 -0800116
117 mWorkerHandler.sendMessage(PooledLambda.obtainMessage(
118 RoleControllerService::onRemoveRoleHolder, RoleControllerService.this,
119 roleName, packageName, flags, callback));
Hai Zhangb7776682018-09-25 15:10:57 -0700120 }
121
122 @Override
Hai Zhangf5e8ccd2019-03-06 20:12:24 -0800123 public void onClearRoleHolders(String roleName, int flags, RemoteCallback callback) {
124 enforceCallerSystemUid("onClearRoleHolders");
125
Hai Zhangb7776682018-09-25 15:10:57 -0700126 Preconditions.checkStringNotEmpty(roleName, "roleName cannot be null or empty");
127 Preconditions.checkNotNull(callback, "callback cannot be null");
Hai Zhangf5e8ccd2019-03-06 20:12:24 -0800128
129 mWorkerHandler.sendMessage(PooledLambda.obtainMessage(
130 RoleControllerService::onClearRoleHolders, RoleControllerService.this,
131 roleName, flags, callback));
Hai Zhangb7776682018-09-25 15:10:57 -0700132 }
Eugene Suslaa4200f822018-11-09 18:06:43 -0800133
134 @Override
Hai Zhangf5e8ccd2019-03-06 20:12:24 -0800135 public void onSmsKillSwitchToggled(boolean enabled) {
136 enforceCallerSystemUid("onSmsKillSwitchToggled");
137
138 mWorkerHandler.sendMessage(PooledLambda.obtainMessage(
139 RoleControllerService::onSmsKillSwitchToggled, RoleControllerService.this,
140 enabled));
141 }
142
143 private void enforceCallerSystemUid(@NonNull String methodName) {
144 if (Binder.getCallingUid() != Process.SYSTEM_UID) {
145 throw new SecurityException("Only the system process can call " + methodName
146 + "()");
147 }
Eugene Susla34969062019-01-29 11:02:02 -0800148 }
Hai Zhang26f37d32019-03-06 15:58:39 -0800149
150 @Override
151 public void isApplicationQualifiedForRole(String roleName, String packageName,
152 RemoteCallback callback) {
153 enforceCallingPermission(Manifest.permission.MANAGE_ROLE_HOLDERS, null);
154
155 Preconditions.checkStringNotEmpty(roleName, "roleName cannot be null or empty");
156 Preconditions.checkStringNotEmpty(packageName,
157 "packageName cannot be null or empty");
158 Preconditions.checkNotNull(callback, "callback cannot be null");
159
160 boolean qualified = onIsApplicationQualifiedForRole(roleName, packageName);
Hai Zhangf5e8ccd2019-03-06 20:12:24 -0800161 callback.sendResult(qualified ? Bundle.EMPTY : null);
Hai Zhang26f37d32019-03-06 15:58:39 -0800162 }
163
164 @Override
165 public void isRoleVisible(String roleName, RemoteCallback callback) {
166 enforceCallingPermission(Manifest.permission.MANAGE_ROLE_HOLDERS, null);
167
168 Preconditions.checkStringNotEmpty(roleName, "roleName cannot be null or empty");
169 Preconditions.checkNotNull(callback, "callback cannot be null");
170
171 boolean visible = onIsRoleVisible(roleName);
Hai Zhangf5e8ccd2019-03-06 20:12:24 -0800172 callback.sendResult(visible ? Bundle.EMPTY : null);
Hai Zhang26f37d32019-03-06 15:58:39 -0800173 }
Hai Zhangb7776682018-09-25 15:10:57 -0700174 };
175 }
176
Hai Zhangf5e8ccd2019-03-06 20:12:24 -0800177 private void grantDefaultRoles(@NonNull RemoteCallback callback) {
178 boolean successful = onGrantDefaultRoles();
179 callback.sendResult(successful ? Bundle.EMPTY : null);
180 }
181
182 private void onAddRoleHolder(@NonNull String roleName, @NonNull String packageName,
183 @RoleManager.ManageHoldersFlags int flags, @NonNull RemoteCallback callback) {
184 boolean successful = onAddRoleHolder(roleName, packageName, flags);
185 callback.sendResult(successful ? Bundle.EMPTY : null);
186 }
187
188 private void onRemoveRoleHolder(@NonNull String roleName, @NonNull String packageName,
189 @RoleManager.ManageHoldersFlags int flags, @NonNull RemoteCallback callback) {
190 boolean successful = onRemoveRoleHolder(roleName, packageName, flags);
191 callback.sendResult(successful ? Bundle.EMPTY : null);
192 }
193
194 private void onClearRoleHolders(@NonNull String roleName,
195 @RoleManager.ManageHoldersFlags int flags, @NonNull RemoteCallback callback) {
196 boolean successful = onClearRoleHolders(roleName, flags);
197 callback.sendResult(successful ? Bundle.EMPTY : null);
198 }
199
Hai Zhangb7776682018-09-25 15:10:57 -0700200 /**
Hai Zhanga4959e52019-03-06 12:21:07 -0800201 * Called by system to grant default permissions and roles.
202 * <p>
203 * This is typically when creating a new user or upgrading either system or
204 * permission controller package
205 *
Hai Zhangf5e8ccd2019-03-06 20:12:24 -0800206 * @return whether this call was successful
Hai Zhanga4959e52019-03-06 12:21:07 -0800207 */
Hai Zhangf5e8ccd2019-03-06 20:12:24 -0800208 @WorkerThread
209 public abstract boolean onGrantDefaultRoles();
Hai Zhanga4959e52019-03-06 12:21:07 -0800210
211 /**
Hai Zhangb7776682018-09-25 15:10:57 -0700212 * Add a specific application to the holders of a role. If the role is exclusive, the previous
213 * holder will be replaced.
214 * <p>
215 * Implementation should enforce the role requirements and grant or revoke the relevant
216 * privileges of roles.
217 *
218 * @param roleName the name of the role to add the role holder for
219 * @param packageName the package name of the application to add to the role holders
Hai Zhang71d70362019-02-04 16:17:38 -0800220 * @param flags optional behavior flags
Hai Zhangf5e8ccd2019-03-06 20:12:24 -0800221 *
222 * @return whether this call was successful
Hai Zhangb7776682018-09-25 15:10:57 -0700223 *
Hai Zhang71d70362019-02-04 16:17:38 -0800224 * @see RoleManager#addRoleHolderAsUser(String, String, int, UserHandle, Executor,
Hai Zhangf5e8ccd2019-03-06 20:12:24 -0800225 * RemoteCallback)
Hai Zhangb7776682018-09-25 15:10:57 -0700226 */
Hai Zhangf5e8ccd2019-03-06 20:12:24 -0800227 @WorkerThread
228 public abstract boolean onAddRoleHolder(@NonNull String roleName, @NonNull String packageName,
229 @RoleManager.ManageHoldersFlags int flags);
Hai Zhangb7776682018-09-25 15:10:57 -0700230
231 /**
232 * Remove a specific application from the holders of a role.
233 *
234 * @param roleName the name of the role to remove the role holder for
235 * @param packageName the package name of the application to remove from the role holders
Hai Zhang71d70362019-02-04 16:17:38 -0800236 * @param flags optional behavior flags
Hai Zhangf5e8ccd2019-03-06 20:12:24 -0800237 *
238 * @return whether this call was successful
Hai Zhangb7776682018-09-25 15:10:57 -0700239 *
Hai Zhang71d70362019-02-04 16:17:38 -0800240 * @see RoleManager#removeRoleHolderAsUser(String, String, int, UserHandle, Executor,
Hai Zhangf5e8ccd2019-03-06 20:12:24 -0800241 * RemoteCallback)
Hai Zhangb7776682018-09-25 15:10:57 -0700242 */
Hai Zhangf5e8ccd2019-03-06 20:12:24 -0800243 @WorkerThread
244 public abstract boolean onRemoveRoleHolder(@NonNull String roleName,
245 @NonNull String packageName, @RoleManager.ManageHoldersFlags int flags);
Hai Zhangb7776682018-09-25 15:10:57 -0700246
247 /**
248 * Remove all holders of a role.
249 *
250 * @param roleName the name of the role to remove role holders for
Hai Zhang71d70362019-02-04 16:17:38 -0800251 * @param flags optional behavior flags
Hai Zhangb7776682018-09-25 15:10:57 -0700252 *
Hai Zhangf5e8ccd2019-03-06 20:12:24 -0800253 * @return whether this call was successful
254 *
255 * @see RoleManager#clearRoleHoldersAsUser(String, int, UserHandle, Executor, RemoteCallback)
Hai Zhangb7776682018-09-25 15:10:57 -0700256 */
Hai Zhangf5e8ccd2019-03-06 20:12:24 -0800257 @WorkerThread
258 public abstract boolean onClearRoleHolders(@NonNull String roleName,
259 @RoleManager.ManageHoldersFlags int flags);
Hai Zhangb7776682018-09-25 15:10:57 -0700260
Eugene Suslaa4200f822018-11-09 18:06:43 -0800261 /**
Eugene Susla34969062019-01-29 11:02:02 -0800262 * Cleanup appop/permissions state in response to sms kill switch toggle
263 *
Hai Zhanga4959e52019-03-06 12:21:07 -0800264 * @param enabled whether kill switch was turned on
Hai Zhangc33c55b2019-03-06 17:03:38 -0800265 *
266 * @hide
Eugene Susla34969062019-01-29 11:02:02 -0800267 */
268 //STOPSHIP: remove this api before shipping a final version
Hai Zhangf5e8ccd2019-03-06 20:12:24 -0800269 @WorkerThread
Hai Zhanga4959e52019-03-06 12:21:07 -0800270 public abstract void onSmsKillSwitchToggled(boolean enabled);
Eugene Suslaa4200f822018-11-09 18:06:43 -0800271
Hai Zhang26f37d32019-03-06 15:58:39 -0800272 /**
273 * Check whether an application is qualified for a role.
274 *
275 * @param roleName name of the role to check for
276 * @param packageName package name of the application to check for
277 *
278 * @return whether the application is qualified for the role
279 */
280 public abstract boolean onIsApplicationQualifiedForRole(@NonNull String roleName,
281 @NonNull String packageName);
282
283 /**
284 * Check whether a role should be visible to user.
285 *
286 * @param roleName name of the role to check for
287 *
288 * @return whether the role should be visible to user
289 */
290 public abstract boolean onIsRoleVisible(@NonNull String roleName);
Hai Zhangb7776682018-09-25 15:10:57 -0700291}