1/*
2 * Copyright (C) 2014 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.settings.users;
18
19import android.app.Dialog;
20import android.content.Context;
21import android.content.DialogInterface;
22import android.content.pm.UserInfo;
23import android.os.Bundle;
24import android.os.UserHandle;
25import android.os.UserManager;
26import android.support.v14.preference.SwitchPreference;
27import android.support.v7.preference.Preference;
28
29import com.android.internal.logging.nano.MetricsProto;
30import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
31import com.android.settings.R;
32import com.android.settings.SettingsPreferenceFragment;
33import com.android.settingslib.RestrictedLockUtils;
34
35import java.util.List;
36
37/**
38 * Settings screen for configuring a specific user. It can contain user restrictions
39 * and deletion controls. It is shown when you tap on the settings icon in the
40 * user management (UserSettings) screen.
41 *
42 * Arguments to this fragment must include the userId of the user (in EXTRA_USER_ID) for whom
43 * to display controls, or should contain the EXTRA_USER_GUEST = true.
44 */
45public class UserDetailsSettings extends SettingsPreferenceFragment
46        implements Preference.OnPreferenceClickListener, Preference.OnPreferenceChangeListener {
47
48    private static final String TAG = UserDetailsSettings.class.getSimpleName();
49
50    private static final String KEY_ENABLE_TELEPHONY = "enable_calling";
51    private static final String KEY_REMOVE_USER = "remove_user";
52
53    /** Integer extra containing the userId to manage */
54    static final String EXTRA_USER_ID = "user_id";
55    /** Boolean extra to indicate guest preferences */
56    static final String EXTRA_USER_GUEST = "guest_user";
57
58    private static final int DIALOG_CONFIRM_REMOVE = 1;
59    private static final int DIALOG_CONFIRM_ENABLE_CALLING = 2;
60    private static final int DIALOG_CONFIRM_ENABLE_CALLING_AND_SMS = 3;
61
62    private UserManager mUserManager;
63    private SwitchPreference mPhonePref;
64    private Preference mRemoveUserPref;
65
66    private UserInfo mUserInfo;
67    private boolean mGuestUser;
68    private Bundle mDefaultGuestRestrictions;
69
70    @Override
71    public int getMetricsCategory() {
72        return MetricsEvent.USER_DETAILS;
73    }
74
75    @Override
76    public void onCreate(Bundle icicle) {
77        super.onCreate(icicle);
78
79        final Context context = getActivity();
80        mUserManager = (UserManager) context.getSystemService(Context.USER_SERVICE);
81
82        addPreferencesFromResource(R.xml.user_details_settings);
83        mPhonePref = (SwitchPreference) findPreference(KEY_ENABLE_TELEPHONY);
84        mRemoveUserPref = findPreference(KEY_REMOVE_USER);
85
86        mGuestUser = getArguments().getBoolean(EXTRA_USER_GUEST, false);
87
88        if (!mGuestUser) {
89            // Regular user. Get the user id from the caller.
90            final int userId = getArguments().getInt(EXTRA_USER_ID, -1);
91            if (userId == -1) {
92                throw new RuntimeException("Arguments to this fragment must contain the user id");
93            }
94            mUserInfo = mUserManager.getUserInfo(userId);
95            mPhonePref.setChecked(!mUserManager.hasUserRestriction(
96                    UserManager.DISALLOW_OUTGOING_CALLS, new UserHandle(userId)));
97            mRemoveUserPref.setOnPreferenceClickListener(this);
98        } else {
99            // These are not for an existing user, just general Guest settings.
100            removePreference(KEY_REMOVE_USER);
101            // Default title is for calling and SMS. Change to calling-only here
102            mPhonePref.setTitle(R.string.user_enable_calling);
103            mDefaultGuestRestrictions = mUserManager.getDefaultGuestRestrictions();
104            mPhonePref.setChecked(
105                    !mDefaultGuestRestrictions.getBoolean(UserManager.DISALLOW_OUTGOING_CALLS));
106        }
107        if (RestrictedLockUtils.hasBaseUserRestriction(context,
108                UserManager.DISALLOW_REMOVE_USER, UserHandle.myUserId())) {
109            removePreference(KEY_REMOVE_USER);
110        }
111        mPhonePref.setOnPreferenceChangeListener(this);
112    }
113
114    @Override
115    public boolean onPreferenceClick(Preference preference) {
116        if (preference == mRemoveUserPref) {
117            if (!mUserManager.isAdminUser()) {
118                throw new RuntimeException("Only admins can remove a user");
119            }
120            showDialog(DIALOG_CONFIRM_REMOVE);
121            return true;
122        }
123        return false;
124    }
125
126    @Override
127    public boolean onPreferenceChange(Preference preference, Object newValue) {
128        if (Boolean.TRUE.equals(newValue)) {
129            showDialog(mGuestUser ? DIALOG_CONFIRM_ENABLE_CALLING
130                    : DIALOG_CONFIRM_ENABLE_CALLING_AND_SMS);
131            return false;
132        }
133        enableCallsAndSms(false);
134        return true;
135    }
136
137    void enableCallsAndSms(boolean enabled) {
138        mPhonePref.setChecked(enabled);
139        if (mGuestUser) {
140            mDefaultGuestRestrictions.putBoolean(UserManager.DISALLOW_OUTGOING_CALLS, !enabled);
141            // SMS is always disabled for guest
142            mDefaultGuestRestrictions.putBoolean(UserManager.DISALLOW_SMS, true);
143            mUserManager.setDefaultGuestRestrictions(mDefaultGuestRestrictions);
144
145            // Update the guest's restrictions, if there is a guest
146            // TODO: Maybe setDefaultGuestRestrictions() can internally just set the restrictions
147            // on any existing guest rather than do it here with multiple Binder calls.
148            List<UserInfo> users = mUserManager.getUsers(true);
149            for (UserInfo user: users) {
150                if (user.isGuest()) {
151                    UserHandle userHandle = UserHandle.of(user.id);
152                    for (String key : mDefaultGuestRestrictions.keySet()) {
153                        mUserManager.setUserRestriction(
154                                key, mDefaultGuestRestrictions.getBoolean(key), userHandle);
155                    }
156                }
157            }
158        } else {
159            UserHandle userHandle = UserHandle.of(mUserInfo.id);
160            mUserManager.setUserRestriction(UserManager.DISALLOW_OUTGOING_CALLS, !enabled,
161                    userHandle);
162            mUserManager.setUserRestriction(UserManager.DISALLOW_SMS, !enabled, userHandle);
163        }
164    }
165
166    @Override
167    public Dialog onCreateDialog(int dialogId) {
168        Context context = getActivity();
169        if (context == null) return null;
170        switch (dialogId) {
171            case DIALOG_CONFIRM_REMOVE:
172                return UserDialogs.createRemoveDialog(getActivity(), mUserInfo.id,
173                        new DialogInterface.OnClickListener() {
174                            public void onClick(DialogInterface dialog, int which) {
175                                removeUser();
176                            }
177                        });
178            case DIALOG_CONFIRM_ENABLE_CALLING:
179                return UserDialogs.createEnablePhoneCallsDialog(getActivity(),
180                        new DialogInterface.OnClickListener() {
181                            public void onClick(DialogInterface dialog, int which) {
182                                enableCallsAndSms(true);
183                            }
184                        });
185            case DIALOG_CONFIRM_ENABLE_CALLING_AND_SMS:
186                return UserDialogs.createEnablePhoneCallsAndSmsDialog(getActivity(),
187                        new DialogInterface.OnClickListener() {
188                            public void onClick(DialogInterface dialog, int which) {
189                                enableCallsAndSms(true);
190                            }
191                        });
192        }
193        throw new IllegalArgumentException("Unsupported dialogId " + dialogId);
194    }
195
196    @Override
197    public int getDialogMetricsCategory(int dialogId) {
198        switch (dialogId) {
199            case DIALOG_CONFIRM_REMOVE:
200                return MetricsProto.MetricsEvent.DIALOG_USER_REMOVE;
201            case DIALOG_CONFIRM_ENABLE_CALLING:
202                return MetricsProto.MetricsEvent.DIALOG_USER_ENABLE_CALLING;
203            case DIALOG_CONFIRM_ENABLE_CALLING_AND_SMS:
204                return MetricsProto.MetricsEvent.DIALOG_USER_ENABLE_CALLING_AND_SMS;
205            default:
206                return 0;
207        }
208    }
209
210    void removeUser() {
211        mUserManager.removeUser(mUserInfo.id);
212        finishFragment();
213    }
214}
215