1 /* 2 * Copyright (C) 2022 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 com.android.server.devicepolicy; 18 19 import static com.android.server.devicepolicy.DevicePolicyEngine.DEVICE_LOCK_CONTROLLER_ROLE; 20 21 import android.annotation.NonNull; 22 import android.annotation.Nullable; 23 import android.app.admin.AccountTypePolicyKey; 24 import android.app.admin.BooleanPolicyValue; 25 import android.app.admin.DevicePolicyIdentifiers; 26 import android.app.admin.DevicePolicyManager; 27 import android.app.admin.IntegerPolicyValue; 28 import android.app.admin.IntentFilterPolicyKey; 29 import android.app.admin.LockTaskPolicy; 30 import android.app.admin.NoArgsPolicyKey; 31 import android.app.admin.PackagePermissionPolicyKey; 32 import android.app.admin.PackagePolicyKey; 33 import android.app.admin.PolicyKey; 34 import android.app.admin.PolicyValue; 35 import android.app.admin.UserRestrictionPolicyKey; 36 import android.content.ComponentName; 37 import android.content.Context; 38 import android.content.IntentFilter; 39 import android.os.Bundle; 40 import android.os.UserManager; 41 42 import com.android.internal.util.function.QuadFunction; 43 import com.android.modules.utils.TypedXmlPullParser; 44 import com.android.modules.utils.TypedXmlSerializer; 45 import com.android.server.utils.Slogf; 46 47 import org.xmlpull.v1.XmlPullParserException; 48 49 import java.io.IOException; 50 import java.util.HashMap; 51 import java.util.LinkedHashMap; 52 import java.util.List; 53 import java.util.Map; 54 import java.util.Set; 55 56 final class PolicyDefinition<V> { 57 58 static final String TAG = "PolicyDefinition"; 59 60 private static final int POLICY_FLAG_NONE = 0; 61 62 // Only use this flag if a policy can not be applied locally. 63 private static final int POLICY_FLAG_GLOBAL_ONLY_POLICY = 1; 64 65 // Only use this flag if a policy can not be applied globally. 66 private static final int POLICY_FLAG_LOCAL_ONLY_POLICY = 1 << 1; 67 68 // Only use this flag if a policy is inheritable by child profile from parent. 69 private static final int POLICY_FLAG_INHERITABLE = 1 << 2; 70 71 // Use this flag if admin policies should be treated independently of each other and should not 72 // have any resolution logic applied, this should only be used for very limited policies were 73 // this would make sense and the enforcing logic should handle it appropriately, e.g. 74 // application restrictions set by different admins for a single package should not be merged, 75 // but saved and queried independent of each other. 76 // Currently, support is added for local only policies, if you need to add a non coexistable 77 // global policy please add support. 78 private static final int POLICY_FLAG_NON_COEXISTABLE_POLICY = 1 << 3; 79 80 // Add this flag to any policy that is a user restriction, the reason for this is that there 81 // are some special APIs to handle user restriction policies and this is the way we can identify 82 // them. 83 private static final int POLICY_FLAG_USER_RESTRICTION_POLICY = 1 << 4; 84 85 private static final MostRestrictive<Boolean> FALSE_MORE_RESTRICTIVE = new MostRestrictive<>( 86 List.of(new BooleanPolicyValue(false), new BooleanPolicyValue(true))); 87 88 private static final MostRestrictive<Boolean> TRUE_MORE_RESTRICTIVE = new MostRestrictive<>( 89 List.of(new BooleanPolicyValue(true), new BooleanPolicyValue(false))); 90 91 static PolicyDefinition<Boolean> AUTO_TIMEZONE = new PolicyDefinition<>( 92 new NoArgsPolicyKey(DevicePolicyIdentifiers.AUTO_TIMEZONE_POLICY), 93 // auto timezone is disabled by default, hence enabling it is more restrictive. 94 TRUE_MORE_RESTRICTIVE, 95 POLICY_FLAG_GLOBAL_ONLY_POLICY, 96 (Boolean value, Context context, Integer userId, PolicyKey policyKey) -> 97 PolicyEnforcerCallbacks.setAutoTimezoneEnabled(value, context), 98 new BooleanPolicySerializer()); 99 100 // This is saved in the static map sPolicyDefinitions so that we're able to reconstruct the 101 // actual policy with the correct arguments (packageName and permission name) 102 // when reading the policies from xml. 103 static final PolicyDefinition<Integer> GENERIC_PERMISSION_GRANT = 104 new PolicyDefinition<>( 105 new PackagePermissionPolicyKey(DevicePolicyIdentifiers.PERMISSION_GRANT_POLICY), 106 // TODO: is this really the best mechanism, what makes denied more 107 // restrictive than 108 // granted? 109 new MostRestrictive<>( 110 List.of( 111 new IntegerPolicyValue( 112 DevicePolicyManager.PERMISSION_GRANT_STATE_DENIED), 113 new IntegerPolicyValue( 114 DevicePolicyManager.PERMISSION_GRANT_STATE_GRANTED), 115 new IntegerPolicyValue( 116 DevicePolicyManager.PERMISSION_GRANT_STATE_DEFAULT))), 117 POLICY_FLAG_LOCAL_ONLY_POLICY, 118 PolicyEnforcerCallbacks::setPermissionGrantState, 119 new IntegerPolicySerializer()); 120 121 /** 122 * Passing in {@code null} for {@code packageName} or {@code permissionName} will return a 123 * {@link #GENERIC_PERMISSION_GRANT}. 124 */ PERMISSION_GRANT( @onNull String packageName, @NonNull String permissionName)125 static PolicyDefinition<Integer> PERMISSION_GRANT( 126 @NonNull String packageName, @NonNull String permissionName) { 127 if (packageName == null || permissionName == null) { 128 return GENERIC_PERMISSION_GRANT; 129 } 130 return GENERIC_PERMISSION_GRANT.createPolicyDefinition( 131 new PackagePermissionPolicyKey( 132 DevicePolicyIdentifiers.PERMISSION_GRANT_POLICY, 133 packageName, 134 permissionName)); 135 } 136 137 static PolicyDefinition<LockTaskPolicy> LOCK_TASK = new PolicyDefinition<>( 138 new NoArgsPolicyKey(DevicePolicyIdentifiers.LOCK_TASK_POLICY), 139 new TopPriority<>(List.of( 140 EnforcingAdmin.getRoleAuthorityOf(DEVICE_LOCK_CONTROLLER_ROLE), 141 EnforcingAdmin.DPC_AUTHORITY)), 142 POLICY_FLAG_LOCAL_ONLY_POLICY, 143 (LockTaskPolicy value, Context context, Integer userId, PolicyKey policyKey) -> 144 PolicyEnforcerCallbacks.setLockTask(value, context, userId), 145 new LockTaskPolicySerializer()); 146 147 static PolicyDefinition<Set<String>> USER_CONTROLLED_DISABLED_PACKAGES = 148 new PolicyDefinition<>( 149 new NoArgsPolicyKey( 150 DevicePolicyIdentifiers.USER_CONTROL_DISABLED_PACKAGES_POLICY), 151 new StringSetUnion(), 152 (Set<String> value, Context context, Integer userId, PolicyKey policyKey) -> 153 PolicyEnforcerCallbacks.setUserControlDisabledPackages(value, userId), 154 new StringSetPolicySerializer()); 155 156 // This is saved in the static map sPolicyDefinitions so that we're able to reconstruct the 157 // actual policy with the correct arguments (i.e. packageName) when reading the policies from 158 // xml. 159 static PolicyDefinition<ComponentName> GENERIC_PERSISTENT_PREFERRED_ACTIVITY = 160 new PolicyDefinition<>( 161 new IntentFilterPolicyKey( 162 DevicePolicyIdentifiers.PERSISTENT_PREFERRED_ACTIVITY_POLICY), 163 new TopPriority<>(List.of( 164 EnforcingAdmin.getRoleAuthorityOf(DEVICE_LOCK_CONTROLLER_ROLE), 165 EnforcingAdmin.DPC_AUTHORITY)), 166 POLICY_FLAG_LOCAL_ONLY_POLICY, 167 PolicyEnforcerCallbacks::addPersistentPreferredActivity, 168 new ComponentNamePolicySerializer()); 169 170 /** 171 * Passing in {@code null} for {@code intentFilter} will return 172 * {@link #GENERIC_PERSISTENT_PREFERRED_ACTIVITY}. 173 */ PERSISTENT_PREFERRED_ACTIVITY( IntentFilter intentFilter)174 static PolicyDefinition<ComponentName> PERSISTENT_PREFERRED_ACTIVITY( 175 IntentFilter intentFilter) { 176 if (intentFilter == null) { 177 return GENERIC_PERSISTENT_PREFERRED_ACTIVITY; 178 } 179 return GENERIC_PERSISTENT_PREFERRED_ACTIVITY.createPolicyDefinition( 180 new IntentFilterPolicyKey( 181 DevicePolicyIdentifiers.PERSISTENT_PREFERRED_ACTIVITY_POLICY, 182 intentFilter)); 183 } 184 185 // This is saved in the static map sPolicyDefinitions so that we're able to reconstruct the 186 // actual policy with the correct arguments (i.e. packageName) when reading the policies from 187 // xml. 188 static PolicyDefinition<Boolean> GENERIC_PACKAGE_UNINSTALL_BLOCKED = 189 new PolicyDefinition<>( 190 new PackagePolicyKey( 191 DevicePolicyIdentifiers.PACKAGE_UNINSTALL_BLOCKED_POLICY), 192 TRUE_MORE_RESTRICTIVE, 193 POLICY_FLAG_LOCAL_ONLY_POLICY, 194 PolicyEnforcerCallbacks::setUninstallBlocked, 195 new BooleanPolicySerializer()); 196 197 /** 198 * Passing in {@code null} for {@code packageName} will return 199 * {@link #GENERIC_PACKAGE_UNINSTALL_BLOCKED}. 200 */ PACKAGE_UNINSTALL_BLOCKED( String packageName)201 static PolicyDefinition<Boolean> PACKAGE_UNINSTALL_BLOCKED( 202 String packageName) { 203 if (packageName == null) { 204 return GENERIC_PACKAGE_UNINSTALL_BLOCKED; 205 } 206 return GENERIC_PACKAGE_UNINSTALL_BLOCKED.createPolicyDefinition( 207 new PackagePolicyKey( 208 DevicePolicyIdentifiers.PACKAGE_UNINSTALL_BLOCKED_POLICY, packageName)); 209 } 210 211 // This is saved in the static map sPolicyDefinitions so that we're able to reconstruct the 212 // actual policy with the correct arguments (i.e. packageName) when reading the policies from 213 // xml. 214 static PolicyDefinition<Bundle> GENERIC_APPLICATION_RESTRICTIONS = 215 new PolicyDefinition<>( 216 new PackagePolicyKey( 217 DevicePolicyIdentifiers.APPLICATION_RESTRICTIONS_POLICY), 218 // Don't need to take in a resolution mechanism since its never used, but might 219 // need some refactoring to not always assume a non-null mechanism. 220 new MostRecent<>(), 221 POLICY_FLAG_LOCAL_ONLY_POLICY | POLICY_FLAG_NON_COEXISTABLE_POLICY, 222 // Application restrictions are now stored and retrieved from DPMS, so no 223 // enforcing is required, however DPMS calls into UM to set restrictions for 224 // backwards compatibility. 225 (Bundle value, Context context, Integer userId, PolicyKey policyKey) -> true, 226 new BundlePolicySerializer()); 227 228 /** 229 * Passing in {@code null} for {@code packageName} will return 230 * {@link #GENERIC_APPLICATION_RESTRICTIONS}. 231 */ APPLICATION_RESTRICTIONS(String packageName)232 static PolicyDefinition<Bundle> APPLICATION_RESTRICTIONS(String packageName) { 233 if (packageName == null) { 234 return GENERIC_APPLICATION_RESTRICTIONS; 235 } 236 return GENERIC_APPLICATION_RESTRICTIONS.createPolicyDefinition( 237 new PackagePolicyKey( 238 DevicePolicyIdentifiers.APPLICATION_RESTRICTIONS_POLICY, packageName)); 239 } 240 241 static PolicyDefinition<Long> RESET_PASSWORD_TOKEN = new PolicyDefinition<>( 242 new NoArgsPolicyKey(DevicePolicyIdentifiers.RESET_PASSWORD_TOKEN_POLICY), 243 // Don't need to take in a resolution mechanism since its never used, but might 244 // need some refactoring to not always assume a non-null mechanism. 245 new MostRecent<>(), 246 POLICY_FLAG_LOCAL_ONLY_POLICY | POLICY_FLAG_NON_COEXISTABLE_POLICY, 247 // DevicePolicyManagerService handles the enforcement, this just takes care of storage 248 (Long value, Context context, Integer userId, PolicyKey policyKey) -> true, 249 new LongPolicySerializer()); 250 251 static PolicyDefinition<Integer> KEYGUARD_DISABLED_FEATURES = new PolicyDefinition<>( 252 new NoArgsPolicyKey(DevicePolicyIdentifiers.KEYGUARD_DISABLED_FEATURES_POLICY), 253 new FlagUnion(), 254 POLICY_FLAG_LOCAL_ONLY_POLICY, 255 // Nothing is enforced for keyguard features, we just need to store it 256 (Integer value, Context context, Integer userId, PolicyKey policyKey) -> true, 257 new IntegerPolicySerializer()); 258 259 // This is saved in the static map sPolicyDefinitions so that we're able to reconstruct the 260 // actual policy with the correct arguments (i.e. packageName) when reading the policies from 261 // xml. 262 static PolicyDefinition<Boolean> GENERIC_APPLICATION_HIDDEN = 263 new PolicyDefinition<>( 264 new PackagePolicyKey( 265 DevicePolicyIdentifiers.APPLICATION_HIDDEN_POLICY), 266 // TODO(b/276713779): Don't need to take in a resolution mechanism since its 267 // never used, but might need some refactoring to not always assume a non-null 268 // mechanism. 269 TRUE_MORE_RESTRICTIVE, 270 POLICY_FLAG_LOCAL_ONLY_POLICY | POLICY_FLAG_INHERITABLE, 271 PolicyEnforcerCallbacks::setApplicationHidden, 272 new BooleanPolicySerializer()); 273 274 /** 275 * Passing in {@code null} for {@code packageName} will return 276 * {@link #GENERIC_APPLICATION_HIDDEN}. 277 */ APPLICATION_HIDDEN(String packageName)278 static PolicyDefinition<Boolean> APPLICATION_HIDDEN(String packageName) { 279 if (packageName == null) { 280 return GENERIC_APPLICATION_HIDDEN; 281 } 282 return GENERIC_APPLICATION_HIDDEN.createPolicyDefinition( 283 new PackagePolicyKey( 284 DevicePolicyIdentifiers.APPLICATION_HIDDEN_POLICY, packageName)); 285 } 286 287 // This is saved in the static map sPolicyDefinitions so that we're able to reconstruct the 288 // actual policy with the correct arguments (i.e. packageName) when reading the policies from 289 // xml. 290 static PolicyDefinition<Boolean> GENERIC_ACCOUNT_MANAGEMENT_DISABLED = 291 new PolicyDefinition<>( 292 new AccountTypePolicyKey( 293 DevicePolicyIdentifiers.ACCOUNT_MANAGEMENT_DISABLED_POLICY), 294 TRUE_MORE_RESTRICTIVE, 295 POLICY_FLAG_LOCAL_ONLY_POLICY | POLICY_FLAG_INHERITABLE, 296 // Nothing is enforced, we just need to store it 297 (Boolean value, Context context, Integer userId, PolicyKey policyKey) -> true, 298 new BooleanPolicySerializer()); 299 300 /** 301 * Passing in {@code null} for {@code accountType} will return 302 * {@link #GENERIC_ACCOUNT_MANAGEMENT_DISABLED}. 303 */ ACCOUNT_MANAGEMENT_DISABLED(String accountType)304 static PolicyDefinition<Boolean> ACCOUNT_MANAGEMENT_DISABLED(String accountType) { 305 if (accountType == null) { 306 return GENERIC_ACCOUNT_MANAGEMENT_DISABLED; 307 } 308 return GENERIC_ACCOUNT_MANAGEMENT_DISABLED.createPolicyDefinition( 309 new AccountTypePolicyKey( 310 DevicePolicyIdentifiers.ACCOUNT_MANAGEMENT_DISABLED_POLICY, accountType)); 311 } 312 313 static PolicyDefinition<Set<String>> PERMITTED_INPUT_METHODS = new PolicyDefinition<>( 314 new NoArgsPolicyKey(DevicePolicyIdentifiers.PERMITTED_INPUT_METHODS_POLICY), 315 new MostRecent<>(), 316 POLICY_FLAG_LOCAL_ONLY_POLICY | POLICY_FLAG_INHERITABLE, 317 (Set<String> value, Context context, Integer userId, PolicyKey policyKey) -> true, 318 new StringSetPolicySerializer()); 319 320 321 static PolicyDefinition<Boolean> SCREEN_CAPTURE_DISABLED = new PolicyDefinition<>( 322 new NoArgsPolicyKey(DevicePolicyIdentifiers.SCREEN_CAPTURE_DISABLED_POLICY), 323 TRUE_MORE_RESTRICTIVE, 324 POLICY_FLAG_INHERITABLE, 325 PolicyEnforcerCallbacks::setScreenCaptureDisabled, 326 new BooleanPolicySerializer()); 327 328 static PolicyDefinition<Boolean> PERSONAL_APPS_SUSPENDED = new PolicyDefinition<>( 329 new NoArgsPolicyKey(DevicePolicyIdentifiers.PERSONAL_APPS_SUSPENDED_POLICY), 330 new MostRecent<>(), 331 POLICY_FLAG_LOCAL_ONLY_POLICY | POLICY_FLAG_INHERITABLE, 332 PolicyEnforcerCallbacks::setPersonalAppsSuspended, 333 new BooleanPolicySerializer()); 334 335 336 private static final Map<String, PolicyDefinition<?>> POLICY_DEFINITIONS = new HashMap<>(); 337 private static Map<String, Integer> USER_RESTRICTION_FLAGS = new HashMap<>(); 338 339 // TODO(b/277218360): Revisit policies that should be marked as global-only. 340 static { POLICY_DEFINITIONS.put(DevicePolicyIdentifiers.AUTO_TIMEZONE_POLICY, AUTO_TIMEZONE)341 POLICY_DEFINITIONS.put(DevicePolicyIdentifiers.AUTO_TIMEZONE_POLICY, AUTO_TIMEZONE); POLICY_DEFINITIONS.put(DevicePolicyIdentifiers.PERMISSION_GRANT_POLICY, GENERIC_PERMISSION_GRANT)342 POLICY_DEFINITIONS.put(DevicePolicyIdentifiers.PERMISSION_GRANT_POLICY, 343 GENERIC_PERMISSION_GRANT); POLICY_DEFINITIONS.put(DevicePolicyIdentifiers.LOCK_TASK_POLICY, LOCK_TASK)344 POLICY_DEFINITIONS.put(DevicePolicyIdentifiers.LOCK_TASK_POLICY, LOCK_TASK); POLICY_DEFINITIONS.put(DevicePolicyIdentifiers.USER_CONTROL_DISABLED_PACKAGES_POLICY, USER_CONTROLLED_DISABLED_PACKAGES)345 POLICY_DEFINITIONS.put(DevicePolicyIdentifiers.USER_CONTROL_DISABLED_PACKAGES_POLICY, 346 USER_CONTROLLED_DISABLED_PACKAGES); POLICY_DEFINITIONS.put(DevicePolicyIdentifiers.PERSISTENT_PREFERRED_ACTIVITY_POLICY, GENERIC_PERSISTENT_PREFERRED_ACTIVITY)347 POLICY_DEFINITIONS.put(DevicePolicyIdentifiers.PERSISTENT_PREFERRED_ACTIVITY_POLICY, 348 GENERIC_PERSISTENT_PREFERRED_ACTIVITY); POLICY_DEFINITIONS.put(DevicePolicyIdentifiers.PACKAGE_UNINSTALL_BLOCKED_POLICY, GENERIC_PACKAGE_UNINSTALL_BLOCKED)349 POLICY_DEFINITIONS.put(DevicePolicyIdentifiers.PACKAGE_UNINSTALL_BLOCKED_POLICY, 350 GENERIC_PACKAGE_UNINSTALL_BLOCKED); POLICY_DEFINITIONS.put(DevicePolicyIdentifiers.APPLICATION_RESTRICTIONS_POLICY, GENERIC_APPLICATION_RESTRICTIONS)351 POLICY_DEFINITIONS.put(DevicePolicyIdentifiers.APPLICATION_RESTRICTIONS_POLICY, 352 GENERIC_APPLICATION_RESTRICTIONS); POLICY_DEFINITIONS.put(DevicePolicyIdentifiers.RESET_PASSWORD_TOKEN_POLICY, RESET_PASSWORD_TOKEN)353 POLICY_DEFINITIONS.put(DevicePolicyIdentifiers.RESET_PASSWORD_TOKEN_POLICY, 354 RESET_PASSWORD_TOKEN); POLICY_DEFINITIONS.put(DevicePolicyIdentifiers.KEYGUARD_DISABLED_FEATURES_POLICY, KEYGUARD_DISABLED_FEATURES)355 POLICY_DEFINITIONS.put(DevicePolicyIdentifiers.KEYGUARD_DISABLED_FEATURES_POLICY, 356 KEYGUARD_DISABLED_FEATURES); POLICY_DEFINITIONS.put(DevicePolicyIdentifiers.APPLICATION_HIDDEN_POLICY, GENERIC_APPLICATION_HIDDEN)357 POLICY_DEFINITIONS.put(DevicePolicyIdentifiers.APPLICATION_HIDDEN_POLICY, 358 GENERIC_APPLICATION_HIDDEN); POLICY_DEFINITIONS.put(DevicePolicyIdentifiers.ACCOUNT_MANAGEMENT_DISABLED_POLICY, GENERIC_ACCOUNT_MANAGEMENT_DISABLED)359 POLICY_DEFINITIONS.put(DevicePolicyIdentifiers.ACCOUNT_MANAGEMENT_DISABLED_POLICY, 360 GENERIC_ACCOUNT_MANAGEMENT_DISABLED); POLICY_DEFINITIONS.put(DevicePolicyIdentifiers.PERMITTED_INPUT_METHODS_POLICY, PERMITTED_INPUT_METHODS)361 POLICY_DEFINITIONS.put(DevicePolicyIdentifiers.PERMITTED_INPUT_METHODS_POLICY, 362 PERMITTED_INPUT_METHODS); POLICY_DEFINITIONS.put(DevicePolicyIdentifiers.SCREEN_CAPTURE_DISABLED_POLICY, SCREEN_CAPTURE_DISABLED)363 POLICY_DEFINITIONS.put(DevicePolicyIdentifiers.SCREEN_CAPTURE_DISABLED_POLICY, 364 SCREEN_CAPTURE_DISABLED); POLICY_DEFINITIONS.put(DevicePolicyIdentifiers.PERSONAL_APPS_SUSPENDED_POLICY, PERSONAL_APPS_SUSPENDED)365 POLICY_DEFINITIONS.put(DevicePolicyIdentifiers.PERSONAL_APPS_SUSPENDED_POLICY, 366 PERSONAL_APPS_SUSPENDED); 367 368 // User Restriction Policies USER_RESTRICTION_FLAGS.put(UserManager.DISALLOW_MODIFY_ACCOUNTS, 0)369 USER_RESTRICTION_FLAGS.put(UserManager.DISALLOW_MODIFY_ACCOUNTS, /* flags= */ 0); USER_RESTRICTION_FLAGS.put(UserManager.DISALLOW_CONFIG_WIFI, 0)370 USER_RESTRICTION_FLAGS.put(UserManager.DISALLOW_CONFIG_WIFI, /* flags= */ 0); USER_RESTRICTION_FLAGS.put( UserManager.DISALLOW_CHANGE_WIFI_STATE, POLICY_FLAG_GLOBAL_ONLY_POLICY)371 USER_RESTRICTION_FLAGS.put( 372 UserManager.DISALLOW_CHANGE_WIFI_STATE, POLICY_FLAG_GLOBAL_ONLY_POLICY); USER_RESTRICTION_FLAGS.put( UserManager.DISALLOW_WIFI_TETHERING, POLICY_FLAG_GLOBAL_ONLY_POLICY)373 USER_RESTRICTION_FLAGS.put( 374 UserManager.DISALLOW_WIFI_TETHERING, POLICY_FLAG_GLOBAL_ONLY_POLICY); USER_RESTRICTION_FLAGS.put(UserManager.DISALLOW_GRANT_ADMIN, 0)375 USER_RESTRICTION_FLAGS.put(UserManager.DISALLOW_GRANT_ADMIN, /* flags= */ 0); 376 // TODO: set as global only once we get rid of the mapping USER_RESTRICTION_FLAGS.put( UserManager.DISALLOW_SHARING_ADMIN_CONFIGURED_WIFI, 0)377 USER_RESTRICTION_FLAGS.put( 378 UserManager.DISALLOW_SHARING_ADMIN_CONFIGURED_WIFI, /* flags= */ 0); USER_RESTRICTION_FLAGS.put( UserManager.DISALLOW_WIFI_DIRECT, POLICY_FLAG_GLOBAL_ONLY_POLICY)379 USER_RESTRICTION_FLAGS.put( 380 UserManager.DISALLOW_WIFI_DIRECT, POLICY_FLAG_GLOBAL_ONLY_POLICY); USER_RESTRICTION_FLAGS.put( UserManager.DISALLOW_ADD_WIFI_CONFIG, POLICY_FLAG_GLOBAL_ONLY_POLICY)381 USER_RESTRICTION_FLAGS.put( 382 UserManager.DISALLOW_ADD_WIFI_CONFIG, POLICY_FLAG_GLOBAL_ONLY_POLICY); USER_RESTRICTION_FLAGS.put(UserManager.DISALLOW_CONFIG_LOCALE, 0)383 USER_RESTRICTION_FLAGS.put(UserManager.DISALLOW_CONFIG_LOCALE, /* flags= */ 0); USER_RESTRICTION_FLAGS.put(UserManager.DISALLOW_INSTALL_APPS, 0)384 USER_RESTRICTION_FLAGS.put(UserManager.DISALLOW_INSTALL_APPS, /* flags= */ 0); USER_RESTRICTION_FLAGS.put(UserManager.DISALLOW_UNINSTALL_APPS, 0)385 USER_RESTRICTION_FLAGS.put(UserManager.DISALLOW_UNINSTALL_APPS, /* flags= */ 0); USER_RESTRICTION_FLAGS.put(UserManager.DISALLOW_SHARE_LOCATION, 0)386 USER_RESTRICTION_FLAGS.put(UserManager.DISALLOW_SHARE_LOCATION, /* flags= */ 0); USER_RESTRICTION_FLAGS.put( UserManager.DISALLOW_AIRPLANE_MODE, POLICY_FLAG_GLOBAL_ONLY_POLICY)387 USER_RESTRICTION_FLAGS.put( 388 UserManager.DISALLOW_AIRPLANE_MODE, POLICY_FLAG_GLOBAL_ONLY_POLICY); USER_RESTRICTION_FLAGS.put(UserManager.DISALLOW_CONFIG_BRIGHTNESS, 0)389 USER_RESTRICTION_FLAGS.put(UserManager.DISALLOW_CONFIG_BRIGHTNESS, /* flags= */ 0); USER_RESTRICTION_FLAGS.put(UserManager.DISALLOW_AMBIENT_DISPLAY, 0)390 USER_RESTRICTION_FLAGS.put(UserManager.DISALLOW_AMBIENT_DISPLAY, /* flags= */ 0); USER_RESTRICTION_FLAGS.put(UserManager.DISALLOW_CONFIG_SCREEN_TIMEOUT, 0)391 USER_RESTRICTION_FLAGS.put(UserManager.DISALLOW_CONFIG_SCREEN_TIMEOUT, /* flags= */ 0); USER_RESTRICTION_FLAGS.put(UserManager.DISALLOW_INSTALL_UNKNOWN_SOURCES, 0)392 USER_RESTRICTION_FLAGS.put(UserManager.DISALLOW_INSTALL_UNKNOWN_SOURCES, /* flags= */ 0); USER_RESTRICTION_FLAGS.put(UserManager.DISALLOW_INSTALL_UNKNOWN_SOURCES_GLOBALLY, POLICY_FLAG_GLOBAL_ONLY_POLICY)393 USER_RESTRICTION_FLAGS.put(UserManager.DISALLOW_INSTALL_UNKNOWN_SOURCES_GLOBALLY, 394 POLICY_FLAG_GLOBAL_ONLY_POLICY); USER_RESTRICTION_FLAGS.put(UserManager.DISALLOW_CONFIG_BLUETOOTH, 0)395 USER_RESTRICTION_FLAGS.put(UserManager.DISALLOW_CONFIG_BLUETOOTH, /* flags= */ 0); USER_RESTRICTION_FLAGS.put(UserManager.DISALLOW_BLUETOOTH, 0)396 USER_RESTRICTION_FLAGS.put(UserManager.DISALLOW_BLUETOOTH, /* flags= */ 0); USER_RESTRICTION_FLAGS.put(UserManager.DISALLOW_BLUETOOTH_SHARING, 0)397 USER_RESTRICTION_FLAGS.put(UserManager.DISALLOW_BLUETOOTH_SHARING, /* flags= */ 0); 398 // This effectively always applies globally, but it can be set on the profile 399 // parent, check the javadocs on the restriction for more info. USER_RESTRICTION_FLAGS.put( UserManager.DISALLOW_USB_FILE_TRANSFER, 0)400 USER_RESTRICTION_FLAGS.put( 401 UserManager.DISALLOW_USB_FILE_TRANSFER, /* flags= */ 0); USER_RESTRICTION_FLAGS.put(UserManager.DISALLOW_CONFIG_CREDENTIALS, 0)402 USER_RESTRICTION_FLAGS.put(UserManager.DISALLOW_CONFIG_CREDENTIALS, /* flags= */ 0); USER_RESTRICTION_FLAGS.put(UserManager.DISALLOW_REMOVE_USER, 0)403 USER_RESTRICTION_FLAGS.put(UserManager.DISALLOW_REMOVE_USER, /* flags= */ 0); USER_RESTRICTION_FLAGS.put(UserManager.DISALLOW_REMOVE_MANAGED_PROFILE, 0)404 USER_RESTRICTION_FLAGS.put(UserManager.DISALLOW_REMOVE_MANAGED_PROFILE, /* flags= */ 0); USER_RESTRICTION_FLAGS.put(UserManager.DISALLOW_DEBUGGING_FEATURES, 0)405 USER_RESTRICTION_FLAGS.put(UserManager.DISALLOW_DEBUGGING_FEATURES, /* flags= */ 0); USER_RESTRICTION_FLAGS.put(UserManager.DISALLOW_CONFIG_VPN, 0)406 USER_RESTRICTION_FLAGS.put(UserManager.DISALLOW_CONFIG_VPN, /* flags= */ 0); USER_RESTRICTION_FLAGS.put(UserManager.DISALLOW_CONFIG_LOCATION, 0)407 USER_RESTRICTION_FLAGS.put(UserManager.DISALLOW_CONFIG_LOCATION, /* flags= */ 0); USER_RESTRICTION_FLAGS.put(UserManager.DISALLOW_CONFIG_DATE_TIME, 0)408 USER_RESTRICTION_FLAGS.put(UserManager.DISALLOW_CONFIG_DATE_TIME, /* flags= */ 0); USER_RESTRICTION_FLAGS.put( UserManager.DISALLOW_CONFIG_TETHERING, 0)409 USER_RESTRICTION_FLAGS.put( 410 UserManager.DISALLOW_CONFIG_TETHERING, /* flags= */ 0); 411 // This effectively always applies globally, but it can be set on the profile 412 // parent, check the javadocs on the restriction for more info. USER_RESTRICTION_FLAGS.put( UserManager.DISALLOW_NETWORK_RESET, 0)413 USER_RESTRICTION_FLAGS.put( 414 UserManager.DISALLOW_NETWORK_RESET, /* flags= */ 0); USER_RESTRICTION_FLAGS.put(UserManager.DISALLOW_FACTORY_RESET, 0)415 USER_RESTRICTION_FLAGS.put(UserManager.DISALLOW_FACTORY_RESET, /* flags= */ 0); USER_RESTRICTION_FLAGS.put(UserManager.DISALLOW_ADD_USER, 0)416 USER_RESTRICTION_FLAGS.put(UserManager.DISALLOW_ADD_USER, /* flags= */ 0); USER_RESTRICTION_FLAGS.put(UserManager.DISALLOW_ADD_MANAGED_PROFILE, 0)417 USER_RESTRICTION_FLAGS.put(UserManager.DISALLOW_ADD_MANAGED_PROFILE, /* flags= */ 0); USER_RESTRICTION_FLAGS.put(UserManager.DISALLOW_ADD_CLONE_PROFILE, 0)418 USER_RESTRICTION_FLAGS.put(UserManager.DISALLOW_ADD_CLONE_PROFILE, /* flags= */ 0); USER_RESTRICTION_FLAGS.put(UserManager.ENSURE_VERIFY_APPS, POLICY_FLAG_GLOBAL_ONLY_POLICY)419 USER_RESTRICTION_FLAGS.put(UserManager.ENSURE_VERIFY_APPS, POLICY_FLAG_GLOBAL_ONLY_POLICY); USER_RESTRICTION_FLAGS.put(UserManager.DISALLOW_CONFIG_CELL_BROADCASTS, 0)420 USER_RESTRICTION_FLAGS.put(UserManager.DISALLOW_CONFIG_CELL_BROADCASTS, /* flags= */ 0); USER_RESTRICTION_FLAGS.put(UserManager.DISALLOW_CONFIG_MOBILE_NETWORKS, 0)421 USER_RESTRICTION_FLAGS.put(UserManager.DISALLOW_CONFIG_MOBILE_NETWORKS, /* flags= */ 0); USER_RESTRICTION_FLAGS.put(UserManager.DISALLOW_APPS_CONTROL, 0)422 USER_RESTRICTION_FLAGS.put(UserManager.DISALLOW_APPS_CONTROL, /* flags= */ 0); USER_RESTRICTION_FLAGS.put(UserManager.DISALLOW_MOUNT_PHYSICAL_MEDIA, 0)423 USER_RESTRICTION_FLAGS.put(UserManager.DISALLOW_MOUNT_PHYSICAL_MEDIA, /* flags= */ 0); USER_RESTRICTION_FLAGS.put(UserManager.DISALLOW_UNMUTE_MICROPHONE, 0)424 USER_RESTRICTION_FLAGS.put(UserManager.DISALLOW_UNMUTE_MICROPHONE, /* flags= */ 0); USER_RESTRICTION_FLAGS.put(UserManager.DISALLOW_ADJUST_VOLUME, 0)425 USER_RESTRICTION_FLAGS.put(UserManager.DISALLOW_ADJUST_VOLUME, /* flags= */ 0); USER_RESTRICTION_FLAGS.put(UserManager.DISALLOW_OUTGOING_CALLS, 0)426 USER_RESTRICTION_FLAGS.put(UserManager.DISALLOW_OUTGOING_CALLS, /* flags= */ 0); USER_RESTRICTION_FLAGS.put(UserManager.DISALLOW_SMS, 0)427 USER_RESTRICTION_FLAGS.put(UserManager.DISALLOW_SMS, /* flags= */ 0); 428 // TODO: check if its global only USER_RESTRICTION_FLAGS.put(UserManager.DISALLOW_FUN, 0)429 USER_RESTRICTION_FLAGS.put(UserManager.DISALLOW_FUN, /* flags= */ 0); 430 // TODO: check if its global only USER_RESTRICTION_FLAGS.put(UserManager.DISALLOW_CREATE_WINDOWS, 0)431 USER_RESTRICTION_FLAGS.put(UserManager.DISALLOW_CREATE_WINDOWS, /* flags= */ 0); USER_RESTRICTION_FLAGS.put(UserManager.DISALLOW_SYSTEM_ERROR_DIALOGS, 0)432 USER_RESTRICTION_FLAGS.put(UserManager.DISALLOW_SYSTEM_ERROR_DIALOGS, /* flags= */ 0); USER_RESTRICTION_FLAGS.put(UserManager.DISALLOW_CROSS_PROFILE_COPY_PASTE, 0)433 USER_RESTRICTION_FLAGS.put(UserManager.DISALLOW_CROSS_PROFILE_COPY_PASTE, /* flags= */ 0); 434 // TODO: check if its global only USER_RESTRICTION_FLAGS.put(UserManager.DISALLOW_OUTGOING_BEAM, 0)435 USER_RESTRICTION_FLAGS.put(UserManager.DISALLOW_OUTGOING_BEAM, /* flags= */ 0); USER_RESTRICTION_FLAGS.put(UserManager.DISALLOW_WALLPAPER, 0)436 USER_RESTRICTION_FLAGS.put(UserManager.DISALLOW_WALLPAPER, /* flags= */ 0); USER_RESTRICTION_FLAGS.put(UserManager.DISALLOW_SET_WALLPAPER, 0)437 USER_RESTRICTION_FLAGS.put(UserManager.DISALLOW_SET_WALLPAPER, /* flags= */ 0); USER_RESTRICTION_FLAGS.put(UserManager.DISALLOW_SAFE_BOOT, 0)438 USER_RESTRICTION_FLAGS.put(UserManager.DISALLOW_SAFE_BOOT, /* flags= */ 0); USER_RESTRICTION_FLAGS.put(UserManager.DISALLOW_RECORD_AUDIO, 0)439 USER_RESTRICTION_FLAGS.put(UserManager.DISALLOW_RECORD_AUDIO, /* flags= */ 0); USER_RESTRICTION_FLAGS.put(UserManager.DISALLOW_RUN_IN_BACKGROUND, 0)440 USER_RESTRICTION_FLAGS.put(UserManager.DISALLOW_RUN_IN_BACKGROUND, /* flags= */ 0); USER_RESTRICTION_FLAGS.put(UserManager.DISALLOW_CAMERA, 0)441 USER_RESTRICTION_FLAGS.put(UserManager.DISALLOW_CAMERA, /* flags= */ 0); USER_RESTRICTION_FLAGS.put(UserManager.DISALLOW_UNMUTE_DEVICE, 0)442 USER_RESTRICTION_FLAGS.put(UserManager.DISALLOW_UNMUTE_DEVICE, /* flags= */ 0); USER_RESTRICTION_FLAGS.put(UserManager.DISALLOW_DATA_ROAMING, 0)443 USER_RESTRICTION_FLAGS.put(UserManager.DISALLOW_DATA_ROAMING, /* flags= */ 0); USER_RESTRICTION_FLAGS.put(UserManager.DISALLOW_SET_USER_ICON, 0)444 USER_RESTRICTION_FLAGS.put(UserManager.DISALLOW_SET_USER_ICON, /* flags= */ 0); USER_RESTRICTION_FLAGS.put(UserManager.DISALLOW_OEM_UNLOCK, 0)445 USER_RESTRICTION_FLAGS.put(UserManager.DISALLOW_OEM_UNLOCK, /* flags= */ 0); USER_RESTRICTION_FLAGS.put(UserManager.DISALLOW_UNIFIED_PASSWORD, 0)446 USER_RESTRICTION_FLAGS.put(UserManager.DISALLOW_UNIFIED_PASSWORD, /* flags= */ 0); USER_RESTRICTION_FLAGS.put(UserManager.ALLOW_PARENT_PROFILE_APP_LINKING, 0)447 USER_RESTRICTION_FLAGS.put(UserManager.ALLOW_PARENT_PROFILE_APP_LINKING, /* flags= */ 0); USER_RESTRICTION_FLAGS.put(UserManager.DISALLOW_AUTOFILL, 0)448 USER_RESTRICTION_FLAGS.put(UserManager.DISALLOW_AUTOFILL, /* flags= */ 0); USER_RESTRICTION_FLAGS.put(UserManager.DISALLOW_CONTENT_CAPTURE, 0)449 USER_RESTRICTION_FLAGS.put(UserManager.DISALLOW_CONTENT_CAPTURE, /* flags= */ 0); USER_RESTRICTION_FLAGS.put(UserManager.DISALLOW_CONTENT_SUGGESTIONS, 0)450 USER_RESTRICTION_FLAGS.put(UserManager.DISALLOW_CONTENT_SUGGESTIONS, /* flags= */ 0); USER_RESTRICTION_FLAGS.put( UserManager.DISALLOW_USER_SWITCH, POLICY_FLAG_GLOBAL_ONLY_POLICY)451 USER_RESTRICTION_FLAGS.put( 452 UserManager.DISALLOW_USER_SWITCH, POLICY_FLAG_GLOBAL_ONLY_POLICY); USER_RESTRICTION_FLAGS.put(UserManager.DISALLOW_SHARE_INTO_MANAGED_PROFILE, 0)453 USER_RESTRICTION_FLAGS.put(UserManager.DISALLOW_SHARE_INTO_MANAGED_PROFILE, /* flags= */ 0); USER_RESTRICTION_FLAGS.put(UserManager.DISALLOW_PRINTING, 0)454 USER_RESTRICTION_FLAGS.put(UserManager.DISALLOW_PRINTING, /* flags= */ 0); USER_RESTRICTION_FLAGS.put( UserManager.DISALLOW_CONFIG_PRIVATE_DNS, POLICY_FLAG_GLOBAL_ONLY_POLICY)455 USER_RESTRICTION_FLAGS.put( 456 UserManager.DISALLOW_CONFIG_PRIVATE_DNS, POLICY_FLAG_GLOBAL_ONLY_POLICY); USER_RESTRICTION_FLAGS.put(UserManager.DISALLOW_MICROPHONE_TOGGLE, 0)457 USER_RESTRICTION_FLAGS.put(UserManager.DISALLOW_MICROPHONE_TOGGLE, /* flags= */ 0); 458 // TODO: According the UserRestrictionsUtils, this is global only, need to confirm. USER_RESTRICTION_FLAGS.put(UserManager.DISALLOW_CAMERA_TOGGLE, 0)459 USER_RESTRICTION_FLAGS.put(UserManager.DISALLOW_CAMERA_TOGGLE, /* flags= */ 0); 460 // TODO: check if its global only USER_RESTRICTION_FLAGS.put(UserManager.DISALLOW_BIOMETRIC, 0)461 USER_RESTRICTION_FLAGS.put(UserManager.DISALLOW_BIOMETRIC, /* flags= */ 0); USER_RESTRICTION_FLAGS.put(UserManager.DISALLOW_CONFIG_DEFAULT_APPS, 0)462 USER_RESTRICTION_FLAGS.put(UserManager.DISALLOW_CONFIG_DEFAULT_APPS, /* flags= */ 0); USER_RESTRICTION_FLAGS.put( UserManager.DISALLOW_CELLULAR_2G, POLICY_FLAG_GLOBAL_ONLY_POLICY)463 USER_RESTRICTION_FLAGS.put( 464 UserManager.DISALLOW_CELLULAR_2G, POLICY_FLAG_GLOBAL_ONLY_POLICY); USER_RESTRICTION_FLAGS.put( UserManager.DISALLOW_ULTRA_WIDEBAND_RADIO, POLICY_FLAG_GLOBAL_ONLY_POLICY)465 USER_RESTRICTION_FLAGS.put( 466 UserManager.DISALLOW_ULTRA_WIDEBAND_RADIO, POLICY_FLAG_GLOBAL_ONLY_POLICY); 467 468 for (String key : USER_RESTRICTION_FLAGS.keySet()) { createAndAddUserRestrictionPolicyDefinition(key, USER_RESTRICTION_FLAGS.get(key))469 createAndAddUserRestrictionPolicyDefinition(key, USER_RESTRICTION_FLAGS.get(key)); 470 } 471 } 472 473 private final PolicyKey mPolicyKey; 474 private final ResolutionMechanism<V> mResolutionMechanism; 475 private final int mPolicyFlags; 476 // A function that accepts policy to apple, context, userId, callback arguments, and returns 477 // true if the policy has been enforced successfully. 478 private final QuadFunction<V, Context, Integer, PolicyKey, Boolean> mPolicyEnforcerCallback; 479 private final PolicySerializer<V> mPolicySerializer; 480 createPolicyDefinition(PolicyKey key)481 private PolicyDefinition<V> createPolicyDefinition(PolicyKey key) { 482 return new PolicyDefinition<>(key, mResolutionMechanism, mPolicyFlags, 483 mPolicyEnforcerCallback, mPolicySerializer); 484 } 485 getPolicyDefinitionForUserRestriction( @serManager.UserRestrictionKey String restriction)486 static PolicyDefinition<Boolean> getPolicyDefinitionForUserRestriction( 487 @UserManager.UserRestrictionKey String restriction) { 488 String key = DevicePolicyIdentifiers.getIdentifierForUserRestriction(restriction); 489 490 if (!POLICY_DEFINITIONS.containsKey(key)) { 491 throw new IllegalArgumentException("Unsupported user restriction " + restriction); 492 } 493 // All user restrictions are of type boolean 494 return (PolicyDefinition<Boolean>) POLICY_DEFINITIONS.get(key); 495 } 496 497 @NonNull getPolicyKey()498 PolicyKey getPolicyKey() { 499 return mPolicyKey; 500 } 501 502 @NonNull getResolutionMechanism()503 ResolutionMechanism<V> getResolutionMechanism() { 504 return mResolutionMechanism; 505 } 506 /** 507 * Returns {@code true} if the policy is a global policy by nature and can't be applied locally. 508 */ isGlobalOnlyPolicy()509 boolean isGlobalOnlyPolicy() { 510 return (mPolicyFlags & POLICY_FLAG_GLOBAL_ONLY_POLICY) != 0; 511 } 512 513 /** 514 * Returns {@code true} if the policy is a local policy by nature and can't be applied globally. 515 */ isLocalOnlyPolicy()516 boolean isLocalOnlyPolicy() { 517 return (mPolicyFlags & POLICY_FLAG_LOCAL_ONLY_POLICY) != 0; 518 } 519 520 /** 521 * Returns {@code true} if the policy is inheritable by child profiles. 522 */ isInheritable()523 boolean isInheritable() { 524 return (mPolicyFlags & POLICY_FLAG_INHERITABLE) != 0; 525 } 526 527 /** 528 * Returns {@code true} if the policy engine should not try to resolve policies set by different 529 * admins and should just store it and pass it on to the enforcing logic. 530 */ isNonCoexistablePolicy()531 boolean isNonCoexistablePolicy() { 532 return (mPolicyFlags & POLICY_FLAG_NON_COEXISTABLE_POLICY) != 0; 533 } 534 isUserRestrictionPolicy()535 boolean isUserRestrictionPolicy() { 536 return (mPolicyFlags & POLICY_FLAG_USER_RESTRICTION_POLICY) != 0; 537 } 538 539 @Nullable resolvePolicy(LinkedHashMap<EnforcingAdmin, PolicyValue<V>> adminsPolicy)540 PolicyValue<V> resolvePolicy(LinkedHashMap<EnforcingAdmin, PolicyValue<V>> adminsPolicy) { 541 return mResolutionMechanism.resolve(adminsPolicy); 542 } 543 enforcePolicy(@ullable V value, Context context, int userId)544 boolean enforcePolicy(@Nullable V value, Context context, int userId) { 545 return mPolicyEnforcerCallback.apply(value, context, userId, mPolicyKey); 546 } 547 createAndAddUserRestrictionPolicyDefinition( String restriction, int flags)548 private static void createAndAddUserRestrictionPolicyDefinition( 549 String restriction, int flags) { 550 String identifier = DevicePolicyIdentifiers.getIdentifierForUserRestriction(restriction); 551 UserRestrictionPolicyKey key = new UserRestrictionPolicyKey(identifier, restriction); 552 flags |= (POLICY_FLAG_USER_RESTRICTION_POLICY | POLICY_FLAG_INHERITABLE); 553 PolicyDefinition<Boolean> definition = new PolicyDefinition<>( 554 key, 555 TRUE_MORE_RESTRICTIVE, 556 flags, 557 PolicyEnforcerCallbacks::setUserRestriction, 558 new BooleanPolicySerializer()); 559 POLICY_DEFINITIONS.put(key.getIdentifier(), definition); 560 } 561 562 563 /** 564 * Callers must ensure that {@code policyType} have implemented an appropriate 565 * {@link Object#equals} implementation. 566 */ PolicyDefinition( PolicyKey key, ResolutionMechanism<V> resolutionMechanism, QuadFunction<V, Context, Integer, PolicyKey, Boolean> policyEnforcerCallback, PolicySerializer<V> policySerializer)567 private PolicyDefinition( 568 PolicyKey key, 569 ResolutionMechanism<V> resolutionMechanism, 570 QuadFunction<V, Context, Integer, PolicyKey, Boolean> policyEnforcerCallback, 571 PolicySerializer<V> policySerializer) { 572 this(key, resolutionMechanism, POLICY_FLAG_NONE, policyEnforcerCallback, policySerializer); 573 } 574 575 /** 576 * Callers must ensure that custom {@code policyKeys} and {@code V} have an appropriate 577 * {@link Object#equals} and {@link Object#hashCode()} implementation. 578 */ PolicyDefinition( PolicyKey policyKey, ResolutionMechanism<V> resolutionMechanism, int policyFlags, QuadFunction<V, Context, Integer, PolicyKey, Boolean> policyEnforcerCallback, PolicySerializer<V> policySerializer)579 private PolicyDefinition( 580 PolicyKey policyKey, 581 ResolutionMechanism<V> resolutionMechanism, 582 int policyFlags, 583 QuadFunction<V, Context, Integer, PolicyKey, Boolean> policyEnforcerCallback, 584 PolicySerializer<V> policySerializer) { 585 mPolicyKey = policyKey; 586 mResolutionMechanism = resolutionMechanism; 587 mPolicyFlags = policyFlags; 588 mPolicyEnforcerCallback = policyEnforcerCallback; 589 mPolicySerializer = policySerializer; 590 591 if (isNonCoexistablePolicy() && !isLocalOnlyPolicy()) { 592 throw new UnsupportedOperationException("Non-coexistable global policies not supported," 593 + "please add support."); 594 } 595 // TODO: maybe use this instead of manually adding to the map 596 // sPolicyDefinitions.put(policyDefinitionKey, this); 597 } 598 saveToXml(TypedXmlSerializer serializer)599 void saveToXml(TypedXmlSerializer serializer) throws IOException { 600 mPolicyKey.saveToXml(serializer); 601 } 602 603 @Nullable readFromXml(TypedXmlPullParser parser)604 static <V> PolicyDefinition<V> readFromXml(TypedXmlPullParser parser) 605 throws XmlPullParserException, IOException { 606 // TODO: can we avoid casting? 607 PolicyKey policyKey = readPolicyKeyFromXml(parser); 608 if (policyKey == null) { 609 Slogf.wtf(TAG, "Error parsing PolicyDefinition, PolicyKey is null."); 610 return null; 611 } 612 PolicyDefinition<V> genericPolicyDefinition = 613 (PolicyDefinition<V>) POLICY_DEFINITIONS.get(policyKey.getIdentifier()); 614 if (genericPolicyDefinition == null) { 615 Slogf.wtf(TAG, "Unknown generic policy key: " + policyKey); 616 return null; 617 } 618 return genericPolicyDefinition.createPolicyDefinition(policyKey); 619 } 620 621 @Nullable readPolicyKeyFromXml(TypedXmlPullParser parser)622 static <V> PolicyKey readPolicyKeyFromXml(TypedXmlPullParser parser) 623 throws XmlPullParserException, IOException { 624 // TODO: can we avoid casting? 625 PolicyKey policyKey = PolicyKey.readGenericPolicyKeyFromXml(parser); 626 if (policyKey == null) { 627 Slogf.wtf(TAG, "Error parsing PolicyKey, GenericPolicyKey is null"); 628 return null; 629 } 630 PolicyDefinition<PolicyValue<V>> genericPolicyDefinition = 631 (PolicyDefinition<PolicyValue<V>>) POLICY_DEFINITIONS.get( 632 policyKey.getIdentifier()); 633 if (genericPolicyDefinition == null) { 634 Slogf.wtf(TAG, "Error parsing PolicyKey, Unknown generic policy key: " + policyKey); 635 return null; 636 } 637 return genericPolicyDefinition.mPolicyKey.readFromXml(parser); 638 } 639 savePolicyValueToXml(TypedXmlSerializer serializer, V value)640 void savePolicyValueToXml(TypedXmlSerializer serializer, V value) 641 throws IOException { 642 mPolicySerializer.saveToXml(mPolicyKey, serializer, value); 643 } 644 645 @Nullable readPolicyValueFromXml(TypedXmlPullParser parser)646 PolicyValue<V> readPolicyValueFromXml(TypedXmlPullParser parser) { 647 return mPolicySerializer.readFromXml(parser); 648 } 649 650 @Override toString()651 public String toString() { 652 return "PolicyDefinition{ mPolicyKey= " + mPolicyKey + ", mResolutionMechanism= " 653 + mResolutionMechanism + ", mPolicyFlags= " + mPolicyFlags + " }"; 654 } 655 } 656