Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit e7beedff authored by Rubin Xu's avatar Rubin Xu Committed by Android (Google) Code Review
Browse files

Merge "Add unit tests for LockSettingsService"

parents b3e31004 0cbc19e4
Loading
Loading
Loading
Loading
+28 −20
Original line number Diff line number Diff line
@@ -19,6 +19,8 @@ package android.service.gatekeeper;
import android.os.Parcel;
import android.os.Parcelable;

import com.android.internal.annotations.VisibleForTesting;

/**
 * Response object for a GateKeeper verification request.
 * @hide
@@ -35,12 +37,28 @@ public final class GateKeeperResponse implements Parcelable {
    private byte[] mPayload;
    private boolean mShouldReEnroll;

    /** Default constructor for response with generic response code **/
    private GateKeeperResponse(int responseCode) {
        mResponseCode = responseCode;
    }

    private GateKeeperResponse(int responseCode, int timeout) {
        mResponseCode = responseCode;
    @VisibleForTesting
    public static GateKeeperResponse createGenericResponse(int responseCode) {
        return new GateKeeperResponse(responseCode);
    }

    private static GateKeeperResponse createRetryResponse(int timeout) {
        GateKeeperResponse response = new GateKeeperResponse(RESPONSE_RETRY);
        response.mTimeout = timeout;
        return response;
    }

    @VisibleForTesting
    public static GateKeeperResponse createOkResponse(byte[] payload, boolean shouldReEnroll) {
        GateKeeperResponse response = new GateKeeperResponse(RESPONSE_OK);
        response.mPayload = payload;
        response.mShouldReEnroll = shouldReEnroll;
        return response;
    }

    @Override
@@ -53,17 +71,20 @@ public final class GateKeeperResponse implements Parcelable {
        @Override
        public GateKeeperResponse createFromParcel(Parcel source) {
            int responseCode = source.readInt();
            GateKeeperResponse response = new GateKeeperResponse(responseCode);
            final GateKeeperResponse response;
            if (responseCode == RESPONSE_RETRY) {
                response.setTimeout(source.readInt());
                response = createRetryResponse(source.readInt());
            } else if (responseCode == RESPONSE_OK) {
                response.setShouldReEnroll(source.readInt() == 1);
                final boolean shouldReEnroll = source.readInt() == 1;
                byte[] payload = null;
                int size = source.readInt();
                if (size > 0) {
                    byte[] payload = new byte[size];
                    payload = new byte[size];
                    source.readByteArray(payload);
                    response.setPayload(payload);
                }
                response = createOkResponse(payload, shouldReEnroll);
            } else {
                response = createGenericResponse(responseCode);
            }
            return response;
        }
@@ -104,17 +125,4 @@ public final class GateKeeperResponse implements Parcelable {
    public int getResponseCode() {
        return mResponseCode;
    }

    private void setTimeout(int timeout) {
        mTimeout = timeout;
    }

    private void setShouldReEnroll(boolean shouldReEnroll) {
        mShouldReEnroll = shouldReEnroll;
    }

    private void setPayload(byte[] payload) {
        mPayload = payload;
    }

}
+3 −1
Original line number Diff line number Diff line
@@ -43,6 +43,7 @@ import android.text.TextUtils;
import android.util.Log;
import android.util.SparseIntArray;

import com.android.internal.annotations.VisibleForTesting;
import com.google.android.collect.Lists;

import libcore.util.HexEncoding;
@@ -239,7 +240,8 @@ public class LockPatternUtils {
        mHandler = looper != null ? new Handler(looper) : null;
    }

    private ILockSettings getLockSettings() {
    @VisibleForTesting
    public ILockSettings getLockSettings() {
        if (mLockSettingsService == null) {
            ILockSettings service = ILockSettings.Stub.asInterface(
                    ServiceManager.getService("lock_settings"));
+115 −49
Original line number Diff line number Diff line
@@ -23,6 +23,7 @@ import static com.android.internal.widget.LockPatternUtils.StrongAuthTracker.STR

import android.annotation.UserIdInt;
import android.app.ActivityManager;
import android.app.IActivityManager;
import android.app.KeyguardManager;
import android.app.Notification;
import android.app.NotificationManager;
@@ -70,6 +71,7 @@ import android.text.TextUtils;
import android.util.Log;
import android.util.Slog;

import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.util.ArrayUtils;
import com.android.internal.widget.ICheckCredentialProgressCallback;
import com.android.internal.widget.ILockSettings;
@@ -123,20 +125,23 @@ public class LockSettingsService extends ILockSettings.Stub {

    private final Object mSeparateChallengeLock = new Object();

    private final Injector mInjector;
    private final Context mContext;
    private final Handler mHandler;
    private final LockSettingsStorage mStorage;
    @VisibleForTesting
    protected final LockSettingsStorage mStorage;
    private final LockSettingsStrongAuth mStrongAuth;
    private final SynchronizedStrongAuthTracker mStrongAuthTracker;

    private LockPatternUtils mLockPatternUtils;
    private boolean mFirstCallToVold;
    private IGateKeeperService mGateKeeperService;
    private NotificationManager mNotificationManager;
    private UserManager mUserManager;
    private final LockPatternUtils mLockPatternUtils;
    private final NotificationManager mNotificationManager;
    private final UserManager mUserManager;
    private final IActivityManager mActivityManager;

    private final KeyStore mKeyStore = KeyStore.getInstance();
    private final KeyStore mKeyStore;

    private boolean mFirstCallToVold;
    protected IGateKeeperService mGateKeeperService;
    /**
     * The UIDs that are used for system credential storage in keystore.
     */
@@ -177,7 +182,9 @@ public class LockSettingsService extends ILockSettings.Stub {
        }
    }

    private class SynchronizedStrongAuthTracker extends LockPatternUtils.StrongAuthTracker {
    @VisibleForTesting
    protected static class SynchronizedStrongAuthTracker
            extends LockPatternUtils.StrongAuthTracker {
        public SynchronizedStrongAuthTracker(Context context) {
            super(context);
        }
@@ -196,8 +203,8 @@ public class LockSettingsService extends ILockSettings.Stub {
            }
        }

        void register() {
            mStrongAuth.registerStrongAuthTracker(this.mStub);
        void register(LockSettingsStrongAuth strongAuth) {
            strongAuth.registerStrongAuthTracker(this.mStub);
        }
    }

@@ -211,7 +218,7 @@ public class LockSettingsService extends ILockSettings.Stub {
    public void tieManagedProfileLockIfNecessary(int managedUserId, String managedUserPassword) {
        if (DEBUG) Slog.v(TAG, "Check child profile lock for user: " + managedUserId);
        // Only for managed profile
        if (!UserManager.get(mContext).getUserInfo(managedUserId).isManagedProfile()) {
        if (!mUserManager.getUserInfo(managedUserId).isManagedProfile()) {
            return;
        }
        // Do not tie managed profile when work challenge is enabled
@@ -258,38 +265,103 @@ public class LockSettingsService extends ILockSettings.Stub {
        }
    }

    public LockSettingsService(Context context) {
    static class Injector {

        protected Context mContext;

        public Injector(Context context) {
            mContext = context;
        mHandler = new Handler();
        mStrongAuth = new LockSettingsStrongAuth(context);
        // Open the database
        }

        mLockPatternUtils = new LockPatternUtils(context);
        mFirstCallToVold = true;
        public Context getContext() {
            return mContext;
        }

        IntentFilter filter = new IntentFilter();
        filter.addAction(Intent.ACTION_USER_ADDED);
        filter.addAction(Intent.ACTION_USER_STARTING);
        filter.addAction(Intent.ACTION_USER_REMOVED);
        mContext.registerReceiverAsUser(mBroadcastReceiver, UserHandle.ALL, filter, null, null);
        public Handler getHandler() {
            return new Handler();
        }

        mStorage = new LockSettingsStorage(context, new LockSettingsStorage.Callback() {
        public LockSettingsStorage getStorage() {
            final LockSettingsStorage storage = new LockSettingsStorage(mContext);
            storage.setDatabaseOnCreateCallback(new LockSettingsStorage.Callback() {
                @Override
                public void initialize(SQLiteDatabase db) {
                    // Get the lockscreen default from a system property, if available
                    boolean lockScreenDisable = SystemProperties.getBoolean(
                            "ro.lockscreen.disable.default", false);
                    if (lockScreenDisable) {
                    mStorage.writeKeyValue(db, LockPatternUtils.DISABLE_LOCKSCREEN_KEY, "1", 0);
                        storage.writeKeyValue(db, LockPatternUtils.DISABLE_LOCKSCREEN_KEY, "1", 0);
                    }
                }
            });
        mNotificationManager = (NotificationManager)
                mContext.getSystemService(Context.NOTIFICATION_SERVICE);
        mUserManager = (UserManager) mContext.getSystemService(Context.USER_SERVICE);
        mStrongAuthTracker = new SynchronizedStrongAuthTracker(mContext);
        mStrongAuthTracker.register();
            return storage;
        }

        public LockSettingsStrongAuth getStrongAuth() {
            return new LockSettingsStrongAuth(mContext);
        }

        public SynchronizedStrongAuthTracker getStrongAuthTracker() {
            return new SynchronizedStrongAuthTracker(mContext);
        }

        public IActivityManager getActivityManager() {
            return ActivityManager.getService();
        }

        public LockPatternUtils getLockPatternUtils() {
            return new LockPatternUtils(mContext);
        }

        public NotificationManager getNotificationManager() {
            return (NotificationManager) mContext.getSystemService(Context.NOTIFICATION_SERVICE);
        }

        public UserManager getUserManager() {
            return (UserManager) mContext.getSystemService(Context.USER_SERVICE);
        }

        public KeyStore getKeyStore() {
            return KeyStore.getInstance();
        }

        public IStorageManager getStorageManager() {
            final IBinder service = ServiceManager.getService("mount");
            if (service != null) {
                return IStorageManager.Stub.asInterface(service);
            }
            return null;
        }
    }

    public LockSettingsService(Context context) {
        this(new Injector(context));
    }

    @VisibleForTesting
    protected LockSettingsService(Injector injector) {
        mInjector = injector;
        mContext = injector.getContext();
        mKeyStore = injector.getKeyStore();
        mHandler = injector.getHandler();
        mStrongAuth = injector.getStrongAuth();
        mActivityManager = injector.getActivityManager();

        mLockPatternUtils = injector.getLockPatternUtils();
        mFirstCallToVold = true;

        IntentFilter filter = new IntentFilter();
        filter.addAction(Intent.ACTION_USER_ADDED);
        filter.addAction(Intent.ACTION_USER_STARTING);
        filter.addAction(Intent.ACTION_USER_REMOVED);
        injector.getContext().registerReceiverAsUser(mBroadcastReceiver, UserHandle.ALL, filter,
                null, null);

        mStorage = injector.getStorage();
        mNotificationManager = injector.getNotificationManager();
        mUserManager = injector.getUserManager();
        mStrongAuthTracker = injector.getStrongAuthTracker();
        mStrongAuthTracker.register(mStrongAuth);
    }

    /**
@@ -748,7 +820,8 @@ public class LockSettingsService extends ILockSettings.Stub {
        ks.unlock(userHandle, password);
    }

    private String getDecryptedPasswordForTiedProfile(int userId)
    @VisibleForTesting
    protected String getDecryptedPasswordForTiedProfile(int userId)
            throws KeyStoreException, UnrecoverableKeyException,
            NoSuchAlgorithmException, NoSuchPaddingException, InvalidKeyException,
            InvalidAlgorithmParameterException, IllegalBlockSizeException, BadPaddingException,
@@ -814,7 +887,7 @@ public class LockSettingsService extends ILockSettings.Stub {
        };

        try {
            ActivityManager.getService().unlockUser(userId, token, secret, listener);
            mActivityManager.unlockUser(userId, token, secret, listener);
        } catch (RemoteException e) {
            throw e.rethrowAsRuntimeException();
        }
@@ -961,7 +1034,8 @@ public class LockSettingsService extends ILockSettings.Stub {
        }
    }

    private void tieProfileLockToParent(int userId, String password) {
    @VisibleForTesting
    protected void tieProfileLockToParent(int userId, String password) {
        if (DEBUG) Slog.v(TAG, "tieProfileLockToParent for user: " + userId);
        byte[] randomLockSeed = password.getBytes(StandardCharsets.UTF_8);
        byte[] encryptionResult;
@@ -1085,8 +1159,8 @@ public class LockSettingsService extends ILockSettings.Stub {

    private void addUserKeyAuth(int userId, byte[] token, byte[] secret)
            throws RemoteException {
        final UserInfo userInfo = UserManager.get(mContext).getUserInfo(userId);
        final IStorageManager storageManager = getStorageManager();
        final UserInfo userInfo = mUserManager.getUserInfo(userId);
        final IStorageManager storageManager = mInjector.getStorageManager();
        final long callingId = Binder.clearCallingIdentity();
        try {
            storageManager.addUserKeyAuth(userId, userInfo.serialNumber, token, secret);
@@ -1097,7 +1171,7 @@ public class LockSettingsService extends ILockSettings.Stub {

    private void fixateNewestUserKeyAuth(int userId)
            throws RemoteException {
        final IStorageManager storageManager = getStorageManager();
        final IStorageManager storageManager = mInjector.getStorageManager();
        final long callingId = Binder.clearCallingIdentity();
        try {
            storageManager.fixateNewestUserKeyAuth(userId);
@@ -1396,7 +1470,7 @@ public class LockSettingsService extends ILockSettings.Stub {
        // 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 IStorageManager service = getStorageManager();
        final IStorageManager service = mInjector.getStorageManager();
        String password;
        long identity = Binder.clearCallingIdentity();
        try {
@@ -1561,14 +1635,6 @@ public class LockSettingsService extends ILockSettings.Stub {
            Secure.LOCK_SCREEN_OWNER_INFO
    };

    private IStorageManager getStorageManager() {
        final IBinder service = ServiceManager.getService("mount");
        if (service != null) {
            return IStorageManager.Stub.asInterface(service);
        }
        return null;
    }

    private class GateKeeperDiedRecipient implements IBinder.DeathRecipient {
        @Override
        public void binderDied() {
+2 −1
Original line number Diff line number Diff line
@@ -77,7 +77,8 @@ class LockSettingsShellCommand extends ShellCommand {
            }
            return 0;
        } catch (Exception e) {
            getErrPrintWriter().println("Error while executing command: " + e);
            getErrPrintWriter().println("Error while executing command: " + cmd);
            e.printStackTrace(getErrPrintWriter());
            return -1;
        }
    }
+14 −5
Original line number Diff line number Diff line
@@ -119,9 +119,13 @@ class LockSettingsStorage {
        boolean isBaseZeroPattern;
    }

    public LockSettingsStorage(Context context, Callback callback) {
    public LockSettingsStorage(Context context) {
        mContext = context;
        mOpenHelper = new DatabaseHelper(context, callback);
        mOpenHelper = new DatabaseHelper(context);
    }

    public void setDatabaseOnCreateCallback(Callback callback) {
        mOpenHelper.setCallback(callback);
    }

    public void writeKeyValue(String key, String value, int userId) {
@@ -472,11 +476,14 @@ class LockSettingsStorage {

        private static final int DATABASE_VERSION = 2;

        private final Callback mCallback;
        private Callback mCallback;

        public DatabaseHelper(Context context, Callback callback) {
        public DatabaseHelper(Context context) {
            super(context, DATABASE_NAME, null, DATABASE_VERSION);
            setWriteAheadLoggingEnabled(true);
        }

        public void setCallback(Callback callback) {
            mCallback = callback;
        }

@@ -492,8 +499,10 @@ class LockSettingsStorage {
        @Override
        public void onCreate(SQLiteDatabase db) {
            createTable(db);
            if (mCallback != null) {
                mCallback.initialize(db);
            }
        }

        @Override
        public void onUpgrade(SQLiteDatabase db, int oldVersion, int currentVersion) {
Loading