1 /* 2 * Copyright (C) 2024 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.supervision; 18 19 import static android.Manifest.permission.INTERACT_ACROSS_USERS; 20 import static android.Manifest.permission.MANAGE_USERS; 21 import static android.Manifest.permission.QUERY_USERS; 22 import static android.permission.flags.Flags.FLAG_ENABLE_SYSTEM_SUPERVISION_ROLE_BEHAVIOR; 23 24 import android.annotation.FlaggedApi; 25 import android.annotation.Nullable; 26 import android.annotation.RequiresPermission; 27 import android.annotation.SystemApi; 28 import android.annotation.SystemService; 29 import android.annotation.TestApi; 30 import android.annotation.UserHandleAware; 31 import android.annotation.UserIdInt; 32 import android.app.supervision.flags.Flags; 33 import android.compat.annotation.UnsupportedAppUsage; 34 import android.content.Context; 35 import android.content.Intent; 36 import android.os.RemoteException; 37 38 /** 39 * Service for handling parental supervision. 40 * 41 * @hide 42 */ 43 @SystemService(Context.SUPERVISION_SERVICE) 44 @SystemApi 45 @FlaggedApi(Flags.FLAG_SUPERVISION_MANAGER_APIS) 46 public class SupervisionManager { 47 private final Context mContext; 48 @Nullable private final ISupervisionManager mService; 49 50 /** 51 * Activity action: ask the human user to enable supervision for this user. Only the app that 52 * holds the {@code SYSTEM_SUPERVISION} role can launch this intent. 53 * 54 * <p>The intent must be invoked via {@link Activity#startActivityForResult} to receive the 55 * result of whether or not the user approved the action. If approved, the result will be {@link 56 * Activity#RESULT_OK}. 57 * 58 * <p>If supervision is already enabled, the operation will return a failure result. 59 * 60 * @hide 61 */ 62 public static final String ACTION_ENABLE_SUPERVISION = 63 "android.app.supervision.action.ENABLE_SUPERVISION"; 64 65 /** 66 * Activity action: ask the human user to disable supervision for this user. Only the app that 67 * holds the {@code SYSTEM_SUPERVISION} role can launch this intent. 68 * 69 * <p>The intent must be invoked via {@link Activity#startActivityForResult} to receive the 70 * result of whether or not the user approved the action. If approved, the result will be {@link 71 * Activity#RESULT_OK}. 72 * 73 * <p>If supervision is not enabled, the operation will return a failure result. 74 * 75 * @hide 76 */ 77 public static final String ACTION_DISABLE_SUPERVISION = 78 "android.app.supervision.action.DISABLE_SUPERVISION"; 79 80 /** @hide */ 81 @UnsupportedAppUsage SupervisionManager(Context context, @Nullable ISupervisionManager service)82 public SupervisionManager(Context context, @Nullable ISupervisionManager service) { 83 mContext = context; 84 mService = service; 85 } 86 87 /** 88 * Creates an {@link Intent} that can be used with {@link Context#startActivity(Intent)} to 89 * launch the activity to verify supervision credentials. 90 * 91 * <p>A valid {@link Intent} is always returned if supervision is enabled at the time this API 92 * is called, the launched activity still need to perform validity checks as the supervision 93 * state can change when the activity is launched. A null intent is returned if supervision is 94 * disabled at the time of this API call. 95 * 96 * <p>A result code of {@link android.app.Activity#RESULT_OK} indicates successful verification 97 * of the supervision credentials. 98 * 99 * @hide 100 */ 101 @SystemApi 102 @FlaggedApi(Flags.FLAG_SUPERVISION_MANAGER_APIS) 103 @RequiresPermission(anyOf = {MANAGE_USERS, QUERY_USERS}) 104 @Nullable createConfirmSupervisionCredentialsIntent()105 public Intent createConfirmSupervisionCredentialsIntent() { 106 if (mService != null) { 107 try { 108 Intent result = mService.createConfirmSupervisionCredentialsIntent(); 109 if (result != null) { 110 result.prepareToEnterProcess( 111 Intent.LOCAL_FLAG_FROM_SYSTEM, mContext.getAttributionSource()); 112 } 113 return result; 114 } catch (RemoteException e) { 115 throw e.rethrowFromSystemServer(); 116 } 117 } 118 return null; 119 } 120 121 /** 122 * Returns whether the device is supervised. 123 * 124 * @hide 125 */ 126 @SystemApi 127 @FlaggedApi(Flags.FLAG_SUPERVISION_MANAGER_APIS) 128 @RequiresPermission(anyOf = {MANAGE_USERS, QUERY_USERS}) 129 @UserHandleAware(requiresPermissionIfNotCaller = INTERACT_ACROSS_USERS) isSupervisionEnabled()130 public boolean isSupervisionEnabled() { 131 return isSupervisionEnabledForUser(mContext.getUserId()); 132 } 133 134 /** 135 * Returns whether the device is supervised. 136 * 137 * @hide 138 */ 139 @RequiresPermission(anyOf = {MANAGE_USERS, QUERY_USERS}) 140 @UserHandleAware(requiresPermissionIfNotCaller = INTERACT_ACROSS_USERS) isSupervisionEnabledForUser(@serIdInt int userId)141 public boolean isSupervisionEnabledForUser(@UserIdInt int userId) { 142 if (mService != null) { 143 try { 144 return mService.isSupervisionEnabledForUser(userId); 145 } catch (RemoteException e) { 146 throw e.rethrowFromSystemServer(); 147 } 148 } 149 return false; 150 } 151 152 /** 153 * Sets whether the device is supervised for the current user. 154 * 155 * @hide 156 */ 157 @TestApi 158 @UserHandleAware(requiresPermissionIfNotCaller = INTERACT_ACROSS_USERS) setSupervisionEnabled(boolean enabled)159 public void setSupervisionEnabled(boolean enabled) { 160 setSupervisionEnabledForUser(mContext.getUserId(), enabled); 161 } 162 163 /** 164 * Sets whether the device is supervised for a given user. 165 * 166 * @hide 167 */ 168 @UserHandleAware(requiresPermissionIfNotCaller = INTERACT_ACROSS_USERS) setSupervisionEnabledForUser(@serIdInt int userId, boolean enabled)169 public void setSupervisionEnabledForUser(@UserIdInt int userId, boolean enabled) { 170 if (mService != null) { 171 try { 172 mService.setSupervisionEnabledForUser(userId, enabled); 173 } catch (RemoteException e) { 174 throw e.rethrowFromSystemServer(); 175 } 176 } 177 } 178 179 /** 180 * Returns the package name of the app that is acting as the active supervision app or null if 181 * supervision is disabled. 182 * 183 * @hide 184 */ 185 @UserHandleAware 186 @Nullable getActiveSupervisionAppPackage()187 public String getActiveSupervisionAppPackage() { 188 if (mService != null) { 189 try { 190 return mService.getActiveSupervisionAppPackage(mContext.getUserId()); 191 } catch (RemoteException e) { 192 throw e.rethrowFromSystemServer(); 193 } 194 } 195 return null; 196 } 197 198 199 /** 200 * @return {@code true} if bypassing the qualification is allowed for the specified role based 201 * on the current state of the device. 202 * 203 * @hide 204 */ 205 @SystemApi 206 @FlaggedApi(FLAG_ENABLE_SYSTEM_SUPERVISION_ROLE_BEHAVIOR) 207 @RequiresPermission(android.Manifest.permission.MANAGE_ROLE_HOLDERS) shouldAllowBypassingSupervisionRoleQualification()208 public boolean shouldAllowBypassingSupervisionRoleQualification() { 209 if (mService != null) { 210 try { 211 return mService.shouldAllowBypassingSupervisionRoleQualification(); 212 } catch (RemoteException e) { 213 throw e.rethrowFromSystemServer(); 214 } 215 } 216 return false; 217 } 218 } 219