• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
newInstance()133     public static SecurityFragment newInstance() {
134         return new SecurityFragment();
135     }
136 
137     @Override
onCreate(Bundle savedInstanceState)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
onResume()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
onPause()161     public void onPause() {
162         super.onPause();
163         LocalBroadcastManager.getInstance(getActivity())
164                 .unregisterReceiver(mRestrictedProfileReceiver);
165     }
166 
167     @Override
onSaveInstanceState(Bundle outState)168     public void onSaveInstanceState(Bundle outState) {
169         super.onSaveInstanceState(outState);
170         outState.putBoolean(SAVESTATE_CREATING_RESTRICTED_PROFILE, mCreatingRestrictedProfile);
171     }
172 
173     @Override
onCreatePreferences(Bundle savedInstanceState, String rootKey)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 
refresh()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
onPreferenceTreeClick(Preference preference)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 
updateBackgroundRestriction(UserInfo user)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      */
shouldAllowRunInBackground()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 
isUnknownSourcesBlocked()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 
isVerifyAppsEnabled()313     private boolean isVerifyAppsEnabled() {
314         return Settings.Global.getInt(getContext().getContentResolver(),
315                 Settings.Global.PACKAGE_VERIFIER_ENABLE, 1) > 0 && isVerifierInstalled();
316     }
317 
setVerifyAppsEnabled(boolean enable)318     private void setVerifyAppsEnabled(boolean enable) {
319         Settings.Global.putInt(getContext().getContentResolver(),
320                 Settings.Global.PACKAGE_VERIFIER_ENABLE, enable ? 1 : 0);
321     }
322 
isVerifierInstalled()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 
shouldShowVerifierSetting()332     private boolean shouldShowVerifierSetting() {
333         return Settings.Global.getInt(getContext().getContentResolver(),
334                 Settings.Global.PACKAGE_VERIFIER_SETTING_VISIBLE, 1) > 0;
335     }
336 
launchPinDialog(@inMode int pinMode)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
saveLockPassword(String pin, String originalPin, int quality)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
clearLockPassword(String oldPin)372     public void clearLockPassword(String oldPin) {
373         new LockPatternUtils(getActivity()).clearLock(oldPin, UserHandle.myUserId());
374     }
375 
376     @Override
checkPassword(String password, int userId)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
hasLockscreenSecurity()389     public boolean hasLockscreenSecurity() {
390         return hasLockscreenSecurity(new LockPatternUtils(getActivity()));
391     }
392 
getLockSettings()393     private ILockSettings getLockSettings() {
394         if (mLockSettingsService == null) {
395             mLockSettingsService = ILockSettings.Stub.asInterface(
396                     ServiceManager.getService("lock_settings"));
397         }
398         return mLockSettingsService;
399     }
400 
hasLockscreenSecurity(LockPatternUtils lpu)401     private static boolean hasLockscreenSecurity(LockPatternUtils lpu) {
402         return lpu.isLockPasswordEnabled(UserHandle.myUserId())
403                 || lpu.isLockPatternEnabled(UserHandle.myUserId());
404     }
405 
406     @Override
pinFragmentDone(int requestCode, boolean success)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 
findRestrictedUser(UserManager userManager)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 
getRestrictedUser()447     private UserInfo getRestrictedUser() {
448         if (mRestrictedUserInfo == null) {
449             mRestrictedUserInfo = findRestrictedUser(mUserManager);
450         }
451         return mRestrictedUserInfo;
452     }
453 
switchUserNow(int userId)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 
addRestrictedUser()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 
removeRestrictedUser()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 
isRestrictedProfileInEffect(Context context)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 
isRestrictedProfileInEffect(UserManager userManager)493     private static boolean isRestrictedProfileInEffect(UserManager userManager) {
494         UserInfo userInfo = userManager.getUserInfo(UserHandle.myUserId());
495         return userInfo.isRestricted();
496     }
497 
onRestrictedUserCreated(UserInfo result)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 
CreateRestrictedProfileTask(Context context, UserManager userManager)521         CreateRestrictedProfileTask(Context context, UserManager userManager) {
522             mContext = context.getApplicationContext();
523             mUserManager = userManager;
524         }
525 
526         @Override
doInBackground(Void... params)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
onPostExecute(UserInfo result)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 
createBitmapFromDrawable(@rawableRes int resId)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
getMetricsCategory()575     public int getMetricsCategory() {
576         return MetricsProto.MetricsEvent.SECURITY;
577     }
578 }
579