am 4f434a04: Merge "Remove restrictions PIN functionality" into mnc-dev
* commit '4f434a04708e7a254afe2e0d362f715229dc15d1': Remove restrictions PIN functionality
This commit is contained in:
@@ -23633,7 +23633,7 @@ package android.os {
|
|||||||
method public boolean isUserAGoat();
|
method public boolean isUserAGoat();
|
||||||
method public boolean isUserRunning(android.os.UserHandle);
|
method public boolean isUserRunning(android.os.UserHandle);
|
||||||
method public boolean isUserRunningOrStopping(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 setUserRestriction(java.lang.String, boolean);
|
||||||
method public deprecated void setUserRestrictions(android.os.Bundle);
|
method public deprecated void setUserRestrictions(android.os.Bundle);
|
||||||
method public deprecated void setUserRestrictions(android.os.Bundle, android.os.UserHandle);
|
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 isUserAGoat();
|
||||||
method public boolean isUserRunning(android.os.UserHandle);
|
method public boolean isUserRunning(android.os.UserHandle);
|
||||||
method public boolean isUserRunningOrStopping(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 setUserRestriction(java.lang.String, boolean);
|
||||||
method public deprecated void setUserRestrictions(android.os.Bundle);
|
method public deprecated void setUserRestrictions(android.os.Bundle);
|
||||||
method public deprecated void setUserRestrictions(android.os.Bundle, android.os.UserHandle);
|
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 =
|
public static final String ACTION_GET_RESTRICTION_ENTRIES =
|
||||||
"android.intent.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
|
* Sent the first time a user is starting, to allow system apps to
|
||||||
* perform one time initialization. (This will not be seen by third
|
* perform one time initialization. (This will not be seen by third
|
||||||
|
|||||||
@@ -49,9 +49,6 @@ interface IUserManager {
|
|||||||
int userHandle);
|
int userHandle);
|
||||||
Bundle getApplicationRestrictions(in String packageName);
|
Bundle getApplicationRestrictions(in String packageName);
|
||||||
Bundle getApplicationRestrictionsForUser(in String packageName, int userHandle);
|
Bundle getApplicationRestrictionsForUser(in String packageName, int userHandle);
|
||||||
boolean setRestrictionsChallenge(in String newPin);
|
|
||||||
int checkRestrictionsChallenge(in String pin);
|
|
||||||
boolean hasRestrictionsChallenge();
|
|
||||||
void removeRestrictions();
|
void removeRestrictions();
|
||||||
void setDefaultGuestRestrictions(in Bundle restrictions);
|
void setDefaultGuestRestrictions(in Bundle restrictions);
|
||||||
Bundle getDefaultGuestRestrictions();
|
Bundle getDefaultGuestRestrictions();
|
||||||
|
|||||||
@@ -744,7 +744,7 @@ public class UserManager {
|
|||||||
* @see #getSerialNumberForUser(UserHandle)
|
* @see #getSerialNumberForUser(UserHandle)
|
||||||
*/
|
*/
|
||||||
public UserHandle getUserForSerialNumber(long serialNumber) {
|
public UserHandle getUserForSerialNumber(long serialNumber) {
|
||||||
int ident = getUserHandle((int)serialNumber);
|
int ident = getUserHandle((int) serialNumber);
|
||||||
return ident >= 0 ? new UserHandle(ident) : null;
|
return ident >= 0 ? new UserHandle(ident) : null;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1252,49 +1252,10 @@ public class UserManager {
|
|||||||
* apps and requires the MANAGE_USERS permission.
|
* apps and requires the MANAGE_USERS permission.
|
||||||
* @param newPin the PIN to use for challenge dialogs.
|
* @param newPin the PIN to use for challenge dialogs.
|
||||||
* @return Returns true if the challenge PIN was set successfully.
|
* @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) {
|
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;
|
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">
|
android:process=":ui">
|
||||||
</activity>
|
</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"
|
<receiver android:name="com.android.server.BootReceiver"
|
||||||
android:primaryUserOnly="true">
|
android:primaryUserOnly="true">
|
||||||
<intent-filter android:priority="1000">
|
<intent-filter android:priority="1000">
|
||||||
|
|||||||
@@ -68,9 +68,6 @@ import java.io.FileNotFoundException;
|
|||||||
import java.io.FileOutputStream;
|
import java.io.FileOutputStream;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.io.PrintWriter;
|
import java.io.PrintWriter;
|
||||||
import java.security.MessageDigest;
|
|
||||||
import java.security.NoSuchAlgorithmException;
|
|
||||||
import java.security.SecureRandom;
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.List;
|
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_ID = "id";
|
||||||
private static final String ATTR_CREATION_TIME = "created";
|
private static final String ATTR_CREATION_TIME = "created";
|
||||||
private static final String ATTR_LAST_LOGGED_IN_TIME = "lastLoggedIn";
|
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_SERIAL_NO = "serialNumber";
|
||||||
private static final String ATTR_NEXT_SERIAL_NO = "nextSerialNumber";
|
private static final String ATTR_NEXT_SERIAL_NO = "nextSerialNumber";
|
||||||
private static final String ATTR_PARTIAL = "partial";
|
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
|
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
|
// 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.
|
// without first making sure that the rest of the framework is prepared for it.
|
||||||
private static final int MAX_MANAGED_PROFILES = 1;
|
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_MSG = 1;
|
||||||
static final int WRITE_USER_DELAY = 2*1000; // 2 seconds
|
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 SparseArray<Bundle> mUserRestrictions = new SparseArray<Bundle>();
|
||||||
private final Bundle mGuestRestrictions = new 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
|
* Set of user IDs being actively removed. Removed IDs linger in this set
|
||||||
* for several seconds to work around a VFS caching issue.
|
* 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_CREATION_TIME, Long.toString(userInfo.creationTime));
|
||||||
serializer.attribute(null, ATTR_LAST_LOGGED_IN_TIME,
|
serializer.attribute(null, ATTR_LAST_LOGGED_IN_TIME,
|
||||||
Long.toString(userInfo.lastLoggedInTime));
|
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) {
|
if (userInfo.iconPath != null) {
|
||||||
serializer.attribute(null, ATTR_ICON_PATH, userInfo.iconPath);
|
serializer.attribute(null, ATTR_ICON_PATH, userInfo.iconPath);
|
||||||
}
|
}
|
||||||
@@ -944,11 +905,7 @@ public class UserManagerService extends IUserManager.Stub {
|
|||||||
String iconPath = null;
|
String iconPath = null;
|
||||||
long creationTime = 0L;
|
long creationTime = 0L;
|
||||||
long lastLoggedInTime = 0L;
|
long lastLoggedInTime = 0L;
|
||||||
long salt = 0L;
|
|
||||||
String pinHash = null;
|
|
||||||
int failedAttempts = 0;
|
|
||||||
int profileGroupId = UserInfo.NO_PROFILE_GROUP_ID;
|
int profileGroupId = UserInfo.NO_PROFILE_GROUP_ID;
|
||||||
long lastAttemptTime = 0L;
|
|
||||||
boolean partial = false;
|
boolean partial = false;
|
||||||
boolean guestToRemove = false;
|
boolean guestToRemove = false;
|
||||||
Bundle restrictions = new Bundle();
|
Bundle restrictions = new Bundle();
|
||||||
@@ -982,10 +939,6 @@ public class UserManagerService extends IUserManager.Stub {
|
|||||||
iconPath = parser.getAttributeValue(null, ATTR_ICON_PATH);
|
iconPath = parser.getAttributeValue(null, ATTR_ICON_PATH);
|
||||||
creationTime = readLongAttribute(parser, ATTR_CREATION_TIME, 0);
|
creationTime = readLongAttribute(parser, ATTR_CREATION_TIME, 0);
|
||||||
lastLoggedInTime = readLongAttribute(parser, ATTR_LAST_LOGGED_IN_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,
|
profileGroupId = readIntAttribute(parser, ATTR_PROFILE_GROUP_ID,
|
||||||
UserInfo.NO_PROFILE_GROUP_ID);
|
UserInfo.NO_PROFILE_GROUP_ID);
|
||||||
String valueString = parser.getAttributeValue(null, ATTR_PARTIAL);
|
String valueString = parser.getAttributeValue(null, ATTR_PARTIAL);
|
||||||
@@ -1023,17 +976,6 @@ public class UserManagerService extends IUserManager.Stub {
|
|||||||
userInfo.guestToRemove = guestToRemove;
|
userInfo.guestToRemove = guestToRemove;
|
||||||
userInfo.profileGroupId = profileGroupId;
|
userInfo.profileGroupId = profileGroupId;
|
||||||
mUserRestrictions.append(id, restrictions);
|
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;
|
return userInfo;
|
||||||
|
|
||||||
} catch (IOException ioe) {
|
} catch (IOException ioe) {
|
||||||
@@ -1435,8 +1377,6 @@ public class UserManagerService extends IUserManager.Stub {
|
|||||||
|
|
||||||
// Remove this user from the list
|
// Remove this user from the list
|
||||||
mUsers.remove(userHandle);
|
mUsers.remove(userHandle);
|
||||||
|
|
||||||
mRestrictionsPinStates.remove(userHandle);
|
|
||||||
// Remove user file
|
// Remove user file
|
||||||
AtomicFile userFile = new AtomicFile(new File(mUsersDir, userHandle + XML_SUFFIX));
|
AtomicFile userFile = new AtomicFile(new File(mUsersDir, userHandle + XML_SUFFIX));
|
||||||
userFile.delete();
|
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
|
@Override
|
||||||
public void removeRestrictions() {
|
public void removeRestrictions() {
|
||||||
checkManageUsersPermission("Only system can remove restrictions");
|
checkManageUsersPermission("Only system can remove restrictions");
|
||||||
@@ -1604,8 +1458,6 @@ public class UserManagerService extends IUserManager.Stub {
|
|||||||
synchronized (mPackagesLock) {
|
synchronized (mPackagesLock) {
|
||||||
// Remove all user restrictions
|
// Remove all user restrictions
|
||||||
setUserRestrictions(new Bundle(), userHandle);
|
setUserRestrictions(new Bundle(), userHandle);
|
||||||
// Remove restrictions pin
|
|
||||||
setRestrictionsChallenge(null);
|
|
||||||
// Remove any app restrictions
|
// Remove any app restrictions
|
||||||
cleanAppRestrictions(userHandle);
|
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) {
|
private int getUidForPackage(String packageName) {
|
||||||
long ident = Binder.clearCallingIdentity();
|
long ident = Binder.clearCallingIdentity();
|
||||||
try {
|
try {
|
||||||
@@ -1958,11 +1774,6 @@ public class UserManagerService extends IUserManager.Stub {
|
|||||||
return RESTRICTIONS_FILE_PREFIX + packageName + XML_SUFFIX;
|
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
|
@Override
|
||||||
protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
|
protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
|
||||||
if (mContext.checkCallingOrSelfPermission(android.Manifest.permission.DUMP)
|
if (mContext.checkCallingOrSelfPermission(android.Manifest.permission.DUMP)
|
||||||
|
|||||||
Reference in New Issue
Block a user