1 /* 2 * Copyright (C) 2016 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.tv.settings.system; 18 19 import android.accounts.AccountManager; 20 import android.annotation.SuppressLint; 21 import android.app.ActivityManager; 22 import android.app.Fragment; 23 import android.content.BroadcastReceiver; 24 import android.content.Context; 25 import android.content.Intent; 26 import android.content.IntentFilter; 27 import android.content.pm.PackageManager; 28 import android.content.pm.ResolveInfo; 29 import android.content.pm.UserInfo; 30 import android.graphics.Bitmap; 31 import android.graphics.Canvas; 32 import android.graphics.drawable.Drawable; 33 import android.os.AsyncTask; 34 import android.os.Bundle; 35 import android.os.Handler; 36 import android.os.RemoteException; 37 import android.os.ServiceManager; 38 import android.os.UserHandle; 39 import android.os.UserManager; 40 import android.provider.Settings; 41 import android.support.annotation.DrawableRes; 42 import android.support.annotation.IntDef; 43 import android.support.v17.preference.LeanbackSettingsFragment; 44 import android.support.v4.content.LocalBroadcastManager; 45 import android.support.v7.preference.Preference; 46 import android.support.v7.preference.PreferenceGroup; 47 import android.support.v7.preference.TwoStatePreference; 48 import android.text.TextUtils; 49 import android.util.Log; 50 51 import com.android.internal.logging.nano.MetricsProto; 52 import com.android.internal.widget.ILockSettings; 53 import com.android.internal.widget.LockPatternUtils; 54 import com.android.internal.widget.VerifyCredentialResponse; 55 import com.android.tv.settings.R; 56 import com.android.tv.settings.SettingsPreferenceFragment; 57 import com.android.tv.settings.dialog.PinDialogFragment; 58 import com.android.tv.settings.users.AppRestrictionsFragment; 59 import com.android.tv.settings.users.RestrictedProfilePinDialogFragment; 60 import com.android.tv.settings.users.UserSwitchListenerService; 61 62 import java.lang.annotation.Retention; 63 import java.lang.annotation.RetentionPolicy; 64 import java.util.List; 65 66 /** 67 * The security settings screen in Tv settings. 68 */ 69 public class SecurityFragment extends SettingsPreferenceFragment 70 implements RestrictedProfilePinDialogFragment.Callback { 71 72 private static final String TAG = "SecurityFragment"; 73 74 private static final String KEY_UNKNOWN_SOURCES = "unknown_sources"; 75 private static final String KEY_VERIFY_APPS = "verify_apps"; 76 private static final String KEY_RESTRICTED_PROFILE_GROUP = "restricted_profile_group"; 77 private static final String KEY_RESTRICTED_PROFILE_ENTER = "restricted_profile_enter"; 78 private static final String KEY_RESTRICTED_PROFILE_EXIT = "restricted_profile_exit"; 79 private static final String KEY_RESTRICTED_PROFILE_APPS = "restricted_profile_apps"; 80 private static final String KEY_RESTRICTED_PROFILE_PIN = "restricted_profile_pin"; 81 private static final String KEY_RESTRICTED_PROFILE_CREATE = "restricted_profile_create"; 82 private static final String KEY_RESTRICTED_PROFILE_DELETE = "restricted_profile_delete"; 83 84 private static final String PACKAGE_MIME_TYPE = "application/vnd.android.package-archive"; 85 86 private static final String ACTION_RESTRICTED_PROFILE_CREATED = 87 "SecurityFragment.RESTRICTED_PROFILE_CREATED"; 88 private static final String EXTRA_RESTRICTED_PROFILE_INFO = 89 "SecurityFragment.RESTRICTED_PROFILE_INFO"; 90 private static final String SAVESTATE_CREATING_RESTRICTED_PROFILE = 91 "SecurityFragment.CREATING_RESTRICTED_PROFILE"; 92 93 @Retention(RetentionPolicy.SOURCE) 94 @IntDef({PIN_MODE_CHOOSE_LOCKSCREEN, 95 PIN_MODE_RESTRICTED_PROFILE_SWITCH_OUT, 96 PIN_MODE_RESTRICTED_PROFILE_CHANGE_PASSWORD, 97 PIN_MODE_RESTRICTED_PROFILE_DELETE}) 98 private @interface PinMode {} 99 private static final int PIN_MODE_CHOOSE_LOCKSCREEN = 1; 100 private static final int PIN_MODE_RESTRICTED_PROFILE_SWITCH_OUT = 2; 101 private static final int PIN_MODE_RESTRICTED_PROFILE_CHANGE_PASSWORD = 3; 102 private static final int PIN_MODE_RESTRICTED_PROFILE_DELETE = 4; 103 104 private Preference mUnknownSourcesPref; 105 private TwoStatePreference mVerifyAppsPref; 106 private PreferenceGroup mRestrictedProfileGroup; 107 private Preference mRestrictedProfileEnterPref; 108 private Preference mRestrictedProfileExitPref; 109 private Preference mRestrictedProfileAppsPref; 110 private Preference mRestrictedProfilePinPref; 111 private Preference mRestrictedProfileCreatePref; 112 private Preference mRestrictedProfileDeletePref; 113 114 private UserManager mUserManager; 115 private UserInfo mRestrictedUserInfo; 116 private ILockSettings mLockSettingsService; 117 118 private boolean mCreatingRestrictedProfile; 119 @SuppressLint("StaticFieldLeak") 120 private static CreateRestrictedProfileTask sCreateRestrictedProfileTask; 121 private final BroadcastReceiver mRestrictedProfileReceiver = new BroadcastReceiver() { 122 @Override 123 public void onReceive(Context context, Intent intent) { 124 UserInfo result = intent.getParcelableExtra(EXTRA_RESTRICTED_PROFILE_INFO); 125 if (isResumed()) { 126 onRestrictedUserCreated(result); 127 } 128 } 129 }; 130 131 private final Handler mHandler = new Handler(); 132 133 public static SecurityFragment newInstance() { 134 return new SecurityFragment(); 135 } 136 137 @Override 138 public void onCreate(Bundle savedInstanceState) { 139 mUserManager = (UserManager) getContext().getSystemService(Context.USER_SERVICE); 140 super.onCreate(savedInstanceState); 141 mCreatingRestrictedProfile = savedInstanceState != null 142 && savedInstanceState.getBoolean(SAVESTATE_CREATING_RESTRICTED_PROFILE); 143 } 144 145 @Override 146 public void onResume() { 147 super.onResume(); 148 refresh(); 149 LocalBroadcastManager.getInstance(getActivity()) 150 .registerReceiver(mRestrictedProfileReceiver, 151 new IntentFilter(ACTION_RESTRICTED_PROFILE_CREATED)); 152 if (mCreatingRestrictedProfile) { 153 UserInfo userInfo = findRestrictedUser(mUserManager); 154 if (userInfo != null) { 155 onRestrictedUserCreated(userInfo); 156 } 157 } 158 } 159 160 @Override 161 public void onPause() { 162 super.onPause(); 163 LocalBroadcastManager.getInstance(getActivity()) 164 .unregisterReceiver(mRestrictedProfileReceiver); 165 } 166 167 @Override 168 public void onSaveInstanceState(Bundle outState) { 169 super.onSaveInstanceState(outState); 170 outState.putBoolean(SAVESTATE_CREATING_RESTRICTED_PROFILE, mCreatingRestrictedProfile); 171 } 172 173 @Override 174 public void onCreatePreferences(Bundle savedInstanceState, String rootKey) { 175 setPreferencesFromResource(R.xml.security, null); 176 177 mUnknownSourcesPref = findPreference(KEY_UNKNOWN_SOURCES); 178 mVerifyAppsPref = (TwoStatePreference) findPreference(KEY_VERIFY_APPS); 179 mRestrictedProfileGroup = (PreferenceGroup) findPreference(KEY_RESTRICTED_PROFILE_GROUP); 180 mRestrictedProfileEnterPref = findPreference(KEY_RESTRICTED_PROFILE_ENTER); 181 mRestrictedProfileExitPref = findPreference(KEY_RESTRICTED_PROFILE_EXIT); 182 mRestrictedProfileAppsPref = findPreference(KEY_RESTRICTED_PROFILE_APPS); 183 mRestrictedProfilePinPref = findPreference(KEY_RESTRICTED_PROFILE_PIN); 184 mRestrictedProfileCreatePref = findPreference(KEY_RESTRICTED_PROFILE_CREATE); 185 mRestrictedProfileDeletePref = findPreference(KEY_RESTRICTED_PROFILE_DELETE); 186 } 187 188 private void refresh() { 189 if (isRestrictedProfileInEffect(mUserManager)) { 190 // We are in restricted profile 191 mUnknownSourcesPref.setVisible(false); 192 mVerifyAppsPref.setVisible(false); 193 194 mRestrictedProfileGroup.setVisible(true); 195 mRestrictedProfileEnterPref.setVisible(false); 196 mRestrictedProfileExitPref.setVisible(true); 197 mRestrictedProfileAppsPref.setVisible(false); 198 mRestrictedProfilePinPref.setVisible(false); 199 mRestrictedProfileCreatePref.setVisible(false); 200 mRestrictedProfileDeletePref.setVisible(false); 201 } else if (getRestrictedUser() != null) { 202 // Not in restricted profile, but it exists 203 mUnknownSourcesPref.setVisible(true); 204 mVerifyAppsPref.setVisible(shouldShowVerifierSetting()); 205 206 mRestrictedProfileGroup.setVisible(true); 207 mRestrictedProfileEnterPref.setVisible(true); 208 mRestrictedProfileExitPref.setVisible(false); 209 mRestrictedProfileAppsPref.setVisible(true); 210 mRestrictedProfilePinPref.setVisible(true); 211 mRestrictedProfileCreatePref.setVisible(false); 212 mRestrictedProfileDeletePref.setVisible(true); 213 214 AppRestrictionsFragment.prepareArgs(mRestrictedProfileAppsPref.getExtras(), 215 getRestrictedUser().id, false); 216 } else if (UserManager.supportsMultipleUsers()) { 217 // Not in restricted profile, and it doesn't exist 218 mUnknownSourcesPref.setVisible(true); 219 mVerifyAppsPref.setVisible(shouldShowVerifierSetting()); 220 221 mRestrictedProfileGroup.setVisible(true); 222 mRestrictedProfileEnterPref.setVisible(false); 223 mRestrictedProfileExitPref.setVisible(false); 224 mRestrictedProfileAppsPref.setVisible(false); 225 mRestrictedProfilePinPref.setVisible(false); 226 mRestrictedProfileCreatePref.setVisible(true); 227 mRestrictedProfileDeletePref.setVisible(false); 228 } else { 229 // Not in restricted profile, and can't create one either 230 mUnknownSourcesPref.setVisible(true); 231 mVerifyAppsPref.setVisible(shouldShowVerifierSetting()); 232 233 mRestrictedProfileGroup.setVisible(false); 234 mRestrictedProfileEnterPref.setVisible(false); 235 mRestrictedProfileExitPref.setVisible(false); 236 mRestrictedProfileAppsPref.setVisible(false); 237 mRestrictedProfilePinPref.setVisible(false); 238 mRestrictedProfileCreatePref.setVisible(false); 239 mRestrictedProfileDeletePref.setVisible(false); 240 } 241 242 mRestrictedProfileCreatePref.setEnabled(sCreateRestrictedProfileTask == null); 243 244 mUnknownSourcesPref.setEnabled(!isUnknownSourcesBlocked()); 245 mVerifyAppsPref.setChecked(isVerifyAppsEnabled()); 246 mVerifyAppsPref.setEnabled(isVerifierInstalled()); 247 } 248 249 @Override 250 public boolean onPreferenceTreeClick(Preference preference) { 251 final String key = preference.getKey(); 252 if (TextUtils.isEmpty(key)) { 253 return super.onPreferenceTreeClick(preference); 254 } 255 switch (key) { 256 case KEY_VERIFY_APPS: 257 setVerifyAppsEnabled(mVerifyAppsPref.isChecked()); 258 return true; 259 case KEY_RESTRICTED_PROFILE_ENTER: 260 final UserInfo restrictedUser = getRestrictedUser(); 261 if (restrictedUser == null) { 262 Log.e(TAG, "Tried to enter non-existent restricted user"); 263 return true; 264 } 265 updateBackgroundRestriction(restrictedUser); 266 switchUserNow(restrictedUser.id); 267 getActivity().finish(); 268 return true; 269 case KEY_RESTRICTED_PROFILE_EXIT: 270 launchPinDialog(PIN_MODE_RESTRICTED_PROFILE_SWITCH_OUT); 271 return true; 272 case KEY_RESTRICTED_PROFILE_PIN: 273 launchPinDialog(PIN_MODE_RESTRICTED_PROFILE_CHANGE_PASSWORD); 274 return true; 275 case KEY_RESTRICTED_PROFILE_CREATE: 276 if (hasLockscreenSecurity(new LockPatternUtils(getActivity()))) { 277 addRestrictedUser(); 278 } else { 279 launchPinDialog(PIN_MODE_CHOOSE_LOCKSCREEN); 280 } 281 return true; 282 case KEY_RESTRICTED_PROFILE_DELETE: 283 launchPinDialog(PIN_MODE_RESTRICTED_PROFILE_DELETE); 284 return true; 285 } 286 return super.onPreferenceTreeClick(preference); 287 } 288 289 private void updateBackgroundRestriction(UserInfo user) { 290 final boolean allowedToRun = shouldAllowRunInBackground(); 291 mUserManager.setUserRestriction( 292 UserManager.DISALLOW_RUN_IN_BACKGROUND, !allowedToRun, user.getUserHandle()); 293 } 294 295 /** 296 * Profiles are allowed to run in the background by default, unless the device specifically 297 * sets a config flag and/or has the global setting overridden by something on-device. 298 * 299 * @see Settings.Global#KEEP_PROFILE_IN_BACKGROUND 300 */ 301 private boolean shouldAllowRunInBackground() { 302 final boolean defaultValue = getContext().getResources().getBoolean( 303 com.android.internal.R.bool.config_keepRestrictedProfilesInBackground); 304 return Settings.Global.getInt(getContext().getContentResolver(), 305 Settings.Global.KEEP_PROFILE_IN_BACKGROUND, defaultValue ? 1 : 0) > 0; 306 } 307 308 private boolean isUnknownSourcesBlocked() { 309 final UserManager um = (UserManager) getContext().getSystemService(Context.USER_SERVICE); 310 return um.hasUserRestriction(UserManager.DISALLOW_INSTALL_UNKNOWN_SOURCES); 311 } 312 313 private boolean isVerifyAppsEnabled() { 314 return Settings.Global.getInt(getContext().getContentResolver(), 315 Settings.Global.PACKAGE_VERIFIER_ENABLE, 1) > 0 && isVerifierInstalled(); 316 } 317 318 private void setVerifyAppsEnabled(boolean enable) { 319 Settings.Global.putInt(getContext().getContentResolver(), 320 Settings.Global.PACKAGE_VERIFIER_ENABLE, enable ? 1 : 0); 321 } 322 323 private boolean isVerifierInstalled() { 324 final PackageManager pm = getContext().getPackageManager(); 325 final Intent verification = new Intent(Intent.ACTION_PACKAGE_NEEDS_VERIFICATION); 326 verification.setType(PACKAGE_MIME_TYPE); 327 verification.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION); 328 final List<ResolveInfo> receivers = pm.queryBroadcastReceivers(verification, 0); 329 return receivers.size() > 0; 330 } 331 332 private boolean shouldShowVerifierSetting() { 333 return Settings.Global.getInt(getContext().getContentResolver(), 334 Settings.Global.PACKAGE_VERIFIER_SETTING_VISIBLE, 1) > 0; 335 } 336 337 private void launchPinDialog(@PinMode int pinMode) { 338 @PinDialogFragment.PinDialogType 339 int pinDialogMode; 340 341 switch (pinMode) { 342 case PIN_MODE_CHOOSE_LOCKSCREEN: 343 pinDialogMode = PinDialogFragment.PIN_DIALOG_TYPE_NEW_PIN; 344 break; 345 case PIN_MODE_RESTRICTED_PROFILE_SWITCH_OUT: 346 pinDialogMode = PinDialogFragment.PIN_DIALOG_TYPE_ENTER_PIN; 347 break; 348 case PIN_MODE_RESTRICTED_PROFILE_CHANGE_PASSWORD: 349 pinDialogMode = PinDialogFragment.PIN_DIALOG_TYPE_NEW_PIN; 350 break; 351 case PIN_MODE_RESTRICTED_PROFILE_DELETE: 352 pinDialogMode = PinDialogFragment.PIN_DIALOG_TYPE_DELETE_PIN; 353 break; 354 default: 355 throw new IllegalArgumentException("Unknown pin mode: " + pinMode); 356 } 357 358 RestrictedProfilePinDialogFragment restrictedProfilePinDialogFragment = 359 RestrictedProfilePinDialogFragment.newInstance(pinDialogMode); 360 restrictedProfilePinDialogFragment.setTargetFragment(this, pinMode); 361 restrictedProfilePinDialogFragment.show(getFragmentManager(), 362 PinDialogFragment.DIALOG_TAG); 363 } 364 365 @Override 366 public void saveLockPassword(String pin, String originalPin, int quality) { 367 new LockPatternUtils(getActivity()).saveLockPassword(pin, originalPin, quality, 368 UserHandle.myUserId()); 369 } 370 371 @Override 372 public void clearLockPassword(String oldPin) { 373 new LockPatternUtils(getActivity()).clearLock(oldPin, UserHandle.myUserId()); 374 } 375 376 @Override 377 public boolean checkPassword(String password, int userId) { 378 try { 379 return getLockSettings().checkCredential(password, 380 LockPatternUtils.CREDENTIAL_TYPE_PASSWORD, userId, null /* progressCallback */) 381 .getResponseCode() == VerifyCredentialResponse.RESPONSE_OK; 382 } catch (final RemoteException e) { 383 // ignore 384 } 385 return false; 386 } 387 388 @Override 389 public boolean hasLockscreenSecurity() { 390 return hasLockscreenSecurity(new LockPatternUtils(getActivity())); 391 } 392 393 private ILockSettings getLockSettings() { 394 if (mLockSettingsService == null) { 395 mLockSettingsService = ILockSettings.Stub.asInterface( 396 ServiceManager.getService("lock_settings")); 397 } 398 return mLockSettingsService; 399 } 400 401 private static boolean hasLockscreenSecurity(LockPatternUtils lpu) { 402 return lpu.isLockPasswordEnabled(UserHandle.myUserId()) 403 || lpu.isLockPatternEnabled(UserHandle.myUserId()); 404 } 405 406 @Override 407 public void pinFragmentDone(int requestCode, boolean success) { 408 switch (requestCode) { 409 case PIN_MODE_CHOOSE_LOCKSCREEN: 410 if (success) { 411 addRestrictedUser(); 412 } 413 break; 414 case PIN_MODE_RESTRICTED_PROFILE_SWITCH_OUT: 415 if (success) { 416 UserInfo myUserInfo = 417 UserManager.get(getActivity()).getUserInfo(UserHandle.myUserId()); 418 if (myUserInfo == null || 419 myUserInfo.restrictedProfileParentId == UserInfo.NO_PROFILE_GROUP_ID) { 420 switchUserNow(UserHandle.USER_SYSTEM); 421 } else { 422 switchUserNow(myUserInfo.restrictedProfileParentId); 423 } 424 getActivity().finish(); 425 } 426 break; 427 case PIN_MODE_RESTRICTED_PROFILE_CHANGE_PASSWORD: 428 // do nothing 429 break; 430 case PIN_MODE_RESTRICTED_PROFILE_DELETE: 431 if (success) { 432 removeRestrictedUser(); 433 } 434 break; 435 } 436 } 437 438 public static UserInfo findRestrictedUser(UserManager userManager) { 439 for (UserInfo userInfo : userManager.getUsers()) { 440 if (userInfo.isRestricted()) { 441 return userInfo; 442 } 443 } 444 return null; 445 } 446 447 private UserInfo getRestrictedUser() { 448 if (mRestrictedUserInfo == null) { 449 mRestrictedUserInfo = findRestrictedUser(mUserManager); 450 } 451 return mRestrictedUserInfo; 452 } 453 454 private static void switchUserNow(int userId) { 455 try { 456 ActivityManager.getService().switchUser(userId); 457 } catch (RemoteException re) { 458 Log.e(TAG, "Caught exception while switching user! ", re); 459 } 460 } 461 462 private void addRestrictedUser() { 463 if (sCreateRestrictedProfileTask == null) { 464 sCreateRestrictedProfileTask = new CreateRestrictedProfileTask(getContext(), 465 mUserManager); 466 sCreateRestrictedProfileTask.execute(); 467 mCreatingRestrictedProfile = true; 468 } 469 refresh(); 470 } 471 472 private void removeRestrictedUser() { 473 final UserInfo restrictedUser = getRestrictedUser(); 474 if (restrictedUser == null) { 475 Log.w(TAG, "No restricted user to remove?"); 476 return; 477 } 478 final int restrictedUserHandle = restrictedUser.id; 479 mRestrictedUserInfo = null; 480 mHandler.post(() -> { 481 mUserManager.removeUser(restrictedUserHandle); 482 UserSwitchListenerService.updateLaunchPoint(getActivity(), false); 483 refresh(); 484 }); 485 } 486 487 public static boolean isRestrictedProfileInEffect(Context context) { 488 UserManager userManager = (UserManager) context.getSystemService(Context.USER_SERVICE); 489 UserInfo userInfo = userManager.getUserInfo(UserHandle.myUserId()); 490 return userInfo.isRestricted(); 491 } 492 493 private static boolean isRestrictedProfileInEffect(UserManager userManager) { 494 UserInfo userInfo = userManager.getUserInfo(UserHandle.myUserId()); 495 return userInfo.isRestricted(); 496 } 497 498 private void onRestrictedUserCreated(UserInfo result) { 499 int userId = result.id; 500 if (result.isRestricted() 501 && result.restrictedProfileParentId == UserHandle.myUserId()) { 502 final AppRestrictionsFragment restrictionsFragment = 503 AppRestrictionsFragment.newInstance(userId, true); 504 final Fragment settingsFragment = getCallbackFragment(); 505 if (settingsFragment instanceof LeanbackSettingsFragment) { 506 ((LeanbackSettingsFragment) settingsFragment) 507 .startPreferenceFragment(restrictionsFragment); 508 } else { 509 throw new IllegalStateException("Didn't find fragment of expected type: " 510 + settingsFragment); 511 } 512 } 513 mCreatingRestrictedProfile = false; 514 refresh(); 515 } 516 517 private static class CreateRestrictedProfileTask extends AsyncTask<Void, Void, UserInfo> { 518 private final Context mContext; 519 private final UserManager mUserManager; 520 521 CreateRestrictedProfileTask(Context context, UserManager userManager) { 522 mContext = context.getApplicationContext(); 523 mUserManager = userManager; 524 } 525 526 @Override 527 protected UserInfo doInBackground(Void... params) { 528 UserInfo restrictedUserInfo = mUserManager.createProfileForUser( 529 mContext.getString(R.string.user_new_profile_name), 530 UserInfo.FLAG_RESTRICTED, UserHandle.myUserId()); 531 if (restrictedUserInfo == null) { 532 final UserInfo existingUserInfo = findRestrictedUser(mUserManager); 533 if (existingUserInfo == null) { 534 Log.wtf(TAG, "Got back a null user handle!"); 535 } 536 return existingUserInfo; 537 } 538 int userId = restrictedUserInfo.id; 539 UserHandle user = new UserHandle(userId); 540 mUserManager.setUserRestriction(UserManager.DISALLOW_MODIFY_ACCOUNTS, true, user); 541 Bitmap bitmap = createBitmapFromDrawable(R.drawable.ic_avatar_default); 542 mUserManager.setUserIcon(userId, bitmap); 543 // Add shared accounts 544 AccountManager.get(mContext).addSharedAccountsFromParentUser( 545 UserHandle.of(UserHandle.myUserId()), user); 546 return restrictedUserInfo; 547 } 548 549 @Override 550 protected void onPostExecute(UserInfo result) { 551 sCreateRestrictedProfileTask = null; 552 if (result == null) { 553 return; 554 } 555 UserSwitchListenerService.updateLaunchPoint(mContext, true); 556 LocalBroadcastManager.getInstance(mContext).sendBroadcast( 557 new Intent(ACTION_RESTRICTED_PROFILE_CREATED) 558 .putExtra(EXTRA_RESTRICTED_PROFILE_INFO, result)); 559 } 560 561 private Bitmap createBitmapFromDrawable(@DrawableRes int resId) { 562 Drawable icon = mContext.getDrawable(resId); 563 if (icon == null) { 564 throw new IllegalArgumentException("Drawable is missing!"); 565 } 566 icon.setBounds(0, 0, icon.getIntrinsicWidth(), icon.getIntrinsicHeight()); 567 Bitmap bitmap = Bitmap.createBitmap(icon.getIntrinsicWidth(), icon.getIntrinsicHeight(), 568 Bitmap.Config.ARGB_8888); 569 icon.draw(new Canvas(bitmap)); 570 return bitmap; 571 } 572 } 573 574 @Override 575 public int getMetricsCategory() { 576 return MetricsProto.MetricsEvent.SECURITY; 577 } 578 } 579