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

Commit fabb749d authored by Lee Shombert's avatar Lee Shombert
Browse files

Add a binder cache to ILockSettings#getCredentialType

Bug: 214623625

Put a binder cache in front of ILockSettings#getCredentialType().  The
cache is in LockPatternUtils and the invalidation logic is in
LogSettingsService.  The cache is invalidated whenever the
LockSettingsStorage changes.

Three unit tests disable caches because they do not have permission to
write to the system properties.

Test: atest com.android.server.locksettings

Change-Id: Iea4c50ba5cc39de9196d9a9873ae501a946bf9fd
parent 7ad09828
Loading
Loading
Loading
Loading
+43 −6
Original line number Diff line number Diff line
@@ -26,6 +26,7 @@ import static android.app.admin.DevicePolicyManager.PASSWORD_QUALITY_UNSPECIFIED
import android.annotation.IntDef;
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.app.PropertyInvalidatedCache;
import android.app.admin.DevicePolicyManager;
import android.app.admin.PasswordMetrics;
import android.app.trust.IStrongAuthTracker;
@@ -916,11 +917,12 @@ public class LockPatternUtils {
    }

    /**
     * Returns the credential type of the user, can be one of {@link #CREDENTIAL_TYPE_NONE},
     * {@link #CREDENTIAL_TYPE_PATTERN}, {@link #CREDENTIAL_TYPE_PIN} and
     * {@link #CREDENTIAL_TYPE_PASSWORD}
     * Retrieve the credential type of a user.
     */
    public @CredentialType int getCredentialTypeForUser(int userHandle) {
    private final PropertyInvalidatedCache.QueryHandler<Integer, Integer> mCredentialTypeQuery =
            new PropertyInvalidatedCache.QueryHandler<>() {
                @Override
                public Integer apply(Integer userHandle) {
                    try {
                        return getLockSettings().getCredentialType(userHandle);
                    } catch (RemoteException re) {
@@ -928,6 +930,41 @@ public class LockPatternUtils {
                        return CREDENTIAL_TYPE_NONE;
                    }
                }
                @Override
                public boolean shouldBypassCache(Integer userHandle) {
                    return userHandle == USER_FRP;
                }
            };

    /**
     * The API that is cached.
     */
    private final static String CREDENTIAL_TYPE_API = "getCredentialType";

    /**
     * Cache the credential type of a user.
     */
    private final PropertyInvalidatedCache<Integer, Integer> mCredentialTypeCache =
            new PropertyInvalidatedCache<>(4, PropertyInvalidatedCache.MODULE_SYSTEM,
                    CREDENTIAL_TYPE_API, CREDENTIAL_TYPE_API, mCredentialTypeQuery);

    /**
     * Invalidate the credential cache
     * @hide
     */
    public final static void invalidateCredentialTypeCache() {
        PropertyInvalidatedCache.invalidateCache(PropertyInvalidatedCache.MODULE_SYSTEM,
                CREDENTIAL_TYPE_API);
    }

    /**
     * Returns the credential type of the user, can be one of {@link #CREDENTIAL_TYPE_NONE},
     * {@link #CREDENTIAL_TYPE_PATTERN}, {@link #CREDENTIAL_TYPE_PIN} and
     * {@link #CREDENTIAL_TYPE_PASSWORD}
     */
    public @CredentialType int getCredentialTypeForUser(int userHandle) {
        return mCredentialTypeCache.query(userHandle);
    }

    /**
     * @param userId the user for which to report the value
+24 −0
Original line number Diff line number Diff line
@@ -148,6 +148,8 @@ import com.android.server.locksettings.SyntheticPasswordManager.AuthenticationTo
import com.android.server.locksettings.SyntheticPasswordManager.TokenType;
import com.android.server.locksettings.recoverablekeystore.RecoverableKeyStoreManager;
import com.android.server.pm.UserManagerInternal;
import com.android.server.utils.Watchable;
import com.android.server.utils.Watcher;
import com.android.server.wm.WindowManagerInternal;

import libcore.util.HexEncoding;
@@ -229,6 +231,7 @@ public class LockSettingsService extends ILockSettings.Stub {
    protected final Handler mHandler;
    @VisibleForTesting
    protected final LockSettingsStorage mStorage;
    private final Watcher mStorageWatcher;
    private final LockSettingsStrongAuth mStrongAuth;
    private final SynchronizedStrongAuthTracker mStrongAuthTracker;
    private final BiometricDeferredQueue mBiometricDeferredQueue;
@@ -569,6 +572,12 @@ public class LockSettingsService extends ILockSettings.Stub {
        }
    }

    private class StorageWatcher extends Watcher {
        public void onChange(Watchable what) {
            LockSettingsService.this.onChange();
        }
    }

    public LockSettingsService(Context context) {
        this(new Injector(context));
    }
@@ -610,6 +619,16 @@ public class LockSettingsService extends ILockSettings.Stub {
                mStorage);

        LocalServices.addService(LockSettingsInternal.class, new LocalService());

        mStorageWatcher = new StorageWatcher();
        mStorage.registerObserver(mStorageWatcher);
    }

    /**
     * Invalidate caches if the storage has changed.
     */
    private void onChange() {
        LockPatternUtils.invalidateCredentialTypeCache();
    }

    /**
@@ -1273,6 +1292,11 @@ public class LockSettingsService extends ILockSettings.Stub {
                DevicePolicyManager.PASSWORD_QUALITY_UNSPECIFIED, userId);
    }

    /**
     * This API is cached; whenever the result would change,
     * {@link com.android.internal.widget.LockPatternUtils#invalidateCredentialTypeCache}
     * must be called.
     */
    @Override
    public int getCredentialType(int userId) {
        checkPasswordHavePermission(userId);
+10 −3
Original line number Diff line number Diff line
@@ -47,6 +47,7 @@ import com.android.internal.widget.LockPatternUtils;
import com.android.internal.widget.LockPatternUtils.CredentialType;
import com.android.server.LocalServices;
import com.android.server.PersistentDataBlockManagerInternal;
import com.android.server.utils.WatchableImpl;

import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
@@ -66,7 +67,7 @@ import java.util.Map;
/**
 * Storage for the lock settings service.
 */
class LockSettingsStorage {
class LockSettingsStorage extends WatchableImpl {

    private static final String TAG = "LockSettingsStorage";
    private static final String TABLE = "locksettings";
@@ -173,7 +174,7 @@ class LockSettingsStorage {
        } finally {
            db.endTransaction();
        }

        dispatchChange(this);
    }

    @VisibleForTesting
@@ -221,7 +222,7 @@ class LockSettingsStorage {
        } finally {
            db.endTransaction();
        }

        dispatchChange(this);
    }

    public void prefetchUser(int userId) {
@@ -412,6 +413,7 @@ class LockSettingsStorage {
                }
            }
            mCache.putFile(name, hash);
            dispatchChange(this);
        }
    }

@@ -423,6 +425,7 @@ class LockSettingsStorage {
                file.delete();
                mCache.putFile(name, null);
            }
            dispatchChange(this);
        }
    }

@@ -500,6 +503,7 @@ class LockSettingsStorage {
                Slog.w(TAG, "Failed to zeroize " + path, e);
            } finally {
                file.delete();
                dispatchChange(this);
            }
            mCache.putFile(path, null);
        }
@@ -587,6 +591,7 @@ class LockSettingsStorage {
        } finally {
            db.endTransaction();
        }
        dispatchChange(this);
    }

    private void deleteFilesAndRemoveCache(String... names) {
@@ -595,6 +600,7 @@ class LockSettingsStorage {
            if (file.exists()) {
                file.delete();
                mCache.putFile(name, null);
                dispatchChange(this);
            }
        }
    }
@@ -675,6 +681,7 @@ class LockSettingsStorage {
        }
        persistentDataBlock.setFrpCredentialHandle(PersistentData.toBytes(
                persistentType, userId, qualityForUi, payload));
        dispatchChange(this);
    }

    public PersistentData readPersistentDataBlock() {
+7 −0
Original line number Diff line number Diff line
@@ -34,6 +34,7 @@ import static org.mockito.Mockito.never;
import static org.mockito.Mockito.reset;
import static org.mockito.Mockito.verify;

import android.app.PropertyInvalidatedCache;
import android.os.RemoteException;
import android.platform.test.annotations.Presubmit;
import android.service.gatekeeper.GateKeeperResponse;
@@ -47,6 +48,7 @@ import com.android.internal.widget.VerifyCredentialResponse;
import com.android.server.locksettings.FakeGateKeeperService.VerifyHandle;
import com.android.server.locksettings.LockSettingsStorage.CredentialHash;

import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;

@@ -57,6 +59,11 @@ import org.junit.runner.RunWith;
@Presubmit
@RunWith(AndroidJUnit4.class)
public class LockSettingsServiceTests extends BaseLockSettingsServiceTests {
    @Before
    public void disableProcessCaches() {
        PropertyInvalidatedCache.disableForTestMode();
    }

    @Test
    public void testCreatePasswordPrimaryUser() throws RemoteException {
        testCreateCredential(PRIMARY_USER_ID, newPassword("password"));
+6 −0
Original line number Diff line number Diff line
@@ -24,6 +24,7 @@ import static com.android.internal.widget.LockPatternUtils.USER_FRP;

import static org.junit.Assert.assertEquals;

import android.app.PropertyInvalidatedCache;
import android.app.admin.DevicePolicyManager;

import androidx.test.runner.AndroidJUnit4;
@@ -46,6 +47,11 @@ public class LockscreenFrpTest extends BaseLockSettingsServiceTests {
        mSettings.setDeviceProvisioned(false);
    }

    @Before
    public void disableProcessCaches() {
        PropertyInvalidatedCache.disableForTestMode();
    }

    @Test
    public void testFrpCredential_setPin() {
        mService.setLockCredential(newPin("1234"), nonePassword(), PRIMARY_USER_ID);
Loading