Doris Ling | bfac31b | 2016-11-10 15:12:52 -0800 | [diff] [blame] | 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.settings.accounts; |
| 18 | |
Tony Mantler | 1c9e2f6 | 2017-06-13 15:16:50 -0700 | [diff] [blame] | 19 | import static android.content.Intent.EXTRA_USER; |
| 20 | import static android.os.UserManager.DISALLOW_MODIFY_ACCOUNTS; |
| 21 | import static android.os.UserManager.DISALLOW_REMOVE_MANAGED_PROFILE; |
| 22 | import static android.provider.Settings.ACTION_ADD_ACCOUNT; |
| 23 | import static android.provider.Settings.EXTRA_AUTHORITIES; |
| 24 | |
Doris Ling | bfac31b | 2016-11-10 15:12:52 -0800 | [diff] [blame] | 25 | import android.accounts.Account; |
| 26 | import android.accounts.AccountManager; |
| 27 | import android.content.BroadcastReceiver; |
| 28 | import android.content.Context; |
| 29 | import android.content.Intent; |
| 30 | import android.content.IntentFilter; |
| 31 | import android.content.pm.ApplicationInfo; |
| 32 | import android.content.pm.PackageManager; |
| 33 | import android.content.pm.UserInfo; |
| 34 | import android.content.res.Resources; |
Doris Ling | 20d4b04 | 2016-11-22 16:37:06 -0800 | [diff] [blame] | 35 | import android.graphics.drawable.Drawable; |
Doris Ling | bfac31b | 2016-11-10 15:12:52 -0800 | [diff] [blame] | 36 | import android.os.Bundle; |
| 37 | import android.os.UserHandle; |
| 38 | import android.os.UserManager; |
Doris Ling | bfac31b | 2016-11-10 15:12:52 -0800 | [diff] [blame] | 39 | import android.support.v7.preference.Preference; |
| 40 | import android.support.v7.preference.Preference.OnPreferenceClickListener; |
| 41 | import android.support.v7.preference.PreferenceGroup; |
| 42 | import android.support.v7.preference.PreferenceScreen; |
Doris Ling | 633250b | 2017-05-02 11:28:14 -0700 | [diff] [blame] | 43 | import android.util.ArrayMap; |
Doris Ling | bfac31b | 2016-11-10 15:12:52 -0800 | [diff] [blame] | 44 | import android.util.Log; |
| 45 | import android.util.SparseArray; |
| 46 | |
| 47 | import com.android.internal.annotations.VisibleForTesting; |
| 48 | import com.android.settings.AccessiblePreferenceCategory; |
Doris Ling | bfac31b | 2016-11-10 15:12:52 -0800 | [diff] [blame] | 49 | import com.android.settings.R; |
Doris Ling | f074f0f | 2017-02-24 15:20:05 -0800 | [diff] [blame] | 50 | import com.android.settings.SettingsPreferenceFragment; |
Doris Ling | bfac31b | 2016-11-10 15:12:52 -0800 | [diff] [blame] | 51 | import com.android.settings.Utils; |
Tony Mantler | 1d583e1 | 2017-06-13 13:09:25 -0700 | [diff] [blame] | 52 | import com.android.settings.core.PreferenceControllerMixin; |
Fan Zhang | 7cf99f5 | 2018-02-16 10:37:37 -0800 | [diff] [blame] | 53 | import com.android.settings.core.SubSettingLauncher; |
Doris Ling | bfac31b | 2016-11-10 15:12:52 -0800 | [diff] [blame] | 54 | import com.android.settings.overlay.FeatureFactory; |
Tony Mantler | 1c9e2f6 | 2017-06-13 15:16:50 -0700 | [diff] [blame] | 55 | import com.android.settings.search.SearchIndexableRaw; |
Doris Ling | bfac31b | 2016-11-10 15:12:52 -0800 | [diff] [blame] | 56 | import com.android.settingslib.RestrictedPreference; |
| 57 | import com.android.settingslib.accounts.AuthenticatorHelper; |
Tony Mantler | 1d583e1 | 2017-06-13 13:09:25 -0700 | [diff] [blame] | 58 | import com.android.settingslib.core.AbstractPreferenceController; |
Leif Hendrik Wilden | 28dee1f | 2018-01-11 10:15:36 -0800 | [diff] [blame] | 59 | import com.android.settingslib.core.instrumentation.MetricsFeatureProvider; |
Juan Lang | 777ed25 | 2017-05-09 15:42:36 -0700 | [diff] [blame] | 60 | import com.android.settingslib.core.lifecycle.LifecycleObserver; |
| 61 | import com.android.settingslib.core.lifecycle.events.OnPause; |
| 62 | import com.android.settingslib.core.lifecycle.events.OnResume; |
Doris Ling | bfac31b | 2016-11-10 15:12:52 -0800 | [diff] [blame] | 63 | |
| 64 | import java.util.ArrayList; |
| 65 | import java.util.Collections; |
| 66 | import java.util.Comparator; |
| 67 | import java.util.List; |
| 68 | |
Tony Mantler | 1d583e1 | 2017-06-13 13:09:25 -0700 | [diff] [blame] | 69 | public class AccountPreferenceController extends AbstractPreferenceController |
| 70 | implements PreferenceControllerMixin, AuthenticatorHelper.OnAccountsUpdateListener, |
Doris Ling | bfac31b | 2016-11-10 15:12:52 -0800 | [diff] [blame] | 71 | OnPreferenceClickListener, LifecycleObserver, OnPause, OnResume { |
| 72 | |
| 73 | private static final String TAG = "AccountPrefController"; |
Doris Ling | bfac31b | 2016-11-10 15:12:52 -0800 | [diff] [blame] | 74 | |
| 75 | private static final int ORDER_ACCOUNT_PROFILES = 1; |
| 76 | private static final int ORDER_LAST = 1002; |
| 77 | private static final int ORDER_NEXT_TO_LAST = 1001; |
| 78 | private static final int ORDER_NEXT_TO_NEXT_TO_LAST = 1000; |
| 79 | |
| 80 | private UserManager mUm; |
| 81 | private SparseArray<ProfileData> mProfiles = new SparseArray<ProfileData>(); |
| 82 | private ManagedProfileBroadcastReceiver mManagedProfileBroadcastReceiver |
| 83 | = new ManagedProfileBroadcastReceiver(); |
| 84 | private Preference mProfileNotAvailablePreference; |
| 85 | private String[] mAuthorities; |
| 86 | private int mAuthoritiesCount = 0; |
Doris Ling | f074f0f | 2017-02-24 15:20:05 -0800 | [diff] [blame] | 87 | private SettingsPreferenceFragment mParent; |
Doris Ling | bfac31b | 2016-11-10 15:12:52 -0800 | [diff] [blame] | 88 | private int mAccountProfileOrder = ORDER_ACCOUNT_PROFILES; |
| 89 | private AccountRestrictionHelper mHelper; |
Fan Zhang | c6ca314 | 2017-02-14 15:02:35 -0800 | [diff] [blame] | 90 | private MetricsFeatureProvider mMetricsFeatureProvider; |
Doris Ling | bfac31b | 2016-11-10 15:12:52 -0800 | [diff] [blame] | 91 | |
| 92 | /** |
| 93 | * Holds data related to the accounts belonging to one profile. |
| 94 | */ |
| 95 | public static class ProfileData { |
| 96 | /** |
| 97 | * The preference that displays the accounts. |
| 98 | */ |
| 99 | public PreferenceGroup preferenceGroup; |
| 100 | /** |
| 101 | * The preference that displays the add account button. |
| 102 | */ |
Fan Zhang | 12b03b2 | 2017-10-29 13:57:29 -0700 | [diff] [blame] | 103 | public RestrictedPreference addAccountPreference; |
Doris Ling | bfac31b | 2016-11-10 15:12:52 -0800 | [diff] [blame] | 104 | /** |
| 105 | * The preference that displays the button to remove the managed profile |
| 106 | */ |
| 107 | public RestrictedPreference removeWorkProfilePreference; |
| 108 | /** |
| 109 | * The preference that displays managed profile settings. |
| 110 | */ |
| 111 | public Preference managedProfilePreference; |
| 112 | /** |
| 113 | * The {@link AuthenticatorHelper} that holds accounts data for this profile. |
| 114 | */ |
| 115 | public AuthenticatorHelper authenticatorHelper; |
| 116 | /** |
| 117 | * The {@link UserInfo} of the profile. |
| 118 | */ |
| 119 | public UserInfo userInfo; |
Doris Ling | 633250b | 2017-05-02 11:28:14 -0700 | [diff] [blame] | 120 | /** |
| 121 | * The {@link UserInfo} of the profile. |
| 122 | */ |
| 123 | public boolean pendingRemoval; |
| 124 | /** |
Fan Zhang | c754f59 | 2017-05-17 12:32:59 -0700 | [diff] [blame] | 125 | * The map from account key to account preference |
Doris Ling | 633250b | 2017-05-02 11:28:14 -0700 | [diff] [blame] | 126 | */ |
Fan Zhang | c754f59 | 2017-05-17 12:32:59 -0700 | [diff] [blame] | 127 | public ArrayMap<String, AccountTypePreference> accountPreferences = new ArrayMap<>(); |
Doris Ling | bfac31b | 2016-11-10 15:12:52 -0800 | [diff] [blame] | 128 | } |
| 129 | |
Doris Ling | f074f0f | 2017-02-24 15:20:05 -0800 | [diff] [blame] | 130 | public AccountPreferenceController(Context context, SettingsPreferenceFragment parent, |
Doris Ling | bfac31b | 2016-11-10 15:12:52 -0800 | [diff] [blame] | 131 | String[] authorities) { |
| 132 | this(context, parent, authorities, new AccountRestrictionHelper(context)); |
| 133 | } |
| 134 | |
| 135 | @VisibleForTesting |
Doris Ling | f074f0f | 2017-02-24 15:20:05 -0800 | [diff] [blame] | 136 | AccountPreferenceController(Context context, SettingsPreferenceFragment parent, |
Doris Ling | bfac31b | 2016-11-10 15:12:52 -0800 | [diff] [blame] | 137 | String[] authorities, AccountRestrictionHelper helper) { |
| 138 | super(context); |
| 139 | mUm = (UserManager) context.getSystemService(Context.USER_SERVICE); |
| 140 | mAuthorities = authorities; |
| 141 | mParent = parent; |
| 142 | if (mAuthorities != null) { |
| 143 | mAuthoritiesCount = mAuthorities.length; |
| 144 | } |
Fan Zhang | c6ca314 | 2017-02-14 15:02:35 -0800 | [diff] [blame] | 145 | final FeatureFactory featureFactory = FeatureFactory.getFactory(mContext); |
Fan Zhang | c6ca314 | 2017-02-14 15:02:35 -0800 | [diff] [blame] | 146 | mMetricsFeatureProvider = featureFactory.getMetricsFeatureProvider(); |
Doris Ling | bfac31b | 2016-11-10 15:12:52 -0800 | [diff] [blame] | 147 | mHelper = helper; |
| 148 | } |
| 149 | |
| 150 | @Override |
| 151 | public boolean isAvailable() { |
| 152 | return !mUm.isManagedProfile(); |
| 153 | } |
| 154 | |
| 155 | @Override |
Doris Ling | bfac31b | 2016-11-10 15:12:52 -0800 | [diff] [blame] | 156 | public String getPreferenceKey() { |
| 157 | return null; |
| 158 | } |
| 159 | |
| 160 | @Override |
Doris Ling | 633250b | 2017-05-02 11:28:14 -0700 | [diff] [blame] | 161 | public void displayPreference(PreferenceScreen screen) { |
| 162 | super.displayPreference(screen); |
| 163 | updateUi(); |
| 164 | } |
| 165 | |
| 166 | @Override |
Doris Ling | bfac31b | 2016-11-10 15:12:52 -0800 | [diff] [blame] | 167 | public void updateRawDataToIndex(List<SearchIndexableRaw> rawData) { |
| 168 | if (!isAvailable()) { |
| 169 | return; |
| 170 | } |
| 171 | final Resources res = mContext.getResources(); |
| 172 | final String screenTitle = res.getString(R.string.account_settings_title); |
| 173 | |
| 174 | List<UserInfo> profiles = mUm.getProfiles(UserHandle.myUserId()); |
| 175 | final int profilesCount = profiles.size(); |
| 176 | for (int i = 0; i < profilesCount; i++) { |
| 177 | UserInfo userInfo = profiles.get(i); |
| 178 | if (userInfo.isEnabled()) { |
| 179 | if (!mHelper.hasBaseUserRestriction(DISALLOW_MODIFY_ACCOUNTS, userInfo.id)) { |
| 180 | SearchIndexableRaw data = new SearchIndexableRaw(mContext); |
| 181 | data.title = res.getString(R.string.add_account_label); |
| 182 | data.screenTitle = screenTitle; |
| 183 | rawData.add(data); |
| 184 | } |
| 185 | if (userInfo.isManagedProfile()) { |
Esteban Talavera | 50e515e | 2016-11-30 22:14:00 +0000 | [diff] [blame] | 186 | if (!mHelper.hasBaseUserRestriction(DISALLOW_REMOVE_MANAGED_PROFILE, |
Doris Ling | bfac31b | 2016-11-10 15:12:52 -0800 | [diff] [blame] | 187 | UserHandle.myUserId())) { |
| 188 | SearchIndexableRaw data = new SearchIndexableRaw(mContext); |
| 189 | data.title = res.getString(R.string.remove_managed_profile_label); |
| 190 | data.screenTitle = screenTitle; |
| 191 | rawData.add(data); |
| 192 | } |
| 193 | { |
| 194 | SearchIndexableRaw data = new SearchIndexableRaw(mContext); |
| 195 | data.title = res.getString(R.string.managed_profile_settings_title); |
| 196 | data.screenTitle = screenTitle; |
| 197 | rawData.add(data); |
| 198 | } |
| 199 | } |
| 200 | } |
| 201 | } |
| 202 | } |
| 203 | |
| 204 | @Override |
| 205 | public void onResume() { |
Doris Ling | bfac31b | 2016-11-10 15:12:52 -0800 | [diff] [blame] | 206 | updateUi(); |
| 207 | mManagedProfileBroadcastReceiver.register(mContext); |
| 208 | listenToAccountUpdates(); |
| 209 | } |
| 210 | |
| 211 | @Override |
| 212 | public void onPause() { |
| 213 | stopListeningToAccountUpdates(); |
| 214 | mManagedProfileBroadcastReceiver.unregister(mContext); |
| 215 | } |
| 216 | |
| 217 | @Override |
| 218 | public void onAccountsUpdate(UserHandle userHandle) { |
| 219 | final ProfileData profileData = mProfiles.get(userHandle.getIdentifier()); |
| 220 | if (profileData != null) { |
| 221 | updateAccountTypes(profileData); |
| 222 | } else { |
| 223 | Log.w(TAG, "Missing Settings screen for: " + userHandle.getIdentifier()); |
| 224 | } |
| 225 | } |
| 226 | |
| 227 | @Override |
| 228 | public boolean onPreferenceClick(Preference preference) { |
| 229 | // Check the preference |
| 230 | final int count = mProfiles.size(); |
| 231 | for (int i = 0; i < count; i++) { |
| 232 | ProfileData profileData = mProfiles.valueAt(i); |
| 233 | if (preference == profileData.addAccountPreference) { |
Tony Mantler | 1c9e2f6 | 2017-06-13 15:16:50 -0700 | [diff] [blame] | 234 | Intent intent = new Intent(ACTION_ADD_ACCOUNT); |
Doris Ling | bfac31b | 2016-11-10 15:12:52 -0800 | [diff] [blame] | 235 | intent.putExtra(EXTRA_USER, profileData.userInfo.getUserHandle()); |
| 236 | intent.putExtra(EXTRA_AUTHORITIES, mAuthorities); |
| 237 | mContext.startActivity(intent); |
| 238 | return true; |
| 239 | } |
| 240 | if (preference == profileData.removeWorkProfilePreference) { |
| 241 | final int userId = profileData.userInfo.id; |
| 242 | RemoveUserFragment.newInstance(userId).show(mParent.getFragmentManager(), |
| 243 | "removeUser"); |
| 244 | return true; |
| 245 | } |
| 246 | if (preference == profileData.managedProfilePreference) { |
| 247 | Bundle arguments = new Bundle(); |
| 248 | arguments.putParcelable(Intent.EXTRA_USER, profileData.userInfo.getUserHandle()); |
Fan Zhang | 7cf99f5 | 2018-02-16 10:37:37 -0800 | [diff] [blame] | 249 | new SubSettingLauncher(mContext) |
| 250 | .setSourceMetricsCategory(mParent.getMetricsCategory()) |
| 251 | .setDestination(ManagedProfileSettings.class.getName()) |
| 252 | .setTitle(R.string.managed_profile_settings_title) |
| 253 | .setArguments(arguments) |
| 254 | .launch(); |
| 255 | |
Doris Ling | bfac31b | 2016-11-10 15:12:52 -0800 | [diff] [blame] | 256 | return true; |
| 257 | } |
| 258 | } |
| 259 | return false; |
| 260 | } |
| 261 | |
Doris Ling | bfac31b | 2016-11-10 15:12:52 -0800 | [diff] [blame] | 262 | private void updateUi() { |
Doris Ling | bfac31b | 2016-11-10 15:12:52 -0800 | [diff] [blame] | 263 | if (!isAvailable()) { |
| 264 | // This should not happen |
| 265 | Log.e(TAG, "We should not be showing settings for a managed profile"); |
Doris Ling | bfac31b | 2016-11-10 15:12:52 -0800 | [diff] [blame] | 266 | return; |
| 267 | } |
| 268 | |
Doris Ling | 633250b | 2017-05-02 11:28:14 -0700 | [diff] [blame] | 269 | for (int i = 0, size = mProfiles.size(); i < size; i++) { |
| 270 | mProfiles.valueAt(i).pendingRemoval = true; |
| 271 | } |
James Lemieux | 22a39c2 | 2018-02-26 00:51:42 -0800 | [diff] [blame^] | 272 | if (mUm.isRestrictedProfile()) { |
Doris Ling | bfac31b | 2016-11-10 15:12:52 -0800 | [diff] [blame] | 273 | // Restricted user or similar |
| 274 | UserInfo userInfo = mUm.getUserInfo(UserHandle.myUserId()); |
| 275 | updateProfileUi(userInfo); |
| 276 | } else { |
| 277 | List<UserInfo> profiles = mUm.getProfiles(UserHandle.myUserId()); |
| 278 | final int profilesCount = profiles.size(); |
Doris Ling | bfac31b | 2016-11-10 15:12:52 -0800 | [diff] [blame] | 279 | for (int i = 0; i < profilesCount; i++) { |
| 280 | updateProfileUi(profiles.get(i)); |
| 281 | } |
| 282 | } |
Doris Ling | 633250b | 2017-05-02 11:28:14 -0700 | [diff] [blame] | 283 | cleanUpPreferences(); |
Doris Ling | bfac31b | 2016-11-10 15:12:52 -0800 | [diff] [blame] | 284 | |
| 285 | // Add all preferences, starting with one for the primary profile. |
| 286 | // Note that we're relying on the ordering given by the SparseArray keys, and on the |
| 287 | // value of UserHandle.USER_OWNER being smaller than all the rest. |
| 288 | final int profilesCount = mProfiles.size(); |
| 289 | for (int i = 0; i < profilesCount; i++) { |
| 290 | updateAccountTypes(mProfiles.valueAt(i)); |
| 291 | } |
| 292 | } |
| 293 | |
| 294 | private void updateProfileUi(final UserInfo userInfo) { |
Fan Zhang | 81a030f | 2017-01-11 10:46:45 -0800 | [diff] [blame] | 295 | if (mParent.getPreferenceManager() == null) { |
| 296 | return; |
| 297 | } |
Doris Ling | 633250b | 2017-05-02 11:28:14 -0700 | [diff] [blame] | 298 | final ProfileData data = mProfiles.get(userInfo.id); |
| 299 | if (data != null) { |
| 300 | data.pendingRemoval = false; |
Doris Ling | 7109067 | 2017-05-16 17:23:55 -0700 | [diff] [blame] | 301 | if (userInfo.isEnabled()) { |
| 302 | // recreate the authentication helper to refresh the list of enabled accounts |
| 303 | data.authenticatorHelper = |
| 304 | new AuthenticatorHelper(mContext, userInfo.getUserHandle(), this); |
| 305 | } |
Doris Ling | 633250b | 2017-05-02 11:28:14 -0700 | [diff] [blame] | 306 | return; |
| 307 | } |
Doris Ling | bfac31b | 2016-11-10 15:12:52 -0800 | [diff] [blame] | 308 | final Context context = mContext; |
| 309 | final ProfileData profileData = new ProfileData(); |
| 310 | profileData.userInfo = userInfo; |
| 311 | AccessiblePreferenceCategory preferenceGroup = |
| 312 | mHelper.createAccessiblePreferenceCategory(mParent.getPreferenceManager().getContext()); |
| 313 | preferenceGroup.setOrder(mAccountProfileOrder++); |
| 314 | if (isSingleProfile()) { |
Doris Ling | 829d3aa | 2017-02-03 15:06:56 -0800 | [diff] [blame] | 315 | preferenceGroup.setTitle(context.getString(R.string.account_for_section_header, |
| 316 | userInfo.name)); |
Doris Ling | bfac31b | 2016-11-10 15:12:52 -0800 | [diff] [blame] | 317 | preferenceGroup.setContentDescription( |
| 318 | mContext.getString(R.string.account_settings)); |
| 319 | } else if (userInfo.isManagedProfile()) { |
Doris Ling | bfac31b | 2016-11-10 15:12:52 -0800 | [diff] [blame] | 320 | preferenceGroup.setTitle(R.string.category_work); |
| 321 | String workGroupSummary = getWorkGroupSummary(context, userInfo); |
| 322 | preferenceGroup.setSummary(workGroupSummary); |
| 323 | preferenceGroup.setContentDescription( |
| 324 | mContext.getString(R.string.accessibility_category_work, workGroupSummary)); |
Fan Zhang | 12b03b2 | 2017-10-29 13:57:29 -0700 | [diff] [blame] | 325 | profileData.removeWorkProfilePreference = newRemoveWorkProfilePreference(); |
Doris Ling | bfac31b | 2016-11-10 15:12:52 -0800 | [diff] [blame] | 326 | mHelper.enforceRestrictionOnPreference(profileData.removeWorkProfilePreference, |
Esteban Talavera | 50e515e | 2016-11-30 22:14:00 +0000 | [diff] [blame] | 327 | DISALLOW_REMOVE_MANAGED_PROFILE, UserHandle.myUserId()); |
Doris Ling | bfac31b | 2016-11-10 15:12:52 -0800 | [diff] [blame] | 328 | profileData.managedProfilePreference = newManagedProfileSettings(); |
| 329 | } else { |
| 330 | preferenceGroup.setTitle(R.string.category_personal); |
| 331 | preferenceGroup.setContentDescription( |
| 332 | mContext.getString(R.string.accessibility_category_personal)); |
| 333 | } |
Fan Zhang | 424443b | 2017-01-10 11:50:01 -0800 | [diff] [blame] | 334 | final PreferenceScreen screen = mParent.getPreferenceScreen(); |
| 335 | if (screen != null) { |
| 336 | screen.addPreference(preferenceGroup); |
| 337 | } |
Doris Ling | bfac31b | 2016-11-10 15:12:52 -0800 | [diff] [blame] | 338 | profileData.preferenceGroup = preferenceGroup; |
| 339 | if (userInfo.isEnabled()) { |
| 340 | profileData.authenticatorHelper = new AuthenticatorHelper(context, |
| 341 | userInfo.getUserHandle(), this); |
Fan Zhang | 12b03b2 | 2017-10-29 13:57:29 -0700 | [diff] [blame] | 342 | profileData.addAccountPreference = newAddAccountPreference(); |
Doris Ling | bfac31b | 2016-11-10 15:12:52 -0800 | [diff] [blame] | 343 | mHelper.enforceRestrictionOnPreference(profileData.addAccountPreference, |
| 344 | DISALLOW_MODIFY_ACCOUNTS, userInfo.id); |
| 345 | } |
| 346 | mProfiles.put(userInfo.id, profileData); |
Doris Ling | bfac31b | 2016-11-10 15:12:52 -0800 | [diff] [blame] | 347 | } |
| 348 | |
Fan Zhang | 12b03b2 | 2017-10-29 13:57:29 -0700 | [diff] [blame] | 349 | private RestrictedPreference newAddAccountPreference() { |
| 350 | RestrictedPreference preference = |
| 351 | new RestrictedPreference(mParent.getPreferenceManager().getContext()); |
Doris Ling | bfac31b | 2016-11-10 15:12:52 -0800 | [diff] [blame] | 352 | preference.setTitle(R.string.add_account_label); |
| 353 | preference.setIcon(R.drawable.ic_menu_add); |
| 354 | preference.setOnPreferenceClickListener(this); |
| 355 | preference.setOrder(ORDER_NEXT_TO_NEXT_TO_LAST); |
| 356 | return preference; |
| 357 | } |
| 358 | |
Fan Zhang | 12b03b2 | 2017-10-29 13:57:29 -0700 | [diff] [blame] | 359 | private RestrictedPreference newRemoveWorkProfilePreference() { |
Doris Ling | bfac31b | 2016-11-10 15:12:52 -0800 | [diff] [blame] | 360 | RestrictedPreference preference = new RestrictedPreference( |
| 361 | mParent.getPreferenceManager().getContext()); |
| 362 | preference.setTitle(R.string.remove_managed_profile_label); |
| 363 | preference.setIcon(R.drawable.ic_menu_delete); |
| 364 | preference.setOnPreferenceClickListener(this); |
| 365 | preference.setOrder(ORDER_LAST); |
| 366 | return preference; |
| 367 | } |
| 368 | |
| 369 | |
| 370 | private Preference newManagedProfileSettings() { |
| 371 | Preference preference = new Preference(mParent.getPreferenceManager().getContext()); |
| 372 | preference.setTitle(R.string.managed_profile_settings_title); |
| 373 | preference.setIcon(R.drawable.ic_settings); |
| 374 | preference.setOnPreferenceClickListener(this); |
| 375 | preference.setOrder(ORDER_NEXT_TO_LAST); |
| 376 | return preference; |
| 377 | } |
| 378 | |
| 379 | private String getWorkGroupSummary(Context context, UserInfo userInfo) { |
| 380 | PackageManager packageManager = context.getPackageManager(); |
| 381 | ApplicationInfo adminApplicationInfo = Utils.getAdminApplicationInfo(context, userInfo.id); |
| 382 | if (adminApplicationInfo == null) { |
| 383 | return null; |
| 384 | } |
| 385 | CharSequence appLabel = packageManager.getApplicationLabel(adminApplicationInfo); |
| 386 | return mContext.getString(R.string.managing_admin, appLabel); |
| 387 | } |
| 388 | |
| 389 | void cleanUpPreferences() { |
| 390 | PreferenceScreen screen = mParent.getPreferenceScreen(); |
Fan Zhang | 424443b | 2017-01-10 11:50:01 -0800 | [diff] [blame] | 391 | if (screen == null) { |
| 392 | return; |
| 393 | } |
Doris Ling | 633250b | 2017-05-02 11:28:14 -0700 | [diff] [blame] | 394 | final int count = mProfiles.size(); |
| 395 | for (int i = count-1; i >= 0; i--) { |
| 396 | final ProfileData data = mProfiles.valueAt(i); |
| 397 | if (data.pendingRemoval) { |
| 398 | screen.removePreference(data.preferenceGroup); |
| 399 | mProfiles.removeAt(i); |
| 400 | } |
Doris Ling | bfac31b | 2016-11-10 15:12:52 -0800 | [diff] [blame] | 401 | } |
Doris Ling | bfac31b | 2016-11-10 15:12:52 -0800 | [diff] [blame] | 402 | } |
| 403 | |
| 404 | private void listenToAccountUpdates() { |
| 405 | final int count = mProfiles.size(); |
| 406 | for (int i = 0; i < count; i++) { |
| 407 | AuthenticatorHelper authenticatorHelper = mProfiles.valueAt(i).authenticatorHelper; |
| 408 | if (authenticatorHelper != null) { |
| 409 | authenticatorHelper.listenToAccountUpdates(); |
| 410 | } |
| 411 | } |
| 412 | } |
| 413 | |
| 414 | private void stopListeningToAccountUpdates() { |
| 415 | final int count = mProfiles.size(); |
| 416 | for (int i = 0; i < count; i++) { |
| 417 | AuthenticatorHelper authenticatorHelper = mProfiles.valueAt(i).authenticatorHelper; |
| 418 | if (authenticatorHelper != null) { |
| 419 | authenticatorHelper.stopListeningToAccountUpdates(); |
| 420 | } |
| 421 | } |
| 422 | } |
| 423 | |
| 424 | private void updateAccountTypes(ProfileData profileData) { |
Fan Zhang | c7804c1 | 2017-01-13 14:57:01 -0800 | [diff] [blame] | 425 | if (mParent.getPreferenceManager() == null |
| 426 | || profileData.preferenceGroup.getPreferenceManager() == null) { |
Fan Zhang | 81a030f | 2017-01-11 10:46:45 -0800 | [diff] [blame] | 427 | // This could happen if activity is finishing |
| 428 | return; |
| 429 | } |
Doris Ling | bfac31b | 2016-11-10 15:12:52 -0800 | [diff] [blame] | 430 | if (profileData.userInfo.isEnabled()) { |
Fan Zhang | c754f59 | 2017-05-17 12:32:59 -0700 | [diff] [blame] | 431 | final ArrayMap<String, AccountTypePreference> preferenceToRemove = |
Doris Ling | 633250b | 2017-05-02 11:28:14 -0700 | [diff] [blame] | 432 | new ArrayMap<>(profileData.accountPreferences); |
Doris Ling | 20d4b04 | 2016-11-22 16:37:06 -0800 | [diff] [blame] | 433 | final ArrayList<AccountTypePreference> preferences = getAccountTypePreferences( |
Doris Ling | 633250b | 2017-05-02 11:28:14 -0700 | [diff] [blame] | 434 | profileData.authenticatorHelper, profileData.userInfo.getUserHandle(), |
| 435 | preferenceToRemove); |
Doris Ling | bfac31b | 2016-11-10 15:12:52 -0800 | [diff] [blame] | 436 | final int count = preferences.size(); |
| 437 | for (int i = 0; i < count; i++) { |
Doris Ling | 633250b | 2017-05-02 11:28:14 -0700 | [diff] [blame] | 438 | final AccountTypePreference preference = preferences.get(i); |
| 439 | preference.setOrder(i); |
Fan Zhang | c754f59 | 2017-05-17 12:32:59 -0700 | [diff] [blame] | 440 | final String key = preference.getKey(); |
| 441 | if (!profileData.accountPreferences.containsKey(key)) { |
| 442 | profileData.preferenceGroup.addPreference(preference); |
| 443 | profileData.accountPreferences.put(key, preference); |
Doris Ling | 633250b | 2017-05-02 11:28:14 -0700 | [diff] [blame] | 444 | } |
Doris Ling | bfac31b | 2016-11-10 15:12:52 -0800 | [diff] [blame] | 445 | } |
| 446 | if (profileData.addAccountPreference != null) { |
| 447 | profileData.preferenceGroup.addPreference(profileData.addAccountPreference); |
| 448 | } |
Fan Zhang | c754f59 | 2017-05-17 12:32:59 -0700 | [diff] [blame] | 449 | for (String key : preferenceToRemove.keySet()) { |
Doris Ling | 633250b | 2017-05-02 11:28:14 -0700 | [diff] [blame] | 450 | profileData.preferenceGroup.removePreference( |
Fan Zhang | c754f59 | 2017-05-17 12:32:59 -0700 | [diff] [blame] | 451 | profileData.accountPreferences.get(key)); |
| 452 | profileData.accountPreferences.remove(key); |
Doris Ling | 633250b | 2017-05-02 11:28:14 -0700 | [diff] [blame] | 453 | } |
Doris Ling | bfac31b | 2016-11-10 15:12:52 -0800 | [diff] [blame] | 454 | } else { |
Doris Ling | 633250b | 2017-05-02 11:28:14 -0700 | [diff] [blame] | 455 | profileData.preferenceGroup.removeAll(); |
Doris Ling | bfac31b | 2016-11-10 15:12:52 -0800 | [diff] [blame] | 456 | // Put a label instead of the accounts list |
| 457 | if (mProfileNotAvailablePreference == null) { |
| 458 | mProfileNotAvailablePreference = |
| 459 | new Preference(mParent.getPreferenceManager().getContext()); |
| 460 | } |
| 461 | mProfileNotAvailablePreference.setEnabled(false); |
| 462 | mProfileNotAvailablePreference.setIcon(R.drawable.empty_icon); |
| 463 | mProfileNotAvailablePreference.setTitle(null); |
| 464 | mProfileNotAvailablePreference.setSummary( |
| 465 | R.string.managed_profile_not_available_label); |
| 466 | profileData.preferenceGroup.addPreference(mProfileNotAvailablePreference); |
| 467 | } |
| 468 | if (profileData.removeWorkProfilePreference != null) { |
| 469 | profileData.preferenceGroup.addPreference(profileData.removeWorkProfilePreference); |
| 470 | } |
| 471 | if (profileData.managedProfilePreference != null) { |
| 472 | profileData.preferenceGroup.addPreference(profileData.managedProfilePreference); |
| 473 | } |
| 474 | } |
| 475 | |
Doris Ling | 20d4b04 | 2016-11-22 16:37:06 -0800 | [diff] [blame] | 476 | private ArrayList<AccountTypePreference> getAccountTypePreferences(AuthenticatorHelper helper, |
Fan Zhang | c754f59 | 2017-05-17 12:32:59 -0700 | [diff] [blame] | 477 | UserHandle userHandle, ArrayMap<String, AccountTypePreference> preferenceToRemove) { |
Doris Ling | bfac31b | 2016-11-10 15:12:52 -0800 | [diff] [blame] | 478 | final String[] accountTypes = helper.getEnabledAccountTypes(); |
Doris Ling | 20d4b04 | 2016-11-22 16:37:06 -0800 | [diff] [blame] | 479 | final ArrayList<AccountTypePreference> accountTypePreferences = |
Fan Zhang | c6ca314 | 2017-02-14 15:02:35 -0800 | [diff] [blame] | 480 | new ArrayList<>(accountTypes.length); |
Doris Ling | bfac31b | 2016-11-10 15:12:52 -0800 | [diff] [blame] | 481 | |
| 482 | for (int i = 0; i < accountTypes.length; i++) { |
| 483 | final String accountType = accountTypes[i]; |
| 484 | // Skip showing any account that does not have any of the requested authorities |
| 485 | if (!accountTypeHasAnyRequestedAuthorities(helper, accountType)) { |
| 486 | continue; |
| 487 | } |
| 488 | final CharSequence label = helper.getLabelForType(mContext, accountType); |
| 489 | if (label == null) { |
| 490 | continue; |
| 491 | } |
| 492 | final String titleResPackageName = helper.getPackageForType(accountType); |
| 493 | final int titleResId = helper.getLabelIdForType(accountType); |
| 494 | |
| 495 | final Account[] accounts = AccountManager.get(mContext) |
| 496 | .getAccountsByTypeAsUser(accountType, userHandle); |
Doris Ling | 20d4b04 | 2016-11-22 16:37:06 -0800 | [diff] [blame] | 497 | final Drawable icon = helper.getDrawableForType(mContext, accountType); |
| 498 | final Context prefContext = mParent.getPreferenceManager().getContext(); |
Doris Ling | bfac31b | 2016-11-10 15:12:52 -0800 | [diff] [blame] | 499 | |
Doris Ling | f074f0f | 2017-02-24 15:20:05 -0800 | [diff] [blame] | 500 | // Add a preference row for each individual account |
| 501 | for (Account account : accounts) { |
Fan Zhang | c754f59 | 2017-05-17 12:32:59 -0700 | [diff] [blame] | 502 | final AccountTypePreference preference = |
| 503 | preferenceToRemove.remove(AccountTypePreference.buildKey(account)); |
Doris Ling | 633250b | 2017-05-02 11:28:14 -0700 | [diff] [blame] | 504 | if (preference != null) { |
| 505 | accountTypePreferences.add(preference); |
| 506 | continue; |
| 507 | } |
Doris Ling | f074f0f | 2017-02-24 15:20:05 -0800 | [diff] [blame] | 508 | final ArrayList<String> auths = |
| 509 | helper.getAuthoritiesForAccountType(account.type); |
| 510 | if (!AccountRestrictionHelper.showAccount(mAuthorities, auths)) { |
| 511 | continue; |
Doris Ling | 20d4b04 | 2016-11-22 16:37:06 -0800 | [diff] [blame] | 512 | } |
Doris Ling | bfac31b | 2016-11-10 15:12:52 -0800 | [diff] [blame] | 513 | final Bundle fragmentArguments = new Bundle(); |
Doris Ling | f074f0f | 2017-02-24 15:20:05 -0800 | [diff] [blame] | 514 | fragmentArguments.putParcelable(AccountDetailDashboardFragment.KEY_ACCOUNT, |
| 515 | account); |
| 516 | fragmentArguments.putParcelable(AccountDetailDashboardFragment.KEY_USER_HANDLE, |
| 517 | userHandle); |
| 518 | fragmentArguments.putString(AccountDetailDashboardFragment.KEY_ACCOUNT_TYPE, |
| 519 | accountType); |
| 520 | fragmentArguments.putString(AccountDetailDashboardFragment.KEY_ACCOUNT_LABEL, |
| 521 | label.toString()); |
| 522 | fragmentArguments.putInt(AccountDetailDashboardFragment.KEY_ACCOUNT_TITLE_RES, |
| 523 | titleResId); |
Doris Ling | bfac31b | 2016-11-10 15:12:52 -0800 | [diff] [blame] | 524 | fragmentArguments.putParcelable(EXTRA_USER, userHandle); |
Doris Ling | 20d4b04 | 2016-11-22 16:37:06 -0800 | [diff] [blame] | 525 | accountTypePreferences.add(new AccountTypePreference( |
Doris Ling | f074f0f | 2017-02-24 15:20:05 -0800 | [diff] [blame] | 526 | prefContext, mMetricsFeatureProvider.getMetricsCategory(mParent), |
Fan Zhang | c754f59 | 2017-05-17 12:32:59 -0700 | [diff] [blame] | 527 | account, titleResPackageName, titleResId, label, |
Doris Ling | f074f0f | 2017-02-24 15:20:05 -0800 | [diff] [blame] | 528 | AccountDetailDashboardFragment.class.getName(), fragmentArguments, icon)); |
Doris Ling | bfac31b | 2016-11-10 15:12:52 -0800 | [diff] [blame] | 529 | } |
| 530 | helper.preloadDrawableForType(mContext, accountType); |
| 531 | } |
| 532 | // Sort by label |
Doris Ling | 20d4b04 | 2016-11-22 16:37:06 -0800 | [diff] [blame] | 533 | Collections.sort(accountTypePreferences, new Comparator<AccountTypePreference>() { |
Doris Ling | bfac31b | 2016-11-10 15:12:52 -0800 | [diff] [blame] | 534 | @Override |
Doris Ling | 20d4b04 | 2016-11-22 16:37:06 -0800 | [diff] [blame] | 535 | public int compare(AccountTypePreference t1, AccountTypePreference t2) { |
Doris Ling | f074f0f | 2017-02-24 15:20:05 -0800 | [diff] [blame] | 536 | int result = t1.getSummary().toString().compareTo(t2.getSummary().toString()); |
Doris Ling | 20d4b04 | 2016-11-22 16:37:06 -0800 | [diff] [blame] | 537 | return result != 0 |
| 538 | ? result : t1.getTitle().toString().compareTo(t2.getTitle().toString()); |
Doris Ling | bfac31b | 2016-11-10 15:12:52 -0800 | [diff] [blame] | 539 | } |
| 540 | }); |
| 541 | return accountTypePreferences; |
| 542 | } |
| 543 | |
| 544 | private boolean accountTypeHasAnyRequestedAuthorities(AuthenticatorHelper helper, |
| 545 | String accountType) { |
| 546 | if (mAuthoritiesCount == 0) { |
| 547 | // No authorities required |
| 548 | return true; |
| 549 | } |
| 550 | final ArrayList<String> authoritiesForType = helper.getAuthoritiesForAccountType( |
| 551 | accountType); |
| 552 | if (authoritiesForType == null) { |
| 553 | Log.d(TAG, "No sync authorities for account type: " + accountType); |
| 554 | return false; |
| 555 | } |
| 556 | for (int j = 0; j < mAuthoritiesCount; j++) { |
| 557 | if (authoritiesForType.contains(mAuthorities[j])) { |
| 558 | return true; |
| 559 | } |
| 560 | } |
| 561 | return false; |
| 562 | } |
| 563 | |
| 564 | private boolean isSingleProfile() { |
| 565 | return mUm.isLinkedUser() || mUm.getProfiles(UserHandle.myUserId()).size() == 1; |
| 566 | } |
| 567 | |
| 568 | private class ManagedProfileBroadcastReceiver extends BroadcastReceiver { |
| 569 | private boolean mListeningToManagedProfileEvents; |
| 570 | |
| 571 | @Override |
| 572 | public void onReceive(Context context, Intent intent) { |
| 573 | final String action = intent.getAction(); |
| 574 | Log.v(TAG, "Received broadcast: " + action); |
| 575 | if (action.equals(Intent.ACTION_MANAGED_PROFILE_REMOVED) |
| 576 | || action.equals(Intent.ACTION_MANAGED_PROFILE_ADDED)) { |
| 577 | // Clean old state |
| 578 | stopListeningToAccountUpdates(); |
Doris Ling | bfac31b | 2016-11-10 15:12:52 -0800 | [diff] [blame] | 579 | // Build new state |
| 580 | updateUi(); |
| 581 | listenToAccountUpdates(); |
| 582 | return; |
| 583 | } |
| 584 | Log.w(TAG, "Cannot handle received broadcast: " + intent.getAction()); |
| 585 | } |
| 586 | |
| 587 | public void register(Context context) { |
| 588 | if (!mListeningToManagedProfileEvents) { |
| 589 | IntentFilter intentFilter = new IntentFilter(); |
| 590 | intentFilter.addAction(Intent.ACTION_MANAGED_PROFILE_REMOVED); |
| 591 | intentFilter.addAction(Intent.ACTION_MANAGED_PROFILE_ADDED); |
| 592 | context.registerReceiver(this, intentFilter); |
| 593 | mListeningToManagedProfileEvents = true; |
| 594 | } |
| 595 | } |
| 596 | |
| 597 | public void unregister(Context context) { |
| 598 | if (mListeningToManagedProfileEvents) { |
| 599 | context.unregisterReceiver(this); |
| 600 | mListeningToManagedProfileEvents = false; |
| 601 | } |
| 602 | } |
| 603 | } |
| 604 | } |