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.internal.app;
18 
19 import static android.view.WindowManager.LayoutParams.SYSTEM_FLAG_HIDE_NON_SYSTEM_OVERLAY_WINDOWS;
20 
21 import android.accounts.Account;
22 import android.accounts.AccountManager;
23 import android.content.DialogInterface;
24 import android.content.Intent;
25 import android.content.pm.ApplicationInfo;
26 import android.content.pm.PackageInfo;
27 import android.content.pm.PackageManager.NameNotFoundException;
28 import android.content.pm.UserInfo;
29 import android.os.Bundle;
30 import android.os.PersistableBundle;
31 import android.os.UserHandle;
32 import android.os.UserManager;
33 import android.util.Log;
34 
35 import com.android.internal.R;
36 
37 /**
38  * Activity to confirm with the user that it is ok to create a new user, as requested by
39  * an app. It has to do some checks to decide what kind of prompt the user should be shown.
40  * Particularly, it needs to check if the account requested already exists on another user.
41  */
42 public class ConfirmUserCreationActivity extends AlertActivity
43         implements DialogInterface.OnClickListener {
44 
45     private static final String TAG = "CreateUser";
46 
47     private String mUserName;
48     private String mAccountName;
49     private String mAccountType;
50     private PersistableBundle mAccountOptions;
51     private boolean mCanProceed;
52     private UserManager mUserManager;
53 
54     @Override
onCreate(Bundle icicle)55     public void onCreate(Bundle icicle) {
56         super.onCreate(icicle);
57 
58         getWindow().addSystemFlags(SYSTEM_FLAG_HIDE_NON_SYSTEM_OVERLAY_WINDOWS);
59 
60         Intent intent = getIntent();
61         mUserName = intent.getStringExtra(UserManager.EXTRA_USER_NAME);
62         mAccountName = intent.getStringExtra(UserManager.EXTRA_USER_ACCOUNT_NAME);
63         mAccountType = intent.getStringExtra(UserManager.EXTRA_USER_ACCOUNT_TYPE);
64         mAccountOptions = (PersistableBundle)
65                 intent.getParcelableExtra(UserManager.EXTRA_USER_ACCOUNT_OPTIONS);
66 
67         mUserManager = getSystemService(UserManager.class);
68 
69         String message = checkUserCreationRequirements();
70 
71         if (message == null) {
72             finish();
73             return;
74         }
75         final AlertController.AlertParams ap = mAlertParams;
76         ap.mMessage = message;
77         ap.mPositiveButtonText = getString(android.R.string.ok);
78         ap.mPositiveButtonListener = this;
79 
80         // Show the negative button if the user actually has a choice
81         if (mCanProceed) {
82             ap.mNegativeButtonText = getString(android.R.string.cancel);
83             ap.mNegativeButtonListener = this;
84         }
85         setupAlert();
86     }
87 
checkUserCreationRequirements()88     private String checkUserCreationRequirements() {
89         final String callingPackage = getCallingPackage();
90         if (callingPackage == null) {
91             throw new SecurityException(
92                     "User Creation intent must be launched with startActivityForResult");
93         }
94         final ApplicationInfo appInfo;
95         try {
96             appInfo = getPackageManager().getApplicationInfo(callingPackage, 0);
97         } catch (NameNotFoundException nnfe) {
98             throw new SecurityException(
99                     "Cannot find the calling package");
100         }
101         final String message;
102         // Check the user restrictions
103         boolean cantCreateUser = mUserManager.hasUserRestriction(UserManager.DISALLOW_ADD_USER)
104                 || !mUserManager.isAdminUser();
105         // Check the system state and user count
106         boolean cantCreateAnyMoreUsers = !mUserManager.canAddMoreUsers();
107         // Check the account existence
108         final Account account = new Account(mAccountName, mAccountType);
109         boolean accountExists = mAccountName != null && mAccountType != null
110                 && (AccountManager.get(this).someUserHasAccount(account)
111                     | mUserManager.someUserHasSeedAccount(mAccountName, mAccountType));
112         mCanProceed = true;
113         final String appName = appInfo.loadLabel(getPackageManager()).toString();
114         if (cantCreateUser) {
115             setResult(UserManager.USER_CREATION_FAILED_NOT_PERMITTED);
116             return null;
117         } else if (cantCreateAnyMoreUsers) {
118             setResult(UserManager.USER_CREATION_FAILED_NO_MORE_USERS);
119             return null;
120         } else if (accountExists) {
121             message = getString(R.string.user_creation_account_exists, appName, mAccountName);
122         } else {
123             message = getString(R.string.user_creation_adding, appName, mAccountName);
124         }
125         return message;
126     }
127 
128     @Override
onClick(DialogInterface dialog, int which)129     public void onClick(DialogInterface dialog, int which) {
130         setResult(RESULT_CANCELED);
131         if (which == BUTTON_POSITIVE && mCanProceed) {
132             Log.i(TAG, "Ok, creating user");
133             UserInfo user = mUserManager.createUser(mUserName, 0);
134             if (user == null) {
135                 Log.e(TAG, "Couldn't create user");
136                 finish();
137                 return;
138             }
139             mUserManager.setSeedAccountData(user.id, mAccountName, mAccountType, mAccountOptions);
140             setResult(RESULT_OK);
141         }
142         finish();
143     }
144 }
145