Merge "Address TODOs in WifiNoInternetDialog." into mnc-dev
diff --git a/res/values/dimens.xml b/res/values/dimens.xml
index e4e9255..646c385 100755
--- a/res/values/dimens.xml
+++ b/res/values/dimens.xml
@@ -207,7 +207,9 @@
<integer name="bluetooth_name_length">32</integer>
<dimen name="bluetooth_pairing_padding">20dp</dimen>
+ <!-- WiFi Preferences -->
<dimen name="wifi_divider_height">1px</dimen>
+ <dimen name="wifi_preference_badge_padding">8dip</dimen>
<!-- Color picker -->
<dimen name="color_swatch_size">16dp</dimen>
diff --git a/res/values/strings.xml b/res/values/strings.xml
index feb10a7..c00d904 100644
--- a/res/values/strings.xml
+++ b/res/values/strings.xml
@@ -2451,6 +2451,12 @@
<!-- Title of wizard button offering to cancel move [CHAR LIMIT=32] -->
<string name="storage_wizard_move_progress_cancel">Cancel move</string>
+ <!-- Title of wizard step prompting user to start data migration [CHAR LIMIT=32] -->
+ <string name="storage_wizard_slow_body">This <xliff:g id="name" example="SD card">^1</xliff:g> appears to be slow.
+\n\nYou can continue, but apps moved to this location may stutter and data transfers may take a long time.
+\n\nConsider using a faster <xliff:g id="name" example="SD card">^1</xliff:g> for better performance.
+</string>
+
<!-- Phone info screen, section titles: -->
<string name="battery_status_title">Battery status</string>
<!-- Phone info screen, section titles: -->
diff --git a/src/com/android/settings/ChooseLockPassword.java b/src/com/android/settings/ChooseLockPassword.java
index 1338ac7..6a2ff5e 100644
--- a/src/com/android/settings/ChooseLockPassword.java
+++ b/src/com/android/settings/ChooseLockPassword.java
@@ -21,6 +21,7 @@
import com.android.internal.widget.LockPatternUtils;
import com.android.internal.widget.PasswordEntryKeyboardHelper;
import com.android.internal.widget.PasswordEntryKeyboardView;
+import com.android.internal.widget.TextViewInputDisabler;
import com.android.settings.notification.RedactionInterstitial;
import android.app.Activity;
@@ -127,6 +128,7 @@
private boolean mHasChallenge;
private long mChallenge;
private TextView mPasswordEntry;
+ private TextViewInputDisabler mPasswordEntryInputDisabler;
private int mPasswordMinLength = LockPatternUtils.MIN_LOCK_PASSWORD_SIZE;
private int mPasswordMaxLength = 16;
private int mPasswordMinLetters = 0;
@@ -255,6 +257,7 @@
mPasswordEntry = (TextView) view.findViewById(R.id.password_entry);
mPasswordEntry.setOnEditorActionListener(this);
mPasswordEntry.addTextChangedListener(this);
+ mPasswordEntryInputDisabler = new TextViewInputDisabler(mPasswordEntry);
final Activity activity = getActivity();
mKeyboardHelper = new PasswordEntryKeyboardHelper(activity,
@@ -315,7 +318,7 @@
public void onResume() {
super.onResume();
updateStage(mUiStage);
- mPasswordEntry.setEnabled(true);
+ mPasswordEntryInputDisabler.setInputEnabled(true);
mKeyboardView.requestFocus();
}
@@ -517,7 +520,7 @@
}
private void startVerifyPassword(final String pin, final boolean wasSecureBefore) {
- mPasswordEntry.setEnabled(false);
+ mPasswordEntryInputDisabler.setInputEnabled(false);
setNextEnabled(false);
if (mPendingLockCheck != null) {
mPendingLockCheck.cancel(false);
@@ -531,7 +534,7 @@
new LockPatternChecker.OnVerifyCallback() {
@Override
public void onVerified(byte[] token) {
- mPasswordEntry.setEnabled(true);
+ mPasswordEntryInputDisabler.setInputEnabled(true);
setNextEnabled(true);
mPendingLockCheck = null;
@@ -598,7 +601,7 @@
private void updateUi() {
String password = mPasswordEntry.getText().toString();
final int length = password.length();
- if (mUiStage == Stage.Introduction && length > 0) {
+ if (mUiStage == Stage.Introduction) {
if (length < mPasswordMinLength) {
String msg = getString(mIsAlphaMode ? R.string.lockpassword_password_too_short
: R.string.lockpassword_pin_too_short, mPasswordMinLength);
diff --git a/src/com/android/settings/ConfirmLockPassword.java b/src/com/android/settings/ConfirmLockPassword.java
index 388fde7..c1d8adb 100644
--- a/src/com/android/settings/ConfirmLockPassword.java
+++ b/src/com/android/settings/ConfirmLockPassword.java
@@ -22,6 +22,7 @@
import com.android.internal.logging.MetricsLogger;
import com.android.internal.widget.LockPatternChecker;
import com.android.internal.widget.LockPatternUtils;
+import com.android.internal.widget.TextViewInputDisabler;
import android.app.admin.DevicePolicyManager;
import android.content.Intent;
@@ -66,6 +67,7 @@
= "confirm_lock_password_fragment.key_num_wrong_confirm_attempts";
private static final long ERROR_MESSAGE_TIMEOUT = 3000;
private TextView mPasswordEntry;
+ private TextViewInputDisabler mPasswordEntryInputDisabler;
private LockPatternUtils mLockPatternUtils;
private AsyncTask<?, ?, ?> mPendingLockCheck;
private TextView mHeaderTextView;
@@ -100,6 +102,7 @@
mPasswordEntry = (TextView) view.findViewById(R.id.password_entry);
mPasswordEntry.setOnEditorActionListener(this);
+ mPasswordEntryInputDisabler = new TextViewInputDisabler(mPasswordEntry);
mHeaderTextView = (TextView) view.findViewById(R.id.headerText);
mDetailsTextView = (TextView) view.findViewById(R.id.detailsText);
@@ -169,7 +172,7 @@
if (deadline != 0) {
handleAttemptLockout(deadline);
} else {
- mPasswordEntry.setEnabled(true);
+ mPasswordEntryInputDisabler.setInputEnabled(true);
}
}
@@ -187,7 +190,7 @@
}
private void handleNext() {
- mPasswordEntry.setEnabled(false);
+ mPasswordEntryInputDisabler.setInputEnabled(false);
if (mPendingLockCheck != null) {
mPendingLockCheck.cancel(false);
}
@@ -259,7 +262,7 @@
}
private void onPasswordChecked(boolean matched, Intent intent) {
- mPasswordEntry.setEnabled(true);
+ mPasswordEntryInputDisabler.setInputEnabled(true);
if (matched) {
getActivity().setResult(RESULT_OK, intent);
getActivity().finish();
@@ -276,7 +279,7 @@
private void handleAttemptLockout(long elapsedRealtimeDeadline) {
long elapsedRealtime = SystemClock.elapsedRealtime();
- mPasswordEntry.setEnabled(false);
+ mPasswordEntryInputDisabler.setInputEnabled(false);
mCountdownTimer = new CountDownTimer(
elapsedRealtimeDeadline - elapsedRealtime,
LockPatternUtils.FAILED_ATTEMPT_COUNTDOWN_INTERVAL_MS) {
@@ -291,7 +294,7 @@
@Override
public void onFinish() {
- mPasswordEntry.setEnabled(true);
+ mPasswordEntryInputDisabler.setInputEnabled(true);
mErrorTextView.setText("");
mNumWrongConfirmAttempts = 0;
}
diff --git a/src/com/android/settings/SettingsActivity.java b/src/com/android/settings/SettingsActivity.java
index 7ce581f..c256f5c 100644
--- a/src/com/android/settings/SettingsActivity.java
+++ b/src/com/android/settings/SettingsActivity.java
@@ -1272,8 +1272,7 @@
((UserManager) getSystemService(Context.USER_SERVICE))
.getUserCount() > 1;
if (!UserHandle.MU_ENABLED
- || (!UserManager.supportsMultipleUsers()
- && !hasMultipleUsers)
+ || !UserManager.supportsMultipleUsers()
|| Utils.isMonkeyRunning()) {
removeTile = true;
}
diff --git a/src/com/android/settings/applications/ManageApplications.java b/src/com/android/settings/applications/ManageApplications.java
index 16234ba..124f9da 100644
--- a/src/com/android/settings/applications/ManageApplications.java
+++ b/src/com/android/settings/applications/ManageApplications.java
@@ -237,6 +237,8 @@
getActivity().getActionBar().setTitle(R.string.usage_access_title);
} else if (className.equals(HighPowerApplicationsActivity.class.getName())) {
mListType = LIST_TYPE_HIGH_POWER;
+ // Default to showing system.
+ mShowSystem = true;
} else {
mListType = LIST_TYPE_MAIN;
}
diff --git a/src/com/android/settings/deviceinfo/StorageWizardFormatProgress.java b/src/com/android/settings/deviceinfo/StorageWizardFormatProgress.java
index e2e6dbe..f1f4510 100644
--- a/src/com/android/settings/deviceinfo/StorageWizardFormatProgress.java
+++ b/src/com/android/settings/deviceinfo/StorageWizardFormatProgress.java
@@ -18,7 +18,11 @@
import static com.android.settings.deviceinfo.StorageSettings.TAG;
+import android.app.AlertDialog;
+import android.app.Dialog;
+import android.app.DialogFragment;
import android.content.Context;
+import android.content.DialogInterface;
import android.content.Intent;
import android.os.AsyncTask;
import android.os.Bundle;
@@ -33,6 +37,8 @@
import com.android.settings.R;
public class StorageWizardFormatProgress extends StorageWizardBase {
+ private static final String TAG_SLOW_WARNING = "slow_warning";
+
private boolean mFormatPrivate;
@Override
@@ -56,6 +62,9 @@
}
public class PartitionTask extends AsyncTask<Void, Integer, Exception> {
+ private volatile long mInternalBench;
+ private volatile long mPrivateBench;
+
@Override
protected Exception doInBackground(Void... params) {
try {
@@ -63,15 +72,12 @@
mStorage.partitionPrivate(mDisk.getId());
publishProgress(40);
- final long internalBench = mStorage.benchmark(null);
+ mInternalBench = mStorage.benchmark(null);
publishProgress(60);
final VolumeInfo privateVol = findFirstVolume(VolumeInfo.TYPE_PRIVATE);
- final long privateBench = mStorage.benchmark(privateVol.id);
+ mPrivateBench = mStorage.benchmark(privateVol.id);
- // TODO: plumb through to user when below threshold
- final float pct = (float) internalBench / (float) privateBench;
- Log.d(TAG, "New volume is " + pct + "x the speed of internal");
} else {
mStorage.partitionPublic(mDisk.getId());
}
@@ -89,40 +95,89 @@
@Override
protected void onPostExecute(Exception e) {
final Context context = StorageWizardFormatProgress.this;
- if (e == null) {
- final String forgetUuid = getIntent().getStringExtra(
- StorageWizardFormatConfirm.EXTRA_FORGET_UUID);
- if (!TextUtils.isEmpty(forgetUuid)) {
- mStorage.forgetVolume(forgetUuid);
- }
-
- final boolean offerMigrate;
- if (mFormatPrivate) {
- // Offer to migrate only if storage is currently internal
- final VolumeInfo privateVol = getPackageManager()
- .getPrimaryStorageCurrentVolume();
- offerMigrate = (privateVol != null
- && VolumeInfo.ID_PRIVATE_INTERNAL.equals(privateVol.getId()));
- } else {
- offerMigrate = false;
- }
-
- if (offerMigrate) {
- final Intent intent = new Intent(context, StorageWizardMigrate.class);
- intent.putExtra(DiskInfo.EXTRA_DISK_ID, mDisk.getId());
- startActivity(intent);
- } else {
- final Intent intent = new Intent(context, StorageWizardReady.class);
- intent.putExtra(DiskInfo.EXTRA_DISK_ID, mDisk.getId());
- startActivity(intent);
- }
- finishAffinity();
-
- } else {
+ if (e != null) {
Log.e(TAG, "Failed to partition", e);
Toast.makeText(context, e.getMessage(), Toast.LENGTH_LONG).show();
finishAffinity();
+ return;
+ }
+
+ final float pct = (float) mInternalBench / (float) mPrivateBench;
+ Log.d(TAG, "New volume is " + pct + "x the speed of internal");
+
+ // TODO: refine this warning threshold
+ if (mPrivateBench > 2000000000) {
+ final SlowWarningFragment dialog = new SlowWarningFragment();
+ dialog.show(getFragmentManager(), TAG_SLOW_WARNING);
+ } else {
+ onFormatFinished();
}
}
}
+
+ public class SlowWarningFragment extends DialogFragment {
+ @Override
+ public Dialog onCreateDialog(Bundle savedInstanceState) {
+ final Context context = getActivity();
+
+ final AlertDialog.Builder builder = new AlertDialog.Builder(context);
+
+ final String descrip = mDisk.getDescription();
+ final String genericDescip = getGenericDescription(mDisk);
+ builder.setMessage(TextUtils.expandTemplate(getText(R.string.storage_wizard_slow_body),
+ descrip, genericDescip));
+
+ builder.setPositiveButton(android.R.string.ok, new DialogInterface.OnClickListener() {
+ @Override
+ public void onClick(DialogInterface dialog, int which) {
+ final StorageWizardFormatProgress target =
+ (StorageWizardFormatProgress) getActivity();
+ target.onFormatFinished();
+ }
+ });
+
+ return builder.create();
+ }
+ }
+
+ private String getGenericDescription(DiskInfo disk) {
+ // TODO: move this directly to DiskInfo
+ if (disk.isSd()) {
+ return getString(com.android.internal.R.string.storage_sd_card);
+ } else if (disk.isUsb()) {
+ return getString(com.android.internal.R.string.storage_usb_drive);
+ } else {
+ return null;
+ }
+ }
+
+ private void onFormatFinished() {
+ final String forgetUuid = getIntent().getStringExtra(
+ StorageWizardFormatConfirm.EXTRA_FORGET_UUID);
+ if (!TextUtils.isEmpty(forgetUuid)) {
+ mStorage.forgetVolume(forgetUuid);
+ }
+
+ final boolean offerMigrate;
+ if (mFormatPrivate) {
+ // Offer to migrate only if storage is currently internal
+ final VolumeInfo privateVol = getPackageManager()
+ .getPrimaryStorageCurrentVolume();
+ offerMigrate = (privateVol != null
+ && VolumeInfo.ID_PRIVATE_INTERNAL.equals(privateVol.getId()));
+ } else {
+ offerMigrate = false;
+ }
+
+ if (offerMigrate) {
+ final Intent intent = new Intent(this, StorageWizardMigrate.class);
+ intent.putExtra(DiskInfo.EXTRA_DISK_ID, mDisk.getId());
+ startActivity(intent);
+ } else {
+ final Intent intent = new Intent(this, StorageWizardReady.class);
+ intent.putExtra(DiskInfo.EXTRA_DISK_ID, mDisk.getId());
+ startActivity(intent);
+ }
+ finishAffinity();
+ }
}
diff --git a/src/com/android/settings/deviceinfo/UsbModeChooserActivity.java b/src/com/android/settings/deviceinfo/UsbModeChooserActivity.java
index 76b2fd1..e0369d6 100644
--- a/src/com/android/settings/deviceinfo/UsbModeChooserActivity.java
+++ b/src/com/android/settings/deviceinfo/UsbModeChooserActivity.java
@@ -18,12 +18,14 @@
import android.annotation.Nullable;
import android.app.Activity;
+import android.app.ActivityManager;
import android.app.AlertDialog;
import android.content.Context;
import android.content.DialogInterface;
import android.hardware.usb.UsbManager;
import android.os.Bundle;
import android.util.Log;
+
import com.android.settings.R;
/**
@@ -46,7 +48,9 @@
new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
- setCurrentFunction(which);
+ if (!ActivityManager.isUserAMonkey()) {
+ setCurrentFunction(which);
+ }
dialog.dismiss();
UsbModeChooserActivity.this.finish();
}
diff --git a/src/com/android/settings/search/SearchIndexableResources.java b/src/com/android/settings/search/SearchIndexableResources.java
index 4d28d4a..8aba203 100644
--- a/src/com/android/settings/search/SearchIndexableResources.java
+++ b/src/com/android/settings/search/SearchIndexableResources.java
@@ -208,7 +208,7 @@
sResMap.put(UserSettings.class.getName(),
new SearchIndexableResource(
Ranking.getRankForClassName(UserSettings.class.getName()),
- R.xml.user_settings,
+ NO_DATA_RES_ID,
UserSettings.class.getName(),
R.drawable.ic_settings_multiuser));
diff --git a/src/com/android/settings/users/UserSettings.java b/src/com/android/settings/users/UserSettings.java
index cef0833..d5244d7 100644
--- a/src/com/android/settings/users/UserSettings.java
+++ b/src/com/android/settings/users/UserSettings.java
@@ -22,7 +22,6 @@
import android.app.ActivityManagerNative;
import android.app.AlertDialog;
import android.app.Dialog;
-import android.app.Fragment;
import android.app.admin.DevicePolicyManager;
import android.content.BroadcastReceiver;
import android.content.Context;
@@ -66,6 +65,9 @@
import com.android.settings.SettingsPreferenceFragment;
import com.android.settings.Utils;
import com.android.settings.drawable.CircleFramedDrawable;
+import com.android.settings.search.BaseSearchIndexProvider;
+import com.android.settings.search.Indexable;
+import com.android.settings.search.SearchIndexableRaw;
import java.util.ArrayList;
import java.util.Collections;
@@ -83,7 +85,7 @@
public class UserSettings extends SettingsPreferenceFragment
implements OnPreferenceClickListener, OnClickListener, DialogInterface.OnDismissListener,
Preference.OnPreferenceChangeListener,
- EditUserInfoController.OnContentChangedCallback {
+ EditUserInfoController.OnContentChangedCallback, Indexable {
private static final String TAG = "UserSettings";
@@ -131,15 +133,11 @@
private int mRemovingUserId = -1;
private int mAddedUserId = 0;
private boolean mAddingUser;
- private boolean mEnabled = true;
- private boolean mCanAddUser = true;
- private boolean mCanAddRestrictedProfile = true;
+ private UserCapabilities mUserCaps;
private final Object mUserLock = new Object();
private UserManager mUserManager;
private SparseArray<Bitmap> mUserIcons = new SparseArray<Bitmap>();
- private boolean mIsOwner = UserHandle.myUserId() == UserHandle.USER_OWNER;
- private boolean mIsGuest;
private EditUserInfoController mEditUserInfoController =
new EditUserInfoController();
@@ -198,16 +196,13 @@
mEditUserInfoController.onRestoreInstanceState(icicle);
}
final Context context = getActivity();
+ mUserCaps = UserCapabilities.create(context);
mUserManager = (UserManager) context.getSystemService(Context.USER_SERVICE);
- boolean hasMultipleUsers = mUserManager.getUserCount() > 1;
- if ((!UserManager.supportsMultipleUsers() && !hasMultipleUsers)
- || Utils.isMonkeyRunning()) {
- mEnabled = false;
+ if (!mUserCaps.mEnabled) {
return;
}
final int myUserId = UserHandle.myUserId();
- mIsGuest = mUserManager.getUserInfo(myUserId).isGuest();
addPreferencesFromResource(R.xml.user_settings);
mUserListCategory = (PreferenceGroup) findPreference(KEY_USER_LIST);
@@ -216,25 +211,15 @@
null /* delete icon handler */);
mMePreference.setKey(KEY_USER_ME);
mMePreference.setOnPreferenceClickListener(this);
- if (mIsOwner) {
+ if (mUserCaps.mIsOwner) {
mMePreference.setSummary(R.string.user_owner);
}
mAddUser = findPreference(KEY_ADD_USER);
- DevicePolicyManager dpm = (DevicePolicyManager) context.getSystemService(
- Context.DEVICE_POLICY_SERVICE);
- // No restricted profiles for tablets with a device owner, or phones.
- if (dpm.getDeviceOwner() != null || Utils.isVoiceCapable(context)) {
- mCanAddRestrictedProfile = false;
- }
// Determine if add user/profile button should be visible
- if (!mIsOwner || UserManager.getMaxSupportedUsers() < 2
- || !UserManager.supportsMultipleUsers()
- || mUserManager.hasUserRestriction(UserManager.DISALLOW_ADD_USER)) {
- mCanAddUser = false;
- } else {
+ if (mUserCaps.mCanAddUser) {
mAddUser.setOnPreferenceClickListener(this);
// change label to only mention user, if restricted profiles are not supported
- if (!mCanAddRestrictedProfile) {
+ if (!mUserCaps.mCanAddRestrictedProfile) {
mAddUser.setTitle(R.string.user_add_user_menu);
}
}
@@ -250,7 +235,7 @@
public void onResume() {
super.onResume();
- if (!mEnabled) return;
+ if (!mUserCaps.mEnabled) return;
loadProfile();
updateUserList();
@@ -260,7 +245,7 @@
public void onDestroy() {
super.onDestroy();
- if (!mEnabled) return;
+ if (!mUserCaps.mEnabled) return;
getActivity().unregisterReceiver(mUserChangeReceiver);
}
@@ -283,13 +268,13 @@
public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
int pos = 0;
UserManager um = (UserManager) getActivity().getSystemService(Context.USER_SERVICE);
- if (!mIsOwner && !um.hasUserRestriction(UserManager.DISALLOW_REMOVE_USER)) {
+ if (!mUserCaps.mIsOwner && !um.hasUserRestriction(UserManager.DISALLOW_REMOVE_USER)) {
String nickname = mUserManager.getUserName();
MenuItem removeThisUser = menu.add(0, MENU_REMOVE_USER, pos++,
getResources().getString(R.string.user_remove_user_menu, nickname));
removeThisUser.setShowAsAction(MenuItem.SHOW_AS_ACTION_NEVER);
}
- if (mIsOwner && !um.hasUserRestriction(UserManager.DISALLOW_ADD_USER)) {
+ if (mUserCaps.mIsOwner && !um.hasUserRestriction(UserManager.DISALLOW_ADD_USER)) {
MenuItem allowAddOnLockscreen = menu.add(0, MENU_ADD_ON_LOCKSCREEN, pos++,
R.string.user_add_on_lockscreen_menu);
allowAddOnLockscreen.setCheckable(true);
@@ -320,7 +305,7 @@
* Loads profile information for the current user.
*/
private void loadProfile() {
- if (mIsGuest) {
+ if (mUserCaps.mIsGuest) {
// No need to load profile information
mMePreference.setIcon(getEncircledDefaultIcon());
mMePreference.setTitle(R.string.user_exit_guest_title);
@@ -451,7 +436,7 @@
return;
}
UserInfo info = mUserManager.getUserInfo(userId);
- if (info.isRestricted() && mIsOwner) {
+ if (info.isRestricted() && mUserCaps.mIsOwner) {
Bundle extras = new Bundle();
extras.putInt(RestrictedProfileSettings.EXTRA_USER_ID, userId);
extras.putBoolean(RestrictedProfileSettings.EXTRA_NEW_USER, newUser);
@@ -462,7 +447,7 @@
} else if (info.id == UserHandle.myUserId()) {
// Jump to owner info panel
OwnerInfoSettings.show(this);
- } else if (mIsOwner) {
+ } else if (mUserCaps.mIsOwner) {
Bundle extras = new Bundle();
extras.putInt(UserDetailsSettings.EXTRA_USER_ID, userId);
((SettingsActivity) getActivity()).startPreferencePanel(
@@ -624,7 +609,7 @@
}
case DIALOG_USER_PROFILE_EDITOR: {
Dialog dlg = mEditUserInfoController.createDialog(
- (Fragment) this,
+ this,
mMePreference.getIcon(),
mMePreference.getTitle(),
R.string.profile_info_settings_title,
@@ -668,7 +653,7 @@
//updateUserList();
new Thread() {
public void run() {
- UserInfo user = null;
+ UserInfo user;
// Could take a few seconds
if (userType == USER_TYPE_USER) {
user = createTrustedUser();
@@ -704,7 +689,7 @@
*/
private void exitGuest() {
// Just to be safe
- if (!mIsGuest) {
+ if (!mUserCaps.mIsGuest) {
return;
}
removeThisUser();
@@ -740,8 +725,9 @@
// Secondary user: Delete
// Guest: Nothing
// Restricted Profile: Settings
- final boolean showSettings = mIsOwner && (voiceCapable || user.isRestricted());
- final boolean showDelete = mIsOwner
+ final boolean showSettings = mUserCaps.mIsOwner
+ && (voiceCapable || user.isRestricted());
+ final boolean showDelete = mUserCaps.mIsOwner
&& (!voiceCapable && !user.isRestricted() && !user.isGuest());
pref = new UserPreference(context, null, user.id,
showSettings ? this : null,
@@ -791,7 +777,7 @@
// Add a virtual Guest user for guest defaults
UserPreference pref = new UserPreference(getActivity(), null,
UserPreference.USERID_GUEST_DEFAULTS,
- mIsOwner && voiceCapable? this : null /* settings icon handler */,
+ mUserCaps.mIsOwner && voiceCapable? this : null /* settings icon handler */,
null /* delete icon handler */);
pref.setTitle(R.string.user_guest);
pref.setIcon(getEncircledDefaultIcon());
@@ -816,7 +802,7 @@
// "User & Profiles", otherwise the category is skipped and elements are added directly
// to preferenceScreen
PreferenceGroup groupToAddUsers;
- if (mCanAddRestrictedProfile) {
+ if (mUserCaps.mCanAddRestrictedProfile) {
mUserListCategory.removeAll();
mUserListCategory.setOrder(Preference.DEFAULT_ORDER);
preferenceScreen.addPreference(mUserListCategory);
@@ -830,7 +816,7 @@
}
// Append Add user to the end of the list
- if (mCanAddUser) {
+ if (mUserCaps.mCanAddUser) {
boolean moreUsers = mUserManager.canAddMoreUsers();
mAddUser.setEnabled(moreUsers);
mAddUser.setOrder(Preference.DEFAULT_ORDER);
@@ -839,7 +825,7 @@
}
private boolean shouldShowGuestUserPreference(List<UserInfo> users) {
- boolean showGuestPreference = !mIsGuest;
+ boolean showGuestPreference = !mUserCaps.mIsGuest;
// If user has DISALLOW_ADD_USER don't allow creating a guest either.
if (showGuestPreference && mUserManager.hasUserRestriction(UserManager.DISALLOW_ADD_USER)) {
showGuestPreference = false;
@@ -856,7 +842,6 @@
private void loadIconsAsync(List<Integer> missingIcons) {
- final Resources resources = getResources();
new AsyncTask<List<Integer>, Void, Void>() {
@Override
protected void onPostExecute(Void result) {
@@ -911,7 +896,7 @@
@Override
public boolean onPreferenceClick(Preference pref) {
if (pref == mMePreference) {
- if (mIsGuest) {
+ if (mUserCaps.mIsGuest) {
showDialog(DIALOG_CONFIRM_EXIT_GUEST);
return true;
}
@@ -938,7 +923,7 @@
} else if (pref == mAddUser) {
// If we allow both types, show a picker, otherwise directly go to
// flow for full user.
- if (mCanAddRestrictedProfile) {
+ if (mUserCaps.mCanAddRestrictedProfile) {
showDialog(DIALOG_CHOOSE_USER_TYPE);
} else {
onAddUserClicked(USER_TYPE_USER);
@@ -958,7 +943,7 @@
// No guest user. Create one, if there's no restriction.
// If it is not the primary user, then adding users from lockscreen must be enabled
if (mUserManager.hasUserRestriction(UserManager.DISALLOW_ADD_USER)
- || (!mIsOwner && Settings.Global.getInt(getContentResolver(),
+ || (!mUserCaps.mIsOwner && Settings.Global.getInt(getContentResolver(),
Settings.Global.ADD_USERS_WHEN_LOCKED, 0) != 1)) {
Log.i(TAG, "Blocking guest creation because it is restricted");
return;
@@ -1030,4 +1015,76 @@
public void onLabelChanged(CharSequence label) {
mMePreference.setTitle(label);
}
+
+ private static class UserCapabilities {
+ boolean mEnabled = true;
+ boolean mCanAddUser = true;
+ boolean mCanAddRestrictedProfile = true;
+ boolean mIsOwner = UserHandle.myUserId() == UserHandle.USER_OWNER;
+ boolean mIsGuest;
+
+ public static UserCapabilities create(Context context) {
+ UserManager userManager = (UserManager) context.getSystemService(Context.USER_SERVICE);
+ UserCapabilities caps = new UserCapabilities();
+ if (!UserManager.supportsMultipleUsers() || Utils.isMonkeyRunning()) {
+ caps.mEnabled = false;
+ return caps;
+ }
+
+ if (!caps.mIsOwner || UserManager.getMaxSupportedUsers() < 2
+ || !UserManager.supportsMultipleUsers()
+ || userManager.hasUserRestriction(UserManager.DISALLOW_ADD_USER)) {
+ caps.mCanAddUser = false;
+ }
+ DevicePolicyManager dpm = (DevicePolicyManager) context.getSystemService(
+ Context.DEVICE_POLICY_SERVICE);
+ // No restricted profiles for tablets with a device owner, or phones.
+ if (dpm.getDeviceOwner() != null || Utils.isVoiceCapable(context)) {
+ caps.mCanAddRestrictedProfile = false;
+ }
+ final int myUserId = UserHandle.myUserId();
+ caps.mIsGuest = userManager.getUserInfo(myUserId).isGuest();
+ return caps;
+ }
+
+ @Override
+ public String toString() {
+ return "UserCapabilities{" +
+ "mEnabled=" + mEnabled +
+ ", mCanAddUser=" + mCanAddUser +
+ ", mCanAddRestrictedProfile=" + mCanAddRestrictedProfile +
+ ", mIsOwner=" + mIsOwner +
+ ", mIsGuest=" + mIsGuest +
+ '}';
+ }
+ }
+
+ public static final Indexable.SearchIndexProvider SEARCH_INDEX_DATA_PROVIDER =
+ new BaseSearchIndexProvider() {
+ @Override
+ public List<SearchIndexableRaw> getRawDataToIndex(Context context,
+ boolean enabled) {
+ final List<SearchIndexableRaw> result = new ArrayList<>();
+ final UserCapabilities userCaps = UserCapabilities.create(context);
+ if (!userCaps.mEnabled) {
+ return result;
+ }
+ final Resources res = context.getResources();
+ SearchIndexableRaw data = new SearchIndexableRaw(context);
+ data.title = res.getString(R.string.user_settings_title);
+ data.screenTitle = res.getString(R.string.user_settings_title);
+ result.add(data);
+
+ if (userCaps.mCanAddUser) {
+ data = new SearchIndexableRaw(context);
+ data.title = res.getString(userCaps.mCanAddRestrictedProfile ?
+ R.string.user_add_user_or_profile_menu
+ : R.string.user_add_user_menu);
+ data.screenTitle = res.getString(R.string.user_settings_title);
+ result.add(data);
+ }
+ return result;
+ }
+ };
+
}
diff --git a/src/com/android/settings/wifi/AccessPointPreference.java b/src/com/android/settings/wifi/AccessPointPreference.java
index 511d88d..55d575e 100644
--- a/src/com/android/settings/wifi/AccessPointPreference.java
+++ b/src/com/android/settings/wifi/AccessPointPreference.java
@@ -18,9 +18,12 @@
import android.content.Context;
import android.graphics.drawable.Drawable;
import android.graphics.drawable.StateListDrawable;
+import android.net.wifi.WifiConfiguration;
+import android.os.UserHandle;
import android.preference.Preference;
import android.view.View;
import android.widget.TextView;
+
import com.android.settings.R;
import com.android.settingslib.wifi.AccessPoint;
@@ -33,6 +36,7 @@
private static int[] wifi_signal_attributes = { R.attr.wifi_signal };
+ private TextView mTitleView;
private TextView mSummaryView;
private boolean showSummary = true;
private boolean mForSavedNetworks = false;
@@ -56,9 +60,12 @@
super.onBindView(view);
updateIcon(mAccessPoint.getLevel(), getContext());
+ mTitleView = (TextView) view.findViewById(com.android.internal.R.id.title);
+
mSummaryView = (TextView) view.findViewById(com.android.internal.R.id.summary);
mSummaryView.setVisibility(showSummary ? View.VISIBLE : View.GONE);
+ updateBadge(getContext());
notifyChanged();
}
@@ -94,6 +101,27 @@
}
}
+ protected void updateBadge(Context context) {
+ if (mTitleView != null) {
+ WifiConfiguration config = mAccessPoint.getConfig();
+ if (config == null) {
+ return;
+ }
+ // Fetch badge (may be null)
+ UserHandle creatorUser = new UserHandle(UserHandle.getUserId(config.creatorUid));
+ Drawable badge =
+ context.getPackageManager().getUserBadgeForDensity(creatorUser, 0 /* dpi */);
+
+ // Distance from the end of the title at which this AP's user badge should sit.
+ final int badgePadding = context.getResources()
+ .getDimensionPixelSize(R.dimen.wifi_preference_badge_padding);
+
+ // Attach to the end of the title view
+ mTitleView.setCompoundDrawablesRelativeWithIntrinsicBounds(null, null, badge, null);
+ mTitleView.setCompoundDrawablePadding(badgePadding);
+ }
+ }
+
/**
* Shows or Hides the Summary of an AccessPoint.
*
@@ -117,6 +145,7 @@
final Context context = getContext();
updateIcon(mAccessPoint.getLevel(), context);
+ updateBadge(context);
// Force new summary
setSummary(null);