Merge "Don't double prompt on booting encrypted device"
This commit is contained in:
committed by
Android (Google) Code Review
commit
df42723d6b
@@ -694,6 +694,36 @@ public interface IMountService extends IInterface {
|
|||||||
return _result;
|
return _result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public String getPassword() throws RemoteException {
|
||||||
|
Parcel _data = Parcel.obtain();
|
||||||
|
Parcel _reply = Parcel.obtain();
|
||||||
|
String _result;
|
||||||
|
try {
|
||||||
|
_data.writeInterfaceToken(DESCRIPTOR);
|
||||||
|
mRemote.transact(Stub.TRANSACTION_getPassword, _data, _reply, 0);
|
||||||
|
_reply.readException();
|
||||||
|
_result = _reply.readString();
|
||||||
|
} finally {
|
||||||
|
_reply.recycle();
|
||||||
|
_data.recycle();
|
||||||
|
}
|
||||||
|
return _result;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void clearPassword() throws RemoteException {
|
||||||
|
Parcel _data = Parcel.obtain();
|
||||||
|
Parcel _reply = Parcel.obtain();
|
||||||
|
String _result;
|
||||||
|
try {
|
||||||
|
_data.writeInterfaceToken(DESCRIPTOR);
|
||||||
|
mRemote.transact(Stub.TRANSACTION_clearPassword, _data, _reply, 0);
|
||||||
|
_reply.readException();
|
||||||
|
} finally {
|
||||||
|
_reply.recycle();
|
||||||
|
_data.recycle();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public StorageVolume[] getVolumeList() throws RemoteException {
|
public StorageVolume[] getVolumeList() throws RemoteException {
|
||||||
Parcel _data = Parcel.obtain();
|
Parcel _data = Parcel.obtain();
|
||||||
Parcel _reply = Parcel.obtain();
|
Parcel _reply = Parcel.obtain();
|
||||||
@@ -846,7 +876,11 @@ public interface IMountService extends IInterface {
|
|||||||
|
|
||||||
static final int TRANSACTION_mkdirs = IBinder.FIRST_CALL_TRANSACTION + 34;
|
static final int TRANSACTION_mkdirs = IBinder.FIRST_CALL_TRANSACTION + 34;
|
||||||
|
|
||||||
static final int TRANSACTION_getPasswordType = IBinder.FIRST_CALL_TRANSACTION + 36;
|
static final int TRANSACTION_getPasswordType = IBinder.FIRST_CALL_TRANSACTION + 35;
|
||||||
|
|
||||||
|
static final int TRANSACTION_getPassword = IBinder.FIRST_CALL_TRANSACTION + 36;
|
||||||
|
|
||||||
|
static final int TRANSACTION_clearPassword = IBinder.FIRST_CALL_TRANSACTION + 37;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Cast an IBinder object into an IMountService interface, generating a
|
* Cast an IBinder object into an IMountService interface, generating a
|
||||||
@@ -1208,6 +1242,19 @@ public interface IMountService extends IInterface {
|
|||||||
reply.writeInt(result);
|
reply.writeInt(result);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
case TRANSACTION_getPassword: {
|
||||||
|
data.enforceInterface(DESCRIPTOR);
|
||||||
|
String result = getPassword();
|
||||||
|
reply.writeNoException();
|
||||||
|
reply.writeString(result);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
case TRANSACTION_clearPassword: {
|
||||||
|
data.enforceInterface(DESCRIPTOR);
|
||||||
|
clearPassword();
|
||||||
|
reply.writeNoException();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return super.onTransact(code, data, reply, flags);
|
return super.onTransact(code, data, reply, flags);
|
||||||
}
|
}
|
||||||
@@ -1446,4 +1493,15 @@ public interface IMountService extends IInterface {
|
|||||||
* @return PasswordType
|
* @return PasswordType
|
||||||
*/
|
*/
|
||||||
public int getPasswordType() throws RemoteException;
|
public int getPasswordType() throws RemoteException;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get password from vold
|
||||||
|
* @return password or empty string
|
||||||
|
*/
|
||||||
|
public String getPassword() throws RemoteException;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Securely clear password from vold
|
||||||
|
*/
|
||||||
|
public void clearPassword() throws RemoteException;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -28,6 +28,7 @@ interface ILockSettings {
|
|||||||
boolean checkPattern(in String pattern, int userId);
|
boolean checkPattern(in String pattern, int userId);
|
||||||
void setLockPassword(in String password, int userId);
|
void setLockPassword(in String password, int userId);
|
||||||
boolean checkPassword(in String password, int userId);
|
boolean checkPassword(in String password, int userId);
|
||||||
|
boolean checkVoldPassword(int userId);
|
||||||
boolean havePattern(int userId);
|
boolean havePattern(int userId);
|
||||||
boolean havePassword(int userId);
|
boolean havePassword(int userId);
|
||||||
void removeUser(int userId);
|
void removeUser(int userId);
|
||||||
|
|||||||
@@ -332,6 +332,20 @@ public class LockPatternUtils {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Check to see if vold already has the password.
|
||||||
|
* Note that this also clears vold's copy of the password.
|
||||||
|
* @return Whether the vold password matches or not.
|
||||||
|
*/
|
||||||
|
public boolean checkVoldPassword() {
|
||||||
|
final int userId = getCurrentOrCallingUserId();
|
||||||
|
try {
|
||||||
|
return getLockSettings().checkVoldPassword(userId);
|
||||||
|
} catch (RemoteException re) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Check to see if a password matches any of the passwords stored in the
|
* Check to see if a password matches any of the passwords stored in the
|
||||||
* password history.
|
* password history.
|
||||||
|
|||||||
@@ -981,6 +981,13 @@ public class KeyguardViewMediator {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (mLockPatternUtils.checkVoldPassword()) {
|
||||||
|
if (DEBUG) Log.d(TAG, "Not showing lock screen since just decrypted");
|
||||||
|
// Without this, settings is not enabled until the lock screen first appears
|
||||||
|
hideLocked();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
if (DEBUG) Log.d(TAG, "doKeyguard: showing the lock screen");
|
if (DEBUG) Log.d(TAG, "doKeyguard: showing the lock screen");
|
||||||
showLocked(options);
|
showLocked(options);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -30,7 +30,11 @@ import android.database.sqlite.SQLiteOpenHelper;
|
|||||||
import android.database.sqlite.SQLiteStatement;
|
import android.database.sqlite.SQLiteStatement;
|
||||||
import android.os.Binder;
|
import android.os.Binder;
|
||||||
import android.os.Environment;
|
import android.os.Environment;
|
||||||
|
import android.os.IBinder;
|
||||||
import android.os.RemoteException;
|
import android.os.RemoteException;
|
||||||
|
import android.os.storage.IMountService;
|
||||||
|
import android.os.ServiceManager;
|
||||||
|
import android.os.storage.StorageManager;
|
||||||
import android.os.SystemProperties;
|
import android.os.SystemProperties;
|
||||||
import android.os.UserHandle;
|
import android.os.UserHandle;
|
||||||
import android.os.UserManager;
|
import android.os.UserManager;
|
||||||
@@ -79,6 +83,7 @@ public class LockSettingsService extends ILockSettings.Stub {
|
|||||||
|
|
||||||
private final Context mContext;
|
private final Context mContext;
|
||||||
private LockPatternUtils mLockPatternUtils;
|
private LockPatternUtils mLockPatternUtils;
|
||||||
|
private boolean mFirstCallToVold;
|
||||||
|
|
||||||
public LockSettingsService(Context context) {
|
public LockSettingsService(Context context) {
|
||||||
mContext = context;
|
mContext = context;
|
||||||
@@ -86,6 +91,7 @@ public class LockSettingsService extends ILockSettings.Stub {
|
|||||||
mOpenHelper = new DatabaseHelper(mContext);
|
mOpenHelper = new DatabaseHelper(mContext);
|
||||||
|
|
||||||
mLockPatternUtils = new LockPatternUtils(context);
|
mLockPatternUtils = new LockPatternUtils(context);
|
||||||
|
mFirstCallToVold = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void systemReady() {
|
public void systemReady() {
|
||||||
@@ -346,6 +352,51 @@ public class LockSettingsService extends ILockSettings.Stub {
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean checkVoldPassword(int userId) throws RemoteException {
|
||||||
|
if (!mFirstCallToVold) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
mFirstCallToVold = false;
|
||||||
|
|
||||||
|
checkPasswordReadPermission(userId);
|
||||||
|
|
||||||
|
// There's no guarantee that this will safely connect, but if it fails
|
||||||
|
// we will simply show the lock screen when we shouldn't, so relatively
|
||||||
|
// benign. There is an outside chance something nasty would happen if
|
||||||
|
// this service restarted before vold stales out the password in this
|
||||||
|
// case. The nastiness is limited to not showing the lock screen when
|
||||||
|
// we should, within the first minute of decrypting the phone if this
|
||||||
|
// service can't connect to vold, it restarts, and then the new instance
|
||||||
|
// does successfully connect.
|
||||||
|
final IMountService service = getMountService();
|
||||||
|
String password = service.getPassword();
|
||||||
|
service.clearPassword();
|
||||||
|
if (password == null) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
if (mLockPatternUtils.isLockPatternEnabled()) {
|
||||||
|
if (checkPattern(password, userId)) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} catch (Exception e) {
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
if (mLockPatternUtils.isLockPasswordEnabled()) {
|
||||||
|
if (checkPassword(password, userId)) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} catch (Exception e) {
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void removeUser(int userId) {
|
public void removeUser(int userId) {
|
||||||
checkWritePermission(userId);
|
checkWritePermission(userId);
|
||||||
@@ -524,4 +575,12 @@ public class LockSettingsService extends ILockSettings.Stub {
|
|||||||
Secure.LOCK_SCREEN_OWNER_INFO_ENABLED,
|
Secure.LOCK_SCREEN_OWNER_INFO_ENABLED,
|
||||||
Secure.LOCK_SCREEN_OWNER_INFO
|
Secure.LOCK_SCREEN_OWNER_INFO
|
||||||
};
|
};
|
||||||
|
|
||||||
|
private IMountService getMountService() {
|
||||||
|
final IBinder service = ServiceManager.getService("mount");
|
||||||
|
if (service != null) {
|
||||||
|
return IMountService.Stub.asInterface(service);
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -74,6 +74,7 @@ import com.google.android.collect.Lists;
|
|||||||
import com.google.android.collect.Maps;
|
import com.google.android.collect.Maps;
|
||||||
|
|
||||||
import org.apache.commons.codec.binary.Hex;
|
import org.apache.commons.codec.binary.Hex;
|
||||||
|
import org.apache.commons.codec.DecoderException;
|
||||||
import org.xmlpull.v1.XmlPullParserException;
|
import org.xmlpull.v1.XmlPullParserException;
|
||||||
|
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
@@ -573,6 +574,14 @@ class MountService extends IMountService.Stub
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private boolean isReady() {
|
||||||
|
try {
|
||||||
|
return mConnectedSignal.await(0, TimeUnit.MILLISECONDS);
|
||||||
|
} catch (InterruptedException e) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private void handleSystemReady() {
|
private void handleSystemReady() {
|
||||||
// Snapshot current volume states since it's not safe to call into vold
|
// Snapshot current volume states since it's not safe to call into vold
|
||||||
// while holding locks.
|
// while holding locks.
|
||||||
@@ -2075,12 +2084,25 @@ class MountService extends IMountService.Stub
|
|||||||
|
|
||||||
private String toHex(String password) {
|
private String toHex(String password) {
|
||||||
if (password == null) {
|
if (password == null) {
|
||||||
return null;
|
return new String();
|
||||||
}
|
}
|
||||||
byte[] bytes = password.getBytes(StandardCharsets.UTF_8);
|
byte[] bytes = password.getBytes(StandardCharsets.UTF_8);
|
||||||
return new String(Hex.encodeHex(bytes));
|
return new String(Hex.encodeHex(bytes));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private String fromHex(String hexPassword) {
|
||||||
|
if (hexPassword == null) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
byte[] bytes = Hex.decodeHex(hexPassword.toCharArray());
|
||||||
|
return new String(bytes, StandardCharsets.UTF_8);
|
||||||
|
} catch (DecoderException e) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int decryptStorage(String password) {
|
public int decryptStorage(String password) {
|
||||||
if (TextUtils.isEmpty(password)) {
|
if (TextUtils.isEmpty(password)) {
|
||||||
@@ -2229,6 +2251,35 @@ class MountService extends IMountService.Stub
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getPassword() throws RemoteException {
|
||||||
|
if (!isReady()) {
|
||||||
|
return new String();
|
||||||
|
}
|
||||||
|
|
||||||
|
final NativeDaemonEvent event;
|
||||||
|
try {
|
||||||
|
event = mConnector.execute("cryptfs", "getpw");
|
||||||
|
return fromHex(event.getMessage());
|
||||||
|
} catch (NativeDaemonConnectorException e) {
|
||||||
|
throw e.rethrowAsParcelableException();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void clearPassword() throws RemoteException {
|
||||||
|
if (!isReady()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
final NativeDaemonEvent event;
|
||||||
|
try {
|
||||||
|
event = mConnector.execute("cryptfs", "clearpw");
|
||||||
|
} catch (NativeDaemonConnectorException e) {
|
||||||
|
throw e.rethrowAsParcelableException();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int mkdirs(String callingPkg, String appPath) {
|
public int mkdirs(String callingPkg, String appPath) {
|
||||||
final int userId = UserHandle.getUserId(Binder.getCallingUid());
|
final int userId = UserHandle.getUserId(Binder.getCallingUid());
|
||||||
|
|||||||
Reference in New Issue
Block a user