• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
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 
17 package android.app.role;
18 
19 import android.Manifest;
20 import android.annotation.NonNull;
21 import android.annotation.Nullable;
22 import android.annotation.SystemApi;
23 import android.annotation.WorkerThread;
24 import android.app.Service;
25 import android.content.Intent;
26 import android.os.Binder;
27 import android.os.Bundle;
28 import android.os.Handler;
29 import android.os.HandlerThread;
30 import android.os.IBinder;
31 import android.os.Process;
32 import android.os.RemoteCallback;
33 import android.os.UserHandle;
34 
35 import com.android.internal.util.Preconditions;
36 import com.android.internal.util.function.pooled.PooledLambda;
37 
38 import 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
50 public abstract class RoleControllerService extends Service {
51 
52     /**
53      * The {@link Intent} that must be declared as handled by the service.
54      */
55     public static final String SERVICE_INTERFACE = "android.app.role.RoleControllerService";
56 
57     private HandlerThread mWorkerThread;
58     private Handler mWorkerHandler;
59 
60     @Override
onCreate()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
onDestroy()70     public void onDestroy() {
71         super.onDestroy();
72 
73         mWorkerThread.quitSafely();
74     }
75 
76     @Nullable
77     @Override
onBind(@ullable Intent intent)78     public final IBinder onBind(@Nullable Intent intent) {
79         return new IRoleController.Stub() {
80 
81             @Override
82             public void grantDefaultRoles(RemoteCallback callback) {
83                 enforceCallerSystemUid("grantDefaultRoles");
84 
85                 Preconditions.checkNotNull(callback, "callback cannot be null");
86 
87                 mWorkerHandler.sendMessage(PooledLambda.obtainMessage(
88                         RoleControllerService::grantDefaultRoles, RoleControllerService.this,
89                         callback));
90             }
91 
92             @Override
93             public void onAddRoleHolder(String roleName, String packageName, int flags,
94                     RemoteCallback callback) {
95                 enforceCallerSystemUid("onAddRoleHolder");
96 
97                 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");
101 
102                 mWorkerHandler.sendMessage(PooledLambda.obtainMessage(
103                         RoleControllerService::onAddRoleHolder, RoleControllerService.this,
104                         roleName, packageName, flags, callback));
105             }
106 
107             @Override
108             public void onRemoveRoleHolder(String roleName, String packageName, int flags,
109                     RemoteCallback callback) {
110                 enforceCallerSystemUid("onRemoveRoleHolder");
111 
112                 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");
116 
117                 mWorkerHandler.sendMessage(PooledLambda.obtainMessage(
118                         RoleControllerService::onRemoveRoleHolder, RoleControllerService.this,
119                         roleName, packageName, flags, callback));
120             }
121 
122             @Override
123             public void onClearRoleHolders(String roleName, int flags, RemoteCallback callback) {
124                 enforceCallerSystemUid("onClearRoleHolders");
125 
126                 Preconditions.checkStringNotEmpty(roleName, "roleName cannot be null or empty");
127                 Preconditions.checkNotNull(callback, "callback cannot be null");
128 
129                 mWorkerHandler.sendMessage(PooledLambda.obtainMessage(
130                         RoleControllerService::onClearRoleHolders, RoleControllerService.this,
131                         roleName, flags, callback));
132             }
133 
134             private void enforceCallerSystemUid(@NonNull String methodName) {
135                 if (Binder.getCallingUid() != Process.SYSTEM_UID) {
136                     throw new SecurityException("Only the system process can call " + methodName
137                             + "()");
138                 }
139             }
140 
141             @Override
142             public void isApplicationQualifiedForRole(String roleName, String packageName,
143                     RemoteCallback callback) {
144                 enforceCallingPermission(Manifest.permission.MANAGE_ROLE_HOLDERS, null);
145 
146                 Preconditions.checkStringNotEmpty(roleName, "roleName cannot be null or empty");
147                 Preconditions.checkStringNotEmpty(packageName,
148                         "packageName cannot be null or empty");
149                 Preconditions.checkNotNull(callback, "callback cannot be null");
150 
151                 boolean qualified = onIsApplicationQualifiedForRole(roleName, packageName);
152                 callback.sendResult(qualified ? Bundle.EMPTY : null);
153             }
154 
155             @Override
156             public void isRoleVisible(String roleName, RemoteCallback callback) {
157                 enforceCallingPermission(Manifest.permission.MANAGE_ROLE_HOLDERS, null);
158 
159                 Preconditions.checkStringNotEmpty(roleName, "roleName cannot be null or empty");
160                 Preconditions.checkNotNull(callback, "callback cannot be null");
161 
162                 boolean visible = onIsRoleVisible(roleName);
163                 callback.sendResult(visible ? Bundle.EMPTY : null);
164             }
165         };
166     }
167 
168     private void grantDefaultRoles(@NonNull RemoteCallback callback) {
169         boolean successful = onGrantDefaultRoles();
170         callback.sendResult(successful ? Bundle.EMPTY : null);
171     }
172 
173     private void onAddRoleHolder(@NonNull String roleName, @NonNull String packageName,
174             @RoleManager.ManageHoldersFlags int flags, @NonNull RemoteCallback callback) {
175         boolean successful = onAddRoleHolder(roleName, packageName, flags);
176         callback.sendResult(successful ? Bundle.EMPTY : null);
177     }
178 
179     private void onRemoveRoleHolder(@NonNull String roleName, @NonNull String packageName,
180             @RoleManager.ManageHoldersFlags int flags, @NonNull RemoteCallback callback) {
181         boolean successful = onRemoveRoleHolder(roleName, packageName, flags);
182         callback.sendResult(successful ? Bundle.EMPTY : null);
183     }
184 
185     private void onClearRoleHolders(@NonNull String roleName,
186             @RoleManager.ManageHoldersFlags int flags, @NonNull RemoteCallback callback) {
187         boolean successful = onClearRoleHolders(roleName, flags);
188         callback.sendResult(successful ? Bundle.EMPTY : null);
189     }
190 
191     /**
192      * Called by system to grant default permissions and roles.
193      * <p>
194      * This is typically when creating a new user or upgrading either system or
195      * permission controller package
196      *
197      * @return whether this call was successful
198      */
199     @WorkerThread
200     public abstract boolean onGrantDefaultRoles();
201 
202     /**
203      * Add a specific application to the holders of a role. If the role is exclusive, the previous
204      * holder will be replaced.
205      * <p>
206      * Implementation should enforce the role requirements and grant or revoke the relevant
207      * privileges of roles.
208      *
209      * @param roleName the name of the role to add the role holder for
210      * @param packageName the package name of the application to add to the role holders
211      * @param flags optional behavior flags
212      *
213      * @return whether this call was successful
214      *
215      * @see RoleManager#addRoleHolderAsUser(String, String, int, UserHandle, Executor,
216      *      RemoteCallback)
217      */
218     @WorkerThread
219     public abstract boolean onAddRoleHolder(@NonNull String roleName, @NonNull String packageName,
220             @RoleManager.ManageHoldersFlags int flags);
221 
222     /**
223      * Remove a specific application from the holders of a role.
224      *
225      * @param roleName the name of the role to remove the role holder for
226      * @param packageName the package name of the application to remove from the role holders
227      * @param flags optional behavior flags
228      *
229      * @return whether this call was successful
230      *
231      * @see RoleManager#removeRoleHolderAsUser(String, String, int, UserHandle, Executor,
232      *      RemoteCallback)
233      */
234     @WorkerThread
235     public abstract boolean onRemoveRoleHolder(@NonNull String roleName,
236             @NonNull String packageName, @RoleManager.ManageHoldersFlags int flags);
237 
238     /**
239      * Remove all holders of a role.
240      *
241      * @param roleName the name of the role to remove role holders for
242      * @param flags optional behavior flags
243      *
244      * @return whether this call was successful
245      *
246      * @see RoleManager#clearRoleHoldersAsUser(String, int, UserHandle, Executor, RemoteCallback)
247      */
248     @WorkerThread
249     public abstract boolean onClearRoleHolders(@NonNull String roleName,
250             @RoleManager.ManageHoldersFlags int flags);
251 
252     /**
253      * Check whether an application is qualified for a role.
254      *
255      * @param roleName name of the role to check for
256      * @param packageName package name of the application to check for
257      *
258      * @return whether the application is qualified for the role
259      */
260     public abstract boolean onIsApplicationQualifiedForRole(@NonNull String roleName,
261             @NonNull String packageName);
262 
263     /**
264      * Check whether a role should be visible to user.
265      *
266      * @param roleName name of the role to check for
267      *
268      * @return whether the role should be visible to user
269      */
270     public abstract boolean onIsRoleVisible(@NonNull String roleName);
271 }
272