Merge "Fix crash when rotating HighPowerDetail dialog" am: 783ff43769 am: 7598c6201d
am: 8711f4055d
Change-Id: Idb2d601fa627dcb8268228435192392c760787d0
diff --git a/res/values/strings.xml b/res/values/strings.xml
index f98a799..58d4642 100644
--- a/res/values/strings.xml
+++ b/res/values/strings.xml
@@ -81,7 +81,23 @@
<!-- Phone Info screen. Menu item label. Used for diagnostic info screens, precise translation isn't needed -->
<string name="radioInfo_menu_viewSDN">View Service Dialing Numbers</string>
<!-- Phone Info screen. Menu item label. Used for diagnostic info screens, precise translation isn't needed -->
- <string name="radioInfo_menu_getPDP">Get PDP List</string>
+ <string name="radioInfo_menu_getIMS">IMS Service Status</string>
+
+ <!-- Phone Info screen. IMS Registration Title. Used for diagnostic info screens, precise translation isn't needed -->
+ <string name="radio_info_ims_reg_status_title">IMS Status</string>
+
+ <!-- Phone Info screen. IMS Status - Registered. Used for diagnostic info screens, precise translation isn't needed -->
+ <string name="radio_info_ims_reg_status_registered">Registered</string>
+ <!-- Phone Info screen. Ims Status - Unregistered. Used for diagnostic info screens, precise translation isn't needed -->
+ <string name="radio_info_ims_reg_status_not_registered">Not Registered</string>
+
+ <!-- Phone Info screen. Ims Feature Status label. Used for diagnostic info screens, precise translation isn't needed -->
+ <string name="radio_info_ims_feature_status_available">Available</string>
+ <!-- Phone Info screen. Ims Feature status label. Used for diagnostic info screens, precise translation isn't needed -->
+ <string name="radio_info_ims_feature_status_unavailable">Unavailable</string>
+
+ <!-- Phone Info screen. IMS Registration. Used for diagnostic info screens, precise translation isn't needed -->
+ <string name="radio_info_ims_reg_status">IMS Registration: <xliff:g id="status" example="registered">%1$s</xliff:g>\u000AVoice over LTE: <xliff:g id="availability" example="available">%2$s</xliff:g>\u000AVoice over WiFi: <xliff:g id="availability" example="available">%3$s</xliff:g>\u000AVideo Calling: <xliff:g id="availability" example="available">%4$s</xliff:g>\u000AUT Interface: <xliff:g id="availability" example="available">%5$s</xliff:g></string>
<!-- Phone Info screen. Status label. Used for diagnostic info screens, precise translation isn't needed -->
<string name="radioInfo_service_in">In Service</string>
diff --git a/src/com/android/settings/ChooseLockGeneric.java b/src/com/android/settings/ChooseLockGeneric.java
index d109eb1..e059041 100644
--- a/src/com/android/settings/ChooseLockGeneric.java
+++ b/src/com/android/settings/ChooseLockGeneric.java
@@ -186,22 +186,15 @@
ENCRYPT_REQUESTED_DISABLED);
}
- int targetUser = Utils.getSecureTargetUser(
+ // a) If this is started from other user, use that user id.
+ // b) If this is started from the same user, read the extra if this is launched
+ // from Settings app itself.
+ // c) Otherwise, use UserHandle.myUserId().
+ mUserId = Utils.getSecureTargetUser(
getActivity().getActivityToken(),
UserManager.get(getActivity()),
- null,
+ getArguments(),
getActivity().getIntent().getExtras()).getIdentifier();
- if (ACTION_SET_NEW_PARENT_PROFILE_PASSWORD.equals(chooseLockAction)
- || !mLockPatternUtils.isSeparateProfileChallengeAllowed(targetUser)) {
- // Always use parent if explicitely requested or if profile challenge is not
- // supported
- Bundle arguments = getArguments();
- mUserId = Utils.getUserIdFromBundle(getContext(), arguments != null ? arguments
- : getActivity().getIntent().getExtras());
- } else {
- mUserId = targetUser;
- }
-
if (ACTION_SET_NEW_PASSWORD.equals(chooseLockAction)
&& Utils.isManagedProfile(UserManager.get(getActivity()), mUserId)
&& mLockPatternUtils.isSeparateProfileChallengeEnabled(mUserId)) {
@@ -256,6 +249,8 @@
} else if (KEY_SKIP_FINGERPRINT.equals(key)) {
Intent chooseLockGenericIntent = new Intent(getActivity(), ChooseLockGeneric.class);
chooseLockGenericIntent.setAction(getIntent().getAction());
+ // Forward the target user id to ChooseLockGeneric.
+ chooseLockGenericIntent.putExtra(Intent.EXTRA_USER_ID, mUserId);
chooseLockGenericIntent.putExtra(PASSWORD_CONFIRMED, mPasswordConfirmed);
startActivityForResult(chooseLockGenericIntent, SKIP_FINGERPRINT_REQUEST);
return true;
@@ -343,6 +338,8 @@
if (data != null) {
intent.putExtras(data.getExtras());
}
+ // Forward the target user id to fingerprint setup page.
+ intent.putExtra(Intent.EXTRA_USER_ID, mUserId);
startActivity(intent);
finish();
} else if (requestCode == SKIP_FINGERPRINT_REQUEST) {
diff --git a/src/com/android/settings/RadioInfo.java b/src/com/android/settings/RadioInfo.java
index 54ff4db..2be1737 100644
--- a/src/com/android/settings/RadioInfo.java
+++ b/src/com/android/settings/RadioInfo.java
@@ -17,6 +17,8 @@
package com.android.settings;
import android.app.Activity;
+import android.app.AlertDialog;
+import android.app.Dialog;
import android.app.QueuedWork;
import android.content.Intent;
import android.content.pm.PackageManager;
@@ -160,7 +162,7 @@
private static final int MENU_ITEM_VIEW_ADN = 1;
private static final int MENU_ITEM_VIEW_FDN = 2;
private static final int MENU_ITEM_VIEW_SDN = 3;
- private static final int MENU_ITEM_GET_PDP_LIST = 4;
+ private static final int MENU_ITEM_GET_IMS_STATUS = 4;
private static final int MENU_ITEM_TOGGLE_DATA = 5;
private TextView mDeviceId; //DeviceId is the IMEI in GSM and the MEID in CDMA
@@ -497,7 +499,7 @@
}
private void restoreFromBundle(Bundle b) {
- if( b == null) {
+ if (b == null) {
return;
}
@@ -537,8 +539,8 @@
R.string.radioInfo_menu_viewFDN).setOnMenuItemClickListener(mViewFDNCallback);
menu.add(1, MENU_ITEM_VIEW_SDN, 0,
R.string.radioInfo_menu_viewSDN).setOnMenuItemClickListener(mViewSDNCallback);
- menu.add(1, MENU_ITEM_GET_PDP_LIST,
- 0, R.string.radioInfo_menu_getPDP).setOnMenuItemClickListener(mGetPdpList);
+ menu.add(1, MENU_ITEM_GET_IMS_STATUS,
+ 0, R.string.radioInfo_menu_getIMS).setOnMenuItemClickListener(mGetImsStatus);
menu.add(1, MENU_ITEM_TOGGLE_DATA,
0, R.string.radio_info_data_connection_disable).setOnMenuItemClickListener(mToggleData);
return true;
@@ -632,7 +634,7 @@
StringBuilder sb = new StringBuilder();
if (cids != null) {
- if ( cids.isEmpty() ) {
+ if (cids.isEmpty()) {
sb.append("no neighboring cells");
} else {
for (NeighboringCellInfo cell : cids) {
@@ -860,7 +862,7 @@
}
private final void updateNetworkType() {
- if( phone != null ) {
+ if (phone != null) {
ServiceState ss = phone.getServiceState();
dataNetwork.setText(ServiceState.rilRadioTechnologyToString(
phone.getServiceState().getRilDataRadioTechnology()));
@@ -1069,10 +1071,36 @@
}
};
- private MenuItem.OnMenuItemClickListener mGetPdpList = new MenuItem.OnMenuItemClickListener() {
+ private MenuItem.OnMenuItemClickListener mGetImsStatus = new MenuItem.OnMenuItemClickListener() {
public boolean onMenuItemClick(MenuItem item) {
- //FIXME: Replace with a TelephonyManager call
- phone.getDataCallList(null);
+ boolean isImsRegistered = phone.isImsRegistered();
+ boolean availableVolte = phone.isVolteEnabled();
+ boolean availableWfc = phone.isWifiCallingEnabled();
+ boolean availableVt = phone.isVideoEnabled();
+ boolean availableUt = phone.isUtEnabled();
+
+ final String imsRegString = isImsRegistered ?
+ getString(R.string.radio_info_ims_reg_status_registered) :
+ getString(R.string.radio_info_ims_reg_status_not_registered);
+
+ final String available = getString(R.string.radio_info_ims_feature_status_available);
+ final String unavailable = getString(
+ R.string.radio_info_ims_feature_status_unavailable);
+
+ String imsStatus = getString(R.string.radio_info_ims_reg_status,
+ imsRegString,
+ availableVolte ? available : unavailable,
+ availableWfc ? available : unavailable,
+ availableVt ? available : unavailable,
+ availableUt ? available : unavailable);
+
+ AlertDialog imsDialog = new AlertDialog.Builder(RadioInfo.this)
+ .setMessage(imsStatus)
+ .setTitle(getString(R.string.radio_info_ims_reg_status_title))
+ .create();
+
+ imsDialog.show();
+
return true;
}
};
@@ -1119,22 +1147,22 @@
radioPowerOnSwitch.setOnCheckedChangeListener(mRadioPowerOnChangeListener);
}
- void setImsVolteProvisionedState( boolean state ) {
+ void setImsVolteProvisionedState(boolean state) {
Log.d(TAG, "setImsVolteProvisioned state: " + ((state)? "on":"off"));
- setImsConfigProvisionedState( IMS_VOLTE_PROVISIONED_CONFIG_ID, state );
+ setImsConfigProvisionedState(IMS_VOLTE_PROVISIONED_CONFIG_ID, state);
}
- void setImsVtProvisionedState( boolean state ) {
+ void setImsVtProvisionedState(boolean state) {
Log.d(TAG, "setImsVtProvisioned() state: " + ((state)? "on":"off"));
- setImsConfigProvisionedState( IMS_VT_PROVISIONED_CONFIG_ID, state );
+ setImsConfigProvisionedState(IMS_VT_PROVISIONED_CONFIG_ID, state);
}
- void setImsWfcProvisionedState( boolean state ) {
+ void setImsWfcProvisionedState(boolean state) {
Log.d(TAG, "setImsWfcProvisioned() state: " + ((state)? "on":"off"));
- setImsConfigProvisionedState( IMS_WFC_PROVISIONED_CONFIG_ID, state );
+ setImsConfigProvisionedState(IMS_WFC_PROVISIONED_CONFIG_ID, state);
}
- void setImsConfigProvisionedState( int configItem, boolean state ) {
+ void setImsConfigProvisionedState(int configItem, boolean state) {
if (phone != null && mImsManager != null) {
QueuedWork.singleThreadExecutor().submit(new Runnable() {
public void run() {
@@ -1170,7 +1198,7 @@
@Override
public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
setImsVolteProvisionedState(isChecked);
- }
+ }
};
private boolean isImsVtProvisioned() {
@@ -1185,7 +1213,7 @@
@Override
public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
setImsVtProvisionedState(isChecked);
- }
+ }
};
private boolean isImsWfcProvisioned() {
@@ -1200,7 +1228,7 @@
@Override
public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
setImsWfcProvisionedState(isChecked);
- }
+ }
};
private void updateImsProvisionedState() {
@@ -1210,14 +1238,20 @@
imsVolteProvisionedSwitch.setOnCheckedChangeListener(null);
imsVolteProvisionedSwitch.setChecked(isImsVolteProvisioned());
imsVolteProvisionedSwitch.setOnCheckedChangeListener(mImsVolteCheckedChangeListener);
+ imsVolteProvisionedSwitch.setEnabled(
+ mImsManager.isVolteEnabledByPlatform(phone.getContext()));
imsVtProvisionedSwitch.setOnCheckedChangeListener(null);
imsVtProvisionedSwitch.setChecked(isImsVtProvisioned());
imsVtProvisionedSwitch.setOnCheckedChangeListener(mImsVtCheckedChangeListener);
+ imsVtProvisionedSwitch.setEnabled(
+ mImsManager.isVtEnabledByPlatform(phone.getContext()));
imsWfcProvisionedSwitch.setOnCheckedChangeListener(null);
imsWfcProvisionedSwitch.setChecked(isImsWfcProvisioned());
imsWfcProvisionedSwitch.setOnCheckedChangeListener(mImsWfcCheckedChangeListener);
+ imsWfcProvisionedSwitch.setEnabled(
+ mImsManager.isWfcEnabledByPlatform(phone.getContext()));
}
OnClickListener mDnsCheckButtonHandler = new OnClickListener() {
diff --git a/src/com/android/settings/Utils.java b/src/com/android/settings/Utils.java
index dd62c6f..eec269f 100644
--- a/src/com/android/settings/Utils.java
+++ b/src/com/android/settings/Utils.java
@@ -102,6 +102,7 @@
import java.util.Locale;
import static android.content.Intent.EXTRA_USER;
+import static android.content.Intent.EXTRA_USER_ID;
import static android.text.format.DateUtils.FORMAT_ABBREV_MONTH;
import static android.text.format.DateUtils.FORMAT_SHOW_DATE;
@@ -651,16 +652,21 @@
/**
* Returns the target user for a Settings activity.
- *
- * The target user can be either the current user, the user that launched this activity or
- * the user contained as an extra in the arguments or intent extras.
- *
+ * <p>
+ * User would be retrieved in this order:
+ * <ul>
+ * <li> If this activity is launched from other user, return that user id.
+ * <li> If this is launched from the Settings app in same user, return the user contained as an
+ * extra in the arguments or intent extras.
+ * <li> Otherwise, return UserHandle.myUserId().
+ * </ul>
+ * <p>
* Note: This is secure in the sense that it only returns a target user different to the current
* one if the app launching this activity is the Settings app itself, running in the same user
* or in one that is in the same profile group, or if the user id is provided by the system.
*/
public static UserHandle getSecureTargetUser(IBinder activityToken,
- UserManager um, @Nullable Bundle arguments, @Nullable Bundle intentExtras) {
+ UserManager um, @Nullable Bundle arguments, @Nullable Bundle intentExtras) {
UserHandle currentUser = new UserHandle(UserHandle.myUserId());
IActivityManager am = ActivityManagerNative.getDefault();
try {
@@ -675,16 +681,14 @@
return launchedFromUser;
}
}
- UserHandle extrasUser = intentExtras != null
- ? (UserHandle) intentExtras.getParcelable(EXTRA_USER) : null;
+ UserHandle extrasUser = getUserHandleFromBundle(intentExtras);
if (extrasUser != null && !extrasUser.equals(currentUser)) {
// Check it's secure
if (launchedFromSettingsApp && isProfileOf(um, extrasUser)) {
return extrasUser;
}
}
- UserHandle argumentsUser = arguments != null
- ? (UserHandle) arguments.getParcelable(EXTRA_USER) : null;
+ UserHandle argumentsUser = getUserHandleFromBundle(arguments);
if (argumentsUser != null && !argumentsUser.equals(currentUser)) {
// Check it's secure
if (launchedFromSettingsApp && isProfileOf(um, argumentsUser)) {
@@ -696,7 +700,26 @@
Log.v(TAG, "Could not talk to activity manager.", e);
}
return currentUser;
- }
+ }
+
+ /**
+ * Lookup both {@link Intent#EXTRA_USER} and {@link Intent#EXTRA_USER_ID} in the bundle
+ * and return the {@link UserHandle} object. Return {@code null} if nothing is found.
+ */
+ private static @Nullable UserHandle getUserHandleFromBundle(Bundle bundle) {
+ if (bundle == null) {
+ return null;
+ }
+ final UserHandle user = bundle.getParcelable(EXTRA_USER);
+ if (user != null) {
+ return user;
+ }
+ final int userId = bundle.getInt(EXTRA_USER_ID, -1);
+ if (userId != -1) {
+ return UserHandle.of(userId);
+ }
+ return null;
+ }
/**
* Returns the target user for a Settings activity.
diff --git a/src/com/android/settings/deviceinfo/StorageSettings.java b/src/com/android/settings/deviceinfo/StorageSettings.java
index 7757efc..1cba34a 100644
--- a/src/com/android/settings/deviceinfo/StorageSettings.java
+++ b/src/com/android/settings/deviceinfo/StorageSettings.java
@@ -53,6 +53,8 @@
import com.android.settings.search.Indexable;
import com.android.settings.search.SearchIndexableRaw;
import com.android.settingslib.RestrictedLockUtils;
+import com.android.settingslib.deviceinfo.PrivateStorageInfo;
+import com.android.settingslib.deviceinfo.StorageManagerVolumeProvider;
import com.android.settingslib.drawer.SettingsDrawerActivity;
import java.io.File;
@@ -167,7 +169,8 @@
for (VolumeInfo vol : volumes) {
if (vol.getType() == VolumeInfo.TYPE_PRIVATE) {
- final long volumeTotalBytes = getTotalSize(vol);
+ final long volumeTotalBytes = PrivateStorageInfo.getTotalSize(vol,
+ sTotalInternalStorage);
final int color = COLOR_PRIVATE[privateCount++ % COLOR_PRIVATE.length];
mInternalCategory.addPreference(
new StorageVolumePreference(context, vol, color, volumeTotalBytes));
@@ -276,7 +279,8 @@
if (vol.getType() == VolumeInfo.TYPE_PRIVATE) {
final Bundle args = new Bundle();
args.putString(VolumeInfo.EXTRA_VOLUME_ID, vol.getId());
- PrivateVolumeSettings.setVolumeSize(args, getTotalSize(vol));
+ PrivateVolumeSettings.setVolumeSize(args, PrivateStorageInfo.getTotalSize(vol,
+ sTotalInternalStorage));
startFragment(this, PrivateVolumeSettings.class.getCanonicalName(),
-1, 0, args);
return true;
@@ -506,47 +510,15 @@
private void updateSummary() {
// TODO: Register listener.
final StorageManager storageManager = mContext.getSystemService(StorageManager.class);
- if (sTotalInternalStorage <= 0) {
- sTotalInternalStorage = storageManager.getPrimaryStorageSize();
- }
- final List<VolumeInfo> volumes = storageManager.getVolumes();
- long privateFreeBytes = 0;
- long privateTotalBytes = 0;
- for (VolumeInfo info : volumes) {
- final File path = info.getPath();
- if (info.getType() != VolumeInfo.TYPE_PRIVATE || path == null) {
- continue;
- }
- privateTotalBytes += getTotalSize(info);
- privateFreeBytes += path.getFreeSpace();
- }
- long privateUsedBytes = privateTotalBytes - privateFreeBytes;
+ PrivateStorageInfo info = PrivateStorageInfo.getPrivateStorageInfo(
+ new StorageManagerVolumeProvider(storageManager));
+ long privateUsedBytes = info.totalBytes - info.freeBytes;
mLoader.setSummary(this, mContext.getString(R.string.storage_summary,
Formatter.formatFileSize(mContext, privateUsedBytes),
- Formatter.formatFileSize(mContext, privateTotalBytes)));
+ Formatter.formatFileSize(mContext, info.totalBytes)));
}
}
- private static long getTotalSize(VolumeInfo info) {
- // Device could have more than one primary storage, which could be located in the
- // internal flash (UUID_PRIVATE_INTERNAL) or in an external disk.
- // If it's internal, try to get its total size from StorageManager first
- // (sTotalInternalStorage), since that size is more precise because it accounts for
- // the system partition.
- if (info.getType() == VolumeInfo.TYPE_PRIVATE
- && Objects.equals(info.getFsUuid(), StorageManager.UUID_PRIVATE_INTERNAL)
- && sTotalInternalStorage > 0) {
- return sTotalInternalStorage;
- } else {
- final File path = info.getPath();
- if (path == null) {
- // Should not happen, caller should have checked.
- Log.e(TAG, "info's path is null on getTotalSize(): " + info);
- return 0;
- }
- return path.getTotalSpace();
- }
- }
public static final SummaryLoader.SummaryProviderFactory SUMMARY_PROVIDER_FACTORY
= new SummaryLoader.SummaryProviderFactory() {
diff --git a/src/com/android/settings/password/FingerprintManagerWrapper.java b/src/com/android/settings/password/FingerprintManagerWrapper.java
new file mode 100644
index 0000000..b00f786
--- /dev/null
+++ b/src/com/android/settings/password/FingerprintManagerWrapper.java
@@ -0,0 +1,47 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.settings.password;
+
+import android.annotation.NonNull;
+import android.hardware.fingerprint.FingerprintManager;
+
+import com.android.internal.util.Preconditions;
+
+/**
+ * Wrapper of {@link FingerprintManager}. Workaround for roboelectic testing. See
+ * {@link IFingerprintManager} for details.
+ */
+public class FingerprintManagerWrapper implements IFingerprintManager {
+ private @NonNull FingerprintManager mFingerprintManager;
+
+ public FingerprintManagerWrapper(@NonNull FingerprintManager fingerprintManager) {
+ Preconditions.checkNotNull(fingerprintManager);
+ mFingerprintManager = fingerprintManager;
+ }
+
+ public boolean isHardwareDetected() {
+ return mFingerprintManager.isHardwareDetected();
+ }
+
+ public boolean hasEnrolledFingerprints(int userId) {
+ return mFingerprintManager.hasEnrolledFingerprints(userId);
+ }
+
+ public long preEnroll() {
+ return mFingerprintManager.preEnroll();
+ }
+}
diff --git a/src/com/android/settings/password/IFingerprintManager.java b/src/com/android/settings/password/IFingerprintManager.java
new file mode 100644
index 0000000..15a9242
--- /dev/null
+++ b/src/com/android/settings/password/IFingerprintManager.java
@@ -0,0 +1,31 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.settings.password;
+
+/**
+ * This is the workaround to allow us test {@link SetNewPasswordController} which uses a new hidden
+ * API {@link android.hardware.fingerprint.FingerprintManager#hasEnrolledFingerprints(int)} that
+ * roboelectric does not support yet. Having roboelectic to support latest platform API is tracked
+ * in b/30995831.
+ */
+public interface IFingerprintManager {
+ boolean isHardwareDetected();
+
+ boolean hasEnrolledFingerprints(int userId);
+
+ long preEnroll();
+}
diff --git a/src/com/android/settings/password/SetNewPasswordActivity.java b/src/com/android/settings/password/SetNewPasswordActivity.java
index 7cdf006..b06da02 100644
--- a/src/com/android/settings/password/SetNewPasswordActivity.java
+++ b/src/com/android/settings/password/SetNewPasswordActivity.java
@@ -16,13 +16,18 @@
package com.android.settings.password;
-import android.annotation.Nullable;
+import static android.app.admin.DevicePolicyManager.ACTION_SET_NEW_PARENT_PROFILE_PASSWORD;
+import static android.app.admin.DevicePolicyManager.ACTION_SET_NEW_PASSWORD;
+
import android.app.Activity;
import android.app.admin.DevicePolicyManager;
import android.content.Intent;
import android.os.Bundle;
+import android.util.Log;
import com.android.settings.ChooseLockGeneric;
+import com.android.settings.SetupChooseLockGeneric;
+import com.android.settings.Utils;
/**
* Trampolines {@link DevicePolicyManager#ACTION_SET_NEW_PASSWORD} and
@@ -30,6 +35,7 @@
* activity for handling set new password.
*/
public class SetNewPasswordActivity extends Activity implements SetNewPasswordController.Ui {
+ private static final String TAG = "SetNewPasswordActivity";
private String mNewPasswordAction;
private SetNewPasswordController mSetNewPasswordController;
@@ -38,17 +44,22 @@
super.onCreate(savedState);
mNewPasswordAction = getIntent().getAction();
- mSetNewPasswordController = new SetNewPasswordController(this, this);
+ if (!ACTION_SET_NEW_PASSWORD.equals(mNewPasswordAction)
+ && !ACTION_SET_NEW_PARENT_PROFILE_PASSWORD.equals(mNewPasswordAction)) {
+ Log.e(TAG, "Unexpected action to launch this activity");
+ finish();
+ return;
+ }
+ mSetNewPasswordController = SetNewPasswordController.create(
+ this, this, getIntent(), getActivityToken());
mSetNewPasswordController.dispatchSetNewPasswordIntent();
}
@Override
- public void launchChooseLock(@Nullable Bundle chooseLockFingerprintExtras) {
+ public void launchChooseLock(Bundle chooseLockFingerprintExtras) {
Intent intent = new Intent(this, ChooseLockGeneric.class)
.setAction(mNewPasswordAction);
- if (chooseLockFingerprintExtras != null) {
- intent.putExtras(chooseLockFingerprintExtras);
- }
+ intent.putExtras(chooseLockFingerprintExtras);
startActivity(intent);
finish();
}
diff --git a/src/com/android/settings/password/SetNewPasswordController.java b/src/com/android/settings/password/SetNewPasswordController.java
index 470723b..b2b20d9 100644
--- a/src/com/android/settings/password/SetNewPasswordController.java
+++ b/src/com/android/settings/password/SetNewPasswordController.java
@@ -16,20 +16,27 @@
package com.android.settings.password;
+import static android.app.admin.DevicePolicyManager.ACTION_SET_NEW_PASSWORD;
+import static android.app.admin.DevicePolicyManager.KEYGUARD_DISABLE_FINGERPRINT;
+import static android.app.admin.DevicePolicyManager.PASSWORD_QUALITY_SOMETHING;
import static com.android.internal.util.Preconditions.checkNotNull;
import android.annotation.Nullable;
+import android.app.ActivityManager;
import android.app.admin.DevicePolicyManager;
import android.content.Context;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.hardware.fingerprint.FingerprintManager;
import android.os.Bundle;
-import android.os.UserHandle;
+import android.os.IBinder;
+import android.os.UserManager;
import com.android.internal.annotations.VisibleForTesting;
+import com.android.internal.widget.LockPatternUtils;
import com.android.settings.ChooseLockGeneric;
import com.android.settings.ChooseLockSettingsHelper;
+import com.android.settings.Utils;
/**
* Business logic for {@link SetNewPasswordActivity}.
@@ -42,31 +49,54 @@
interface Ui {
/** Starts the {@link ChooseLockGeneric} activity with the given extras. */
- void launchChooseLock(@Nullable Bundle chooseLockFingerprintExtras);
+ void launchChooseLock(Bundle chooseLockFingerprintExtras);
}
- private final int mCurrentUserId;
+ /**
+ * Which user is setting new password.
+ */
+ private final int mTargetUserId;
private final PackageManager mPackageManager;
- @Nullable private final FingerprintManager mFingerprintManager;
+ @Nullable private final IFingerprintManager mFingerprintManager;
private final DevicePolicyManager mDevicePolicyManager;
private final Ui mUi;
- public SetNewPasswordController(Context context, Ui ui) {
- this(context.getUserId(),
+ public static SetNewPasswordController create(Context context, Ui ui, Intent intent,
+ IBinder activityToken) {
+ // Trying to figure out which user is setting new password. If it is
+ // ACTION_SET_NEW_PARENT_PROFILE_PASSWORD or the calling user is not allowed to set
+ // separate profile challenge, it is the current user to set new password. Otherwise,
+ // it is the user who starts this activity setting new password.
+ int userId = ActivityManager.getCurrentUser();
+ if (ACTION_SET_NEW_PASSWORD.equals(intent.getAction())) {
+ final int callingUserId = Utils.getSecureTargetUser(activityToken,
+ UserManager.get(context), null, intent.getExtras()).getIdentifier();
+ final LockPatternUtils lockPatternUtils = new LockPatternUtils(context);
+ if (lockPatternUtils.isSeparateProfileChallengeAllowed(callingUserId)) {
+ userId = callingUserId;
+ }
+ }
+ // Create a wrapper of FingerprintManager for testing, see IFingerPrintManager for details.
+ final FingerprintManager fingerprintManager =
+ (FingerprintManager) context.getSystemService(Context.FINGERPRINT_SERVICE);
+ final IFingerprintManager fingerprintManagerWrapper =
+ fingerprintManager == null
+ ? null
+ : new FingerprintManagerWrapper(fingerprintManager);
+ return new SetNewPasswordController(userId,
context.getPackageManager(),
- (FingerprintManager) context.getSystemService(Context.FINGERPRINT_SERVICE),
- (DevicePolicyManager) context.getSystemService(Context.DEVICE_POLICY_SERVICE),
- ui);
+ fingerprintManagerWrapper,
+ (DevicePolicyManager) context.getSystemService(Context.DEVICE_POLICY_SERVICE), ui);
}
@VisibleForTesting
SetNewPasswordController(
- int currentUserId,
+ int targetUserId,
PackageManager packageManager,
- FingerprintManager fingerprintManager,
+ IFingerprintManager fingerprintManager,
DevicePolicyManager devicePolicyManager,
Ui ui) {
- mCurrentUserId = currentUserId;
+ mTargetUserId = targetUserId;
mPackageManager = checkNotNull(packageManager);
mFingerprintManager = fingerprintManager;
mDevicePolicyManager = checkNotNull(devicePolicyManager);
@@ -77,38 +107,38 @@
* Dispatches the set new password intent to the correct activity that handles it.
*/
public void dispatchSetNewPasswordIntent() {
+ final Bundle extras;
if (mPackageManager.hasSystemFeature(PackageManager.FEATURE_FINGERPRINT)
&& mFingerprintManager != null
&& mFingerprintManager.isHardwareDetected()
- && !mFingerprintManager.hasEnrolledFingerprints()
+ && !mFingerprintManager.hasEnrolledFingerprints(mTargetUserId)
&& !isFingerprintDisabledByAdmin()) {
- mUi.launchChooseLock(getFingerprintChooseLockExtras());
+ extras = getFingerprintChooseLockExtras();
} else {
- mUi.launchChooseLock(null);
+ extras = new Bundle();
}
+ // No matter we show fingerprint options or not, we should tell the next activity which
+ // user is setting new password.
+ extras.putInt(Intent.EXTRA_USER_ID, mTargetUserId);
+ mUi.launchChooseLock(extras);
}
private Bundle getFingerprintChooseLockExtras() {
Bundle chooseLockExtras = new Bundle();
- if (mFingerprintManager != null) {
- long challenge = mFingerprintManager.preEnroll();
- chooseLockExtras.putInt(ChooseLockGeneric.ChooseLockGenericFragment.MINIMUM_QUALITY_KEY,
- DevicePolicyManager.PASSWORD_QUALITY_SOMETHING);
- chooseLockExtras.putBoolean(
- ChooseLockGeneric.ChooseLockGenericFragment.HIDE_DISABLED_PREFS, true);
- chooseLockExtras.putBoolean(ChooseLockSettingsHelper.EXTRA_KEY_HAS_CHALLENGE, true);
- chooseLockExtras.putLong(ChooseLockSettingsHelper.EXTRA_KEY_CHALLENGE, challenge);
- chooseLockExtras.putBoolean(ChooseLockSettingsHelper.EXTRA_KEY_FOR_FINGERPRINT, true);
- if (mCurrentUserId != UserHandle.USER_NULL) {
- chooseLockExtras.putInt(Intent.EXTRA_USER_ID, mCurrentUserId);
- }
- }
+ long challenge = mFingerprintManager.preEnroll();
+ chooseLockExtras.putInt(ChooseLockGeneric.ChooseLockGenericFragment.MINIMUM_QUALITY_KEY,
+ PASSWORD_QUALITY_SOMETHING);
+ chooseLockExtras.putBoolean(
+ ChooseLockGeneric.ChooseLockGenericFragment.HIDE_DISABLED_PREFS, true);
+ chooseLockExtras.putBoolean(ChooseLockSettingsHelper.EXTRA_KEY_HAS_CHALLENGE, true);
+ chooseLockExtras.putLong(ChooseLockSettingsHelper.EXTRA_KEY_CHALLENGE, challenge);
+ chooseLockExtras.putBoolean(ChooseLockSettingsHelper.EXTRA_KEY_FOR_FINGERPRINT, true);
return chooseLockExtras;
}
private boolean isFingerprintDisabledByAdmin() {
- int disabledFeatures = mDevicePolicyManager.getKeyguardDisabledFeatures(
- null, mCurrentUserId);
- return (disabledFeatures & DevicePolicyManager.KEYGUARD_DISABLE_FINGERPRINT) != 0;
+ int disabledFeatures =
+ mDevicePolicyManager.getKeyguardDisabledFeatures(null, mTargetUserId);
+ return (disabledFeatures & KEYGUARD_DISABLE_FINGERPRINT) != 0;
}
}
diff --git a/src/com/android/settings/wifi/WifiEnabler.java b/src/com/android/settings/wifi/WifiEnabler.java
index f064050..15be224 100644
--- a/src/com/android/settings/wifi/WifiEnabler.java
+++ b/src/com/android/settings/wifi/WifiEnabler.java
@@ -226,8 +226,13 @@
if (mayDisableTethering(isChecked)) {
mWifiManager.setWifiApEnabled(null, false);
}
- MetricsLogger.action(mContext,
- isChecked ? MetricsEvent.ACTION_WIFI_ON : MetricsEvent.ACTION_WIFI_OFF);
+ if (isChecked) {
+ MetricsLogger.action(mContext, MetricsEvent.ACTION_WIFI_ON);
+ } else {
+ // Log if user was connected at the time of switching off.
+ MetricsLogger.action(mContext, MetricsEvent.ACTION_WIFI_OFF,
+ mConnected.get());
+ }
if (!mWifiManager.setWifiEnabled(isChecked)) {
// Error
mSwitchBar.setEnabled(true);
diff --git a/src/com/android/settings/wifi/WifiSettings.java b/src/com/android/settings/wifi/WifiSettings.java
index 7007d19..1d07f6c 100644
--- a/src/com/android/settings/wifi/WifiSettings.java
+++ b/src/com/android/settings/wifi/WifiSettings.java
@@ -481,12 +481,13 @@
}
switch (item.getItemId()) {
case MENU_ID_CONNECT: {
- if (mSelectedAccessPoint.isSaved()) {
- connect(mSelectedAccessPoint.getConfig());
+ boolean isSavedNetwork = mSelectedAccessPoint.isSaved();
+ if (isSavedNetwork) {
+ connect(mSelectedAccessPoint.getConfig(), isSavedNetwork);
} else if (mSelectedAccessPoint.getSecurity() == AccessPoint.SECURITY_NONE) {
/** Bypass dialog for unsecured networks */
mSelectedAccessPoint.generateOpenNetworkConfig();
- connect(mSelectedAccessPoint.getConfig());
+ connect(mSelectedAccessPoint.getConfig(), isSavedNetwork);
} else {
showDialog(mSelectedAccessPoint, WifiConfigUiBase.MODE_CONNECT);
}
@@ -519,7 +520,7 @@
if (mSelectedAccessPoint.getSecurity() == AccessPoint.SECURITY_NONE &&
!mSelectedAccessPoint.isSaved() && !mSelectedAccessPoint.isActive()) {
mSelectedAccessPoint.generateOpenNetworkConfig();
- connect(mSelectedAccessPoint.getConfig());
+ connect(mSelectedAccessPoint.getConfig(), false /* isSavedNetwork */);
} else if (mSelectedAccessPoint.isSaved()) {
showDialog(mSelectedAccessPoint, WifiConfigUiBase.MODE_VIEW);
} else {
@@ -813,14 +814,14 @@
if (config == null) {
if (mSelectedAccessPoint != null
&& mSelectedAccessPoint.isSaved()) {
- connect(mSelectedAccessPoint.getConfig());
+ connect(mSelectedAccessPoint.getConfig(), true /* isSavedNetwork */);
}
} else if (configController.getMode() == WifiConfigUiBase.MODE_MODIFY) {
mWifiManager.save(config, mSaveListener);
} else {
mWifiManager.save(config, mSaveListener);
if (mSelectedAccessPoint != null) { // Not an "Add network"
- connect(config);
+ connect(config, false /* isSavedNetwork */);
}
}
@@ -850,13 +851,17 @@
changeNextButtonState(false);
}
- protected void connect(final WifiConfiguration config) {
- MetricsLogger.action(getActivity(), MetricsEvent.ACTION_WIFI_CONNECT);
+ protected void connect(final WifiConfiguration config, boolean isSavedNetwork) {
+ // Log subtype if configuration is a saved network.
+ MetricsLogger.action(getActivity(), MetricsEvent.ACTION_WIFI_CONNECT,
+ isSavedNetwork);
mWifiManager.connect(config, mConnectListener);
}
- protected void connect(final int networkId) {
- MetricsLogger.action(getActivity(), MetricsEvent.ACTION_WIFI_CONNECT);
+ protected void connect(final int networkId, boolean isSavedNetwork) {
+ // Log subtype if configuration is a saved network.
+ MetricsLogger.action(getActivity(), MetricsEvent.ACTION_WIFI_CONNECT,
+ isSavedNetwork);
mWifiManager.connect(networkId, mConnectListener);
}
diff --git a/src/com/android/settings/wifi/WifiSettingsForSetupWizard.java b/src/com/android/settings/wifi/WifiSettingsForSetupWizard.java
index 2f35478..68f28ee 100644
--- a/src/com/android/settings/wifi/WifiSettingsForSetupWizard.java
+++ b/src/com/android/settings/wifi/WifiSettingsForSetupWizard.java
@@ -130,17 +130,17 @@
}
@Override
- protected void connect(final WifiConfiguration config) {
+ protected void connect(final WifiConfiguration config, boolean isSavedNetwork) {
WifiSetupActivity activity = (WifiSetupActivity) getActivity();
activity.networkSelected();
- super.connect(config);
+ super.connect(config, isSavedNetwork);
}
@Override
- protected void connect(final int networkId) {
+ protected void connect(final int networkId, boolean isSavedNetwork) {
WifiSetupActivity activity = (WifiSetupActivity) getActivity();
activity.networkSelected();
- super.connect(networkId);
+ super.connect(networkId, isSavedNetwork);
}
@Override