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