Merge "Remove restrictions PIN functionality" into mnc-dev
This commit is contained in:
committed by
Android (Google) Code Review
commit
4f434a0470
@@ -23633,7 +23633,7 @@ package android.os {
|
||||
method public boolean isUserAGoat();
|
||||
method public boolean isUserRunning(android.os.UserHandle);
|
||||
method public boolean isUserRunningOrStopping(android.os.UserHandle);
|
||||
method public boolean setRestrictionsChallenge(java.lang.String);
|
||||
method public deprecated boolean setRestrictionsChallenge(java.lang.String);
|
||||
method public deprecated void setUserRestriction(java.lang.String, boolean);
|
||||
method public deprecated void setUserRestrictions(android.os.Bundle);
|
||||
method public deprecated void setUserRestrictions(android.os.Bundle, android.os.UserHandle);
|
||||
|
||||
@@ -25544,7 +25544,7 @@ package android.os {
|
||||
method public boolean isUserAGoat();
|
||||
method public boolean isUserRunning(android.os.UserHandle);
|
||||
method public boolean isUserRunningOrStopping(android.os.UserHandle);
|
||||
method public boolean setRestrictionsChallenge(java.lang.String);
|
||||
method public deprecated boolean setRestrictionsChallenge(java.lang.String);
|
||||
method public deprecated void setUserRestriction(java.lang.String, boolean);
|
||||
method public deprecated void setUserRestrictions(android.os.Bundle);
|
||||
method public deprecated void setUserRestrictions(android.os.Bundle, android.os.UserHandle);
|
||||
|
||||
@@ -2588,21 +2588,6 @@ public class Intent implements Parcelable, Cloneable {
|
||||
public static final String ACTION_GET_RESTRICTION_ENTRIES =
|
||||
"android.intent.action.GET_RESTRICTION_ENTRIES";
|
||||
|
||||
/**
|
||||
* @hide
|
||||
* Activity to challenge the user for a PIN that was configured when setting up
|
||||
* restrictions. Restrictions include blocking of apps and preventing certain user operations,
|
||||
* controlled by {@link android.os.UserManager#setUserRestrictions(Bundle).
|
||||
* Launch the activity using
|
||||
* {@link android.app.Activity#startActivityForResult(Intent, int)} and check if the
|
||||
* result is {@link android.app.Activity#RESULT_OK} for a successful response to the
|
||||
* challenge.<p/>
|
||||
* Before launching this activity, make sure that there is a PIN in effect, by calling
|
||||
* {@link android.os.UserManager#hasRestrictionsChallenge()}.
|
||||
*/
|
||||
public static final String ACTION_RESTRICTIONS_CHALLENGE =
|
||||
"android.intent.action.RESTRICTIONS_CHALLENGE";
|
||||
|
||||
/**
|
||||
* Sent the first time a user is starting, to allow system apps to
|
||||
* perform one time initialization. (This will not be seen by third
|
||||
|
||||
@@ -49,9 +49,6 @@ interface IUserManager {
|
||||
int userHandle);
|
||||
Bundle getApplicationRestrictions(in String packageName);
|
||||
Bundle getApplicationRestrictionsForUser(in String packageName, int userHandle);
|
||||
boolean setRestrictionsChallenge(in String newPin);
|
||||
int checkRestrictionsChallenge(in String pin);
|
||||
boolean hasRestrictionsChallenge();
|
||||
void removeRestrictions();
|
||||
void setDefaultGuestRestrictions(in Bundle restrictions);
|
||||
Bundle getDefaultGuestRestrictions();
|
||||
|
||||
@@ -744,7 +744,7 @@ public class UserManager {
|
||||
* @see #getSerialNumberForUser(UserHandle)
|
||||
*/
|
||||
public UserHandle getUserForSerialNumber(long serialNumber) {
|
||||
int ident = getUserHandle((int)serialNumber);
|
||||
int ident = getUserHandle((int) serialNumber);
|
||||
return ident >= 0 ? new UserHandle(ident) : null;
|
||||
}
|
||||
|
||||
@@ -1252,49 +1252,10 @@ public class UserManager {
|
||||
* apps and requires the MANAGE_USERS permission.
|
||||
* @param newPin the PIN to use for challenge dialogs.
|
||||
* @return Returns true if the challenge PIN was set successfully.
|
||||
* @deprecated The restrictions PIN functionality is no longer provided by the system.
|
||||
* This method is preserved for backwards compatibility reasons and always returns false.
|
||||
*/
|
||||
public boolean setRestrictionsChallenge(String newPin) {
|
||||
try {
|
||||
return mService.setRestrictionsChallenge(newPin);
|
||||
} catch (RemoteException re) {
|
||||
Log.w(TAG, "Could not change restrictions pin");
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* @hide
|
||||
* @param pin The PIN to verify, or null to get the number of milliseconds to wait for before
|
||||
* allowing the user to enter the PIN.
|
||||
* @return Returns a positive number (including zero) for how many milliseconds before
|
||||
* you can accept another PIN, when the input is null or the input doesn't match the saved PIN.
|
||||
* Returns {@link #PIN_VERIFICATION_SUCCESS} if the input matches the saved PIN. Returns
|
||||
* {@link #PIN_VERIFICATION_FAILED_NOT_SET} if there is no PIN set.
|
||||
*/
|
||||
public int checkRestrictionsChallenge(String pin) {
|
||||
try {
|
||||
return mService.checkRestrictionsChallenge(pin);
|
||||
} catch (RemoteException re) {
|
||||
Log.w(TAG, "Could not check restrictions pin");
|
||||
}
|
||||
return PIN_VERIFICATION_FAILED_INCORRECT;
|
||||
}
|
||||
|
||||
/**
|
||||
* @hide
|
||||
* Checks whether the user has restrictions that are PIN-protected. An application that
|
||||
* participates in restrictions can check if the owner has requested a PIN challenge for
|
||||
* any restricted operations. If there is a PIN in effect, the application should launch
|
||||
* the PIN challenge activity {@link android.content.Intent#ACTION_RESTRICTIONS_CHALLENGE}.
|
||||
* @see android.content.Intent#ACTION_RESTRICTIONS_CHALLENGE
|
||||
* @return whether a restrictions PIN is in effect.
|
||||
*/
|
||||
public boolean hasRestrictionsChallenge() {
|
||||
try {
|
||||
return mService.hasRestrictionsChallenge();
|
||||
} catch (RemoteException re) {
|
||||
Log.w(TAG, "Could not change restrictions pin");
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
@@ -1,181 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2013 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.internal.app;
|
||||
|
||||
import android.content.Context;
|
||||
import android.os.Bundle;
|
||||
import android.os.UserManager;
|
||||
import android.text.Editable;
|
||||
import android.text.TextWatcher;
|
||||
import android.view.KeyEvent;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.View;
|
||||
import android.view.View.OnClickListener;
|
||||
import android.widget.Button;
|
||||
import android.widget.EditText;
|
||||
import android.widget.TextView;
|
||||
import android.widget.TextView.OnEditorActionListener;
|
||||
|
||||
import com.android.internal.R;
|
||||
|
||||
/**
|
||||
* This activity is launched by Settings and other apps to either create a new PIN or
|
||||
* challenge for an existing PIN. The PIN is maintained by UserManager.
|
||||
*/
|
||||
public class RestrictionsPinActivity extends AlertActivity
|
||||
implements OnClickListener, TextWatcher, OnEditorActionListener {
|
||||
|
||||
protected UserManager mUserManager;
|
||||
protected boolean mHasRestrictionsPin;
|
||||
|
||||
protected EditText mPinText;
|
||||
protected TextView mPinErrorMessage;
|
||||
private Button mOkButton;
|
||||
private Button mCancelButton;
|
||||
|
||||
@Override
|
||||
public void onCreate(Bundle icicle) {
|
||||
super.onCreate(icicle);
|
||||
|
||||
mUserManager = (UserManager) getSystemService(Context.USER_SERVICE);
|
||||
mHasRestrictionsPin = mUserManager.hasRestrictionsChallenge();
|
||||
initUi();
|
||||
setupAlert();
|
||||
}
|
||||
|
||||
protected void initUi() {
|
||||
AlertController.AlertParams ap = mAlertParams;
|
||||
ap.mTitle = getString(R.string.restr_pin_enter_admin_pin);
|
||||
LayoutInflater inflater =
|
||||
(LayoutInflater) getSystemService(Context.LAYOUT_INFLATER_SERVICE);
|
||||
ap.mView = inflater.inflate(R.layout.restrictions_pin_challenge, null);
|
||||
|
||||
mPinErrorMessage = (TextView) ap.mView.findViewById(R.id.pin_error_message);
|
||||
mPinText = (EditText) ap.mView.findViewById(R.id.pin_text);
|
||||
mOkButton = (Button) ap.mView.findViewById(R.id.pin_ok_button);
|
||||
mCancelButton = (Button) ap.mView.findViewById(R.id.pin_cancel_button);
|
||||
|
||||
mPinText.addTextChangedListener(this);
|
||||
|
||||
mOkButton.setOnClickListener(this);
|
||||
mCancelButton.setOnClickListener(this);
|
||||
}
|
||||
|
||||
protected boolean verifyingPin() {
|
||||
return true;
|
||||
}
|
||||
|
||||
public void onResume() {
|
||||
super.onResume();
|
||||
|
||||
setPositiveButtonState(false);
|
||||
boolean hasPin = mUserManager.hasRestrictionsChallenge();
|
||||
if (hasPin) {
|
||||
mPinErrorMessage.setVisibility(View.INVISIBLE);
|
||||
mPinText.setOnEditorActionListener(this);
|
||||
updatePinTimer(-1);
|
||||
} else if (verifyingPin()) {
|
||||
setResult(RESULT_OK);
|
||||
finish();
|
||||
}
|
||||
}
|
||||
|
||||
protected void setPositiveButtonState(boolean enabled) {
|
||||
mOkButton.setEnabled(enabled);
|
||||
}
|
||||
|
||||
private boolean updatePinTimer(int pinTimerMs) {
|
||||
if (pinTimerMs < 0) {
|
||||
pinTimerMs = mUserManager.checkRestrictionsChallenge(null);
|
||||
}
|
||||
boolean enableInput;
|
||||
if (pinTimerMs >= 200) {
|
||||
// Do the count down timer for less than a minute, otherwise just say try again later.
|
||||
if (pinTimerMs <= 60000) {
|
||||
final int seconds = (pinTimerMs + 200) / 1000;
|
||||
final String formatString = getResources().getQuantityString(
|
||||
R.plurals.restr_pin_countdown,
|
||||
seconds);
|
||||
mPinErrorMessage.setText(String.format(formatString, seconds));
|
||||
} else {
|
||||
mPinErrorMessage.setText(R.string.restr_pin_try_later);
|
||||
}
|
||||
enableInput = false;
|
||||
mPinErrorMessage.setVisibility(View.VISIBLE);
|
||||
mPinText.setText("");
|
||||
mPinText.postDelayed(mCountdownRunnable, Math.min(1000, pinTimerMs));
|
||||
} else {
|
||||
enableInput = true;
|
||||
mPinErrorMessage.setText(R.string.restr_pin_incorrect);
|
||||
}
|
||||
mPinText.setEnabled(enableInput);
|
||||
setPositiveButtonState(enableInput);
|
||||
return enableInput;
|
||||
}
|
||||
|
||||
protected void performPositiveButtonAction() {
|
||||
int result = mUserManager.checkRestrictionsChallenge(mPinText.getText().toString());
|
||||
if (result == UserManager.PIN_VERIFICATION_SUCCESS) {
|
||||
setResult(RESULT_OK);
|
||||
finish();
|
||||
} else if (result >= 0) {
|
||||
mPinErrorMessage.setText(R.string.restr_pin_incorrect);
|
||||
mPinErrorMessage.setVisibility(View.VISIBLE);
|
||||
updatePinTimer(result);
|
||||
mPinText.setText("");
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void beforeTextChanged(CharSequence s, int start, int count, int after) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onTextChanged(CharSequence s, int start, int before, int count) {
|
||||
CharSequence pin = mPinText.getText();
|
||||
setPositiveButtonState(pin != null && pin.length() >= 4);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void afterTextChanged(Editable s) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onEditorAction(TextView v, int actionId, KeyEvent event) {
|
||||
performPositiveButtonAction();
|
||||
return true;
|
||||
}
|
||||
|
||||
private Runnable mCountdownRunnable = new Runnable() {
|
||||
public void run() {
|
||||
if (updatePinTimer(-1)) {
|
||||
// If we are no longer counting down, clear the message.
|
||||
mPinErrorMessage.setVisibility(View.INVISIBLE);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
@Override
|
||||
public void onClick(View v) {
|
||||
if (v == mOkButton) {
|
||||
performPositiveButtonAction();
|
||||
} else if (v == mCancelButton) {
|
||||
setResult(RESULT_CANCELED);
|
||||
finish();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -2573,17 +2573,6 @@
|
||||
android:process=":ui">
|
||||
</activity>
|
||||
|
||||
<activity android:name="com.android.internal.app.RestrictionsPinActivity"
|
||||
android:theme="@style/Theme.Material.DayNight.Dialog.Alert"
|
||||
android:excludeFromRecents="true"
|
||||
android:windowSoftInputMode="adjustPan"
|
||||
android:process=":ui">
|
||||
<intent-filter android:priority="100">
|
||||
<action android:name="android.intent.action.RESTRICTIONS_CHALLENGE" />
|
||||
<category android:name="android.intent.category.DEFAULT" />
|
||||
</intent-filter>
|
||||
</activity>
|
||||
|
||||
<receiver android:name="com.android.server.BootReceiver"
|
||||
android:primaryUserOnly="true">
|
||||
<intent-filter android:priority="1000">
|
||||
|
||||
@@ -68,9 +68,6 @@ import java.io.FileNotFoundException;
|
||||
import java.io.FileOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.PrintWriter;
|
||||
import java.security.MessageDigest;
|
||||
import java.security.NoSuchAlgorithmException;
|
||||
import java.security.SecureRandom;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
@@ -88,10 +85,6 @@ public class UserManagerService extends IUserManager.Stub {
|
||||
private static final String ATTR_ID = "id";
|
||||
private static final String ATTR_CREATION_TIME = "created";
|
||||
private static final String ATTR_LAST_LOGGED_IN_TIME = "lastLoggedIn";
|
||||
private static final String ATTR_SALT = "salt";
|
||||
private static final String ATTR_PIN_HASH = "pinHash";
|
||||
private static final String ATTR_FAILED_ATTEMPTS = "failedAttempts";
|
||||
private static final String ATTR_LAST_RETRY_MS = "lastAttemptMs";
|
||||
private static final String ATTR_SERIAL_NO = "serialNumber";
|
||||
private static final String ATTR_NEXT_SERIAL_NO = "nextSerialNumber";
|
||||
private static final String ATTR_PARTIAL = "partial";
|
||||
@@ -129,17 +122,10 @@ public class UserManagerService extends IUserManager.Stub {
|
||||
|
||||
private static final long EPOCH_PLUS_30_YEARS = 30L * 365 * 24 * 60 * 60 * 1000L; // ms
|
||||
|
||||
// Number of attempts before jumping to the next BACKOFF_TIMES slot
|
||||
private static final int BACKOFF_INC_INTERVAL = 5;
|
||||
|
||||
// Maximum number of managed profiles permitted is 1. This cannot be increased
|
||||
// without first making sure that the rest of the framework is prepared for it.
|
||||
private static final int MAX_MANAGED_PROFILES = 1;
|
||||
|
||||
// Amount of time to force the user to wait before entering the PIN again, after failing
|
||||
// BACKOFF_INC_INTERVAL times.
|
||||
private static final int[] BACKOFF_TIMES = { 0, 30*1000, 60*1000, 5*60*1000, 30*60*1000 };
|
||||
|
||||
static final int WRITE_USER_MSG = 1;
|
||||
static final int WRITE_USER_DELAY = 2*1000; // 2 seconds
|
||||
|
||||
@@ -158,16 +144,6 @@ public class UserManagerService extends IUserManager.Stub {
|
||||
private final SparseArray<Bundle> mUserRestrictions = new SparseArray<Bundle>();
|
||||
private final Bundle mGuestRestrictions = new Bundle();
|
||||
|
||||
class RestrictionsPinState {
|
||||
long salt;
|
||||
String pinHash;
|
||||
int failedAttempts;
|
||||
long lastAttemptTime;
|
||||
}
|
||||
|
||||
private final SparseArray<RestrictionsPinState> mRestrictionsPinStates =
|
||||
new SparseArray<RestrictionsPinState>();
|
||||
|
||||
/**
|
||||
* Set of user IDs being actively removed. Removed IDs linger in this set
|
||||
* for several seconds to work around a VFS caching issue.
|
||||
@@ -810,21 +786,6 @@ public class UserManagerService extends IUserManager.Stub {
|
||||
serializer.attribute(null, ATTR_CREATION_TIME, Long.toString(userInfo.creationTime));
|
||||
serializer.attribute(null, ATTR_LAST_LOGGED_IN_TIME,
|
||||
Long.toString(userInfo.lastLoggedInTime));
|
||||
RestrictionsPinState pinState = mRestrictionsPinStates.get(userInfo.id);
|
||||
if (pinState != null) {
|
||||
if (pinState.salt != 0) {
|
||||
serializer.attribute(null, ATTR_SALT, Long.toString(pinState.salt));
|
||||
}
|
||||
if (pinState.pinHash != null) {
|
||||
serializer.attribute(null, ATTR_PIN_HASH, pinState.pinHash);
|
||||
}
|
||||
if (pinState.failedAttempts != 0) {
|
||||
serializer.attribute(null, ATTR_FAILED_ATTEMPTS,
|
||||
Integer.toString(pinState.failedAttempts));
|
||||
serializer.attribute(null, ATTR_LAST_RETRY_MS,
|
||||
Long.toString(pinState.lastAttemptTime));
|
||||
}
|
||||
}
|
||||
if (userInfo.iconPath != null) {
|
||||
serializer.attribute(null, ATTR_ICON_PATH, userInfo.iconPath);
|
||||
}
|
||||
@@ -944,11 +905,7 @@ public class UserManagerService extends IUserManager.Stub {
|
||||
String iconPath = null;
|
||||
long creationTime = 0L;
|
||||
long lastLoggedInTime = 0L;
|
||||
long salt = 0L;
|
||||
String pinHash = null;
|
||||
int failedAttempts = 0;
|
||||
int profileGroupId = UserInfo.NO_PROFILE_GROUP_ID;
|
||||
long lastAttemptTime = 0L;
|
||||
boolean partial = false;
|
||||
boolean guestToRemove = false;
|
||||
Bundle restrictions = new Bundle();
|
||||
@@ -982,10 +939,6 @@ public class UserManagerService extends IUserManager.Stub {
|
||||
iconPath = parser.getAttributeValue(null, ATTR_ICON_PATH);
|
||||
creationTime = readLongAttribute(parser, ATTR_CREATION_TIME, 0);
|
||||
lastLoggedInTime = readLongAttribute(parser, ATTR_LAST_LOGGED_IN_TIME, 0);
|
||||
salt = readLongAttribute(parser, ATTR_SALT, 0L);
|
||||
pinHash = parser.getAttributeValue(null, ATTR_PIN_HASH);
|
||||
failedAttempts = readIntAttribute(parser, ATTR_FAILED_ATTEMPTS, 0);
|
||||
lastAttemptTime = readLongAttribute(parser, ATTR_LAST_RETRY_MS, 0L);
|
||||
profileGroupId = readIntAttribute(parser, ATTR_PROFILE_GROUP_ID,
|
||||
UserInfo.NO_PROFILE_GROUP_ID);
|
||||
String valueString = parser.getAttributeValue(null, ATTR_PARTIAL);
|
||||
@@ -1023,17 +976,6 @@ public class UserManagerService extends IUserManager.Stub {
|
||||
userInfo.guestToRemove = guestToRemove;
|
||||
userInfo.profileGroupId = profileGroupId;
|
||||
mUserRestrictions.append(id, restrictions);
|
||||
if (salt != 0L) {
|
||||
RestrictionsPinState pinState = mRestrictionsPinStates.get(id);
|
||||
if (pinState == null) {
|
||||
pinState = new RestrictionsPinState();
|
||||
mRestrictionsPinStates.put(id, pinState);
|
||||
}
|
||||
pinState.salt = salt;
|
||||
pinState.pinHash = pinHash;
|
||||
pinState.failedAttempts = failedAttempts;
|
||||
pinState.lastAttemptTime = lastAttemptTime;
|
||||
}
|
||||
return userInfo;
|
||||
|
||||
} catch (IOException ioe) {
|
||||
@@ -1435,8 +1377,6 @@ public class UserManagerService extends IUserManager.Stub {
|
||||
|
||||
// Remove this user from the list
|
||||
mUsers.remove(userHandle);
|
||||
|
||||
mRestrictionsPinStates.remove(userHandle);
|
||||
// Remove user file
|
||||
AtomicFile userFile = new AtomicFile(new File(mUsersDir, userHandle + XML_SUFFIX));
|
||||
userFile.delete();
|
||||
@@ -1507,92 +1447,6 @@ public class UserManagerService extends IUserManager.Stub {
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean setRestrictionsChallenge(String newPin) {
|
||||
checkManageUsersPermission("Only system can modify the restrictions pin");
|
||||
int userId = UserHandle.getCallingUserId();
|
||||
synchronized (mPackagesLock) {
|
||||
RestrictionsPinState pinState = mRestrictionsPinStates.get(userId);
|
||||
if (pinState == null) {
|
||||
pinState = new RestrictionsPinState();
|
||||
}
|
||||
if (newPin == null) {
|
||||
pinState.salt = 0;
|
||||
pinState.pinHash = null;
|
||||
} else {
|
||||
try {
|
||||
pinState.salt = SecureRandom.getInstance("SHA1PRNG").nextLong();
|
||||
} catch (NoSuchAlgorithmException e) {
|
||||
pinState.salt = (long) (Math.random() * Long.MAX_VALUE);
|
||||
}
|
||||
pinState.pinHash = passwordToHash(newPin, pinState.salt);
|
||||
pinState.failedAttempts = 0;
|
||||
}
|
||||
mRestrictionsPinStates.put(userId, pinState);
|
||||
writeUserLocked(mUsers.get(userId));
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int checkRestrictionsChallenge(String pin) {
|
||||
checkManageUsersPermission("Only system can verify the restrictions pin");
|
||||
int userId = UserHandle.getCallingUserId();
|
||||
synchronized (mPackagesLock) {
|
||||
RestrictionsPinState pinState = mRestrictionsPinStates.get(userId);
|
||||
// If there's no pin set, return error code
|
||||
if (pinState == null || pinState.salt == 0 || pinState.pinHash == null) {
|
||||
return UserManager.PIN_VERIFICATION_FAILED_NOT_SET;
|
||||
} else if (pin == null) {
|
||||
// If just checking if user can be prompted, return remaining time
|
||||
int waitTime = getRemainingTimeForPinAttempt(pinState);
|
||||
Slog.d(LOG_TAG, "Remaining waittime peek=" + waitTime);
|
||||
return waitTime;
|
||||
} else {
|
||||
int waitTime = getRemainingTimeForPinAttempt(pinState);
|
||||
Slog.d(LOG_TAG, "Remaining waittime=" + waitTime);
|
||||
if (waitTime > 0) {
|
||||
return waitTime;
|
||||
}
|
||||
if (passwordToHash(pin, pinState.salt).equals(pinState.pinHash)) {
|
||||
pinState.failedAttempts = 0;
|
||||
scheduleWriteUserLocked(mUsers.get(userId));
|
||||
return UserManager.PIN_VERIFICATION_SUCCESS;
|
||||
} else {
|
||||
pinState.failedAttempts++;
|
||||
pinState.lastAttemptTime = System.currentTimeMillis();
|
||||
scheduleWriteUserLocked(mUsers.get(userId));
|
||||
return waitTime;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private int getRemainingTimeForPinAttempt(RestrictionsPinState pinState) {
|
||||
int backoffIndex = Math.min(pinState.failedAttempts / BACKOFF_INC_INTERVAL,
|
||||
BACKOFF_TIMES.length - 1);
|
||||
int backoffTime = (pinState.failedAttempts % BACKOFF_INC_INTERVAL) == 0 ?
|
||||
BACKOFF_TIMES[backoffIndex] : 0;
|
||||
return (int) Math.max(backoffTime + pinState.lastAttemptTime - System.currentTimeMillis(),
|
||||
0);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean hasRestrictionsChallenge() {
|
||||
int userId = UserHandle.getCallingUserId();
|
||||
synchronized (mPackagesLock) {
|
||||
return hasRestrictionsPinLocked(userId);
|
||||
}
|
||||
}
|
||||
|
||||
private boolean hasRestrictionsPinLocked(int userId) {
|
||||
RestrictionsPinState pinState = mRestrictionsPinStates.get(userId);
|
||||
if (pinState == null || pinState.salt == 0 || pinState.pinHash == null) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void removeRestrictions() {
|
||||
checkManageUsersPermission("Only system can remove restrictions");
|
||||
@@ -1604,8 +1458,6 @@ public class UserManagerService extends IUserManager.Stub {
|
||||
synchronized (mPackagesLock) {
|
||||
// Remove all user restrictions
|
||||
setUserRestrictions(new Bundle(), userHandle);
|
||||
// Remove restrictions pin
|
||||
setRestrictionsChallenge(null);
|
||||
// Remove any app restrictions
|
||||
cleanAppRestrictions(userHandle);
|
||||
}
|
||||
@@ -1637,42 +1489,6 @@ public class UserManagerService extends IUserManager.Stub {
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/*
|
||||
* Generate a hash for the given password. To avoid brute force attacks, we use a salted hash.
|
||||
* Not the most secure, but it is at least a second level of protection. First level is that
|
||||
* the file is in a location only readable by the system process.
|
||||
* @param password the password.
|
||||
* @param salt the randomly generated salt
|
||||
* @return the hash of the pattern in a String.
|
||||
*/
|
||||
private String passwordToHash(String password, long salt) {
|
||||
if (password == null) {
|
||||
return null;
|
||||
}
|
||||
String algo = null;
|
||||
String hashed = salt + password;
|
||||
try {
|
||||
byte[] saltedPassword = (password + salt).getBytes();
|
||||
byte[] sha1 = MessageDigest.getInstance(algo = "SHA-1").digest(saltedPassword);
|
||||
byte[] md5 = MessageDigest.getInstance(algo = "MD5").digest(saltedPassword);
|
||||
hashed = toHex(sha1) + toHex(md5);
|
||||
} catch (NoSuchAlgorithmException e) {
|
||||
Log.w(LOG_TAG, "Failed to encode string because of missing algorithm: " + algo);
|
||||
}
|
||||
return hashed;
|
||||
}
|
||||
|
||||
private static String toHex(byte[] ary) {
|
||||
final String hex = "0123456789ABCDEF";
|
||||
String ret = "";
|
||||
for (int i = 0; i < ary.length; i++) {
|
||||
ret += hex.charAt((ary[i] >> 4) & 0xf);
|
||||
ret += hex.charAt(ary[i] & 0xf);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
private int getUidForPackage(String packageName) {
|
||||
long ident = Binder.clearCallingIdentity();
|
||||
try {
|
||||
@@ -1958,11 +1774,6 @@ public class UserManagerService extends IUserManager.Stub {
|
||||
return RESTRICTIONS_FILE_PREFIX + packageName + XML_SUFFIX;
|
||||
}
|
||||
|
||||
private String restrictionsFileNameToPackage(String fileName) {
|
||||
return fileName.substring(RESTRICTIONS_FILE_PREFIX.length(),
|
||||
(int) (fileName.length() - XML_SUFFIX.length()));
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
|
||||
if (mContext.checkCallingOrSelfPermission(android.Manifest.permission.DUMP)
|
||||
|
||||
Reference in New Issue
Block a user