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

Commit f37c7ec7 authored by Wenhui Yang's avatar Wenhui Yang
Browse files

[4/n] FRR data cleanup

Add logic to delete data when removing a user.

Bug: 258872351
Test: AuthenticationStatsPersisterTest
Change-Id: I5f89ffbeeb0f01fbaffe22e7a372d05a6e22093d
parent 0c596f11
Loading
Loading
Loading
Loading
+22 −0
Original line number Diff line number Diff line
@@ -18,10 +18,14 @@ package com.android.server.biometrics;

import android.annotation.NonNull;
import android.annotation.Nullable;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.content.pm.PackageManager;
import android.hardware.face.FaceManager;
import android.hardware.fingerprint.FingerprintManager;
import android.os.UserHandle;

import com.android.internal.R;
import com.android.internal.annotations.VisibleForTesting;
@@ -56,6 +60,17 @@ public class AuthenticationStatsCollector {
    @NonNull private AuthenticationStatsPersister mAuthenticationStatsPersister;
    @NonNull private BiometricNotification mBiometricNotification;

    private final BroadcastReceiver mBroadcastReceiver = new BroadcastReceiver() {
        @Override
        public void onReceive(@NonNull Context context, @NonNull Intent intent) {
            final int userId = intent.getIntExtra(Intent.EXTRA_USER_HANDLE, UserHandle.USER_NULL);
            if (userId != UserHandle.USER_NULL
                    && intent.getAction().equals(Intent.ACTION_USER_REMOVED)) {
                onUserRemoved(userId);
            }
        }
    };

    public AuthenticationStatsCollector(@NonNull Context context, int modality,
            @NonNull BiometricNotification biometricNotification) {
        mContext = context;
@@ -64,6 +79,8 @@ public class AuthenticationStatsCollector {
        mUserAuthenticationStatsMap = new HashMap<>();
        mModality = modality;
        mBiometricNotification = biometricNotification;

        context.registerReceiver(mBroadcastReceiver, new IntentFilter(Intent.ACTION_USER_REMOVED));
    }

    private void initializeUserAuthenticationStatsMap() {
@@ -146,6 +163,11 @@ public class AuthenticationStatsCollector {
        }
    }

    private void onUserRemoved(final int userId) {
        mUserAuthenticationStatsMap.remove(userId);
        mAuthenticationStatsPersister.removeFrrStats(userId);
    }

    /**
     * Only being used in tests. Callers should not make any changes to the returned
     * authentication stats.
+23 −0
Original line number Diff line number Diff line
@@ -93,6 +93,29 @@ public class AuthenticationStatsPersister {
        return authenticationStatsList;
    }

    /**
     * Remove frr data for a specific user.
     */
    public void removeFrrStats(int userId) {
        try {
            // Copy into a new HashSet to avoid iterator exception.
            Set<String> frrStatsSet = new HashSet<>(readFrrStats());

            // Remove the old authentication stat for the user if it exists.
            for (Iterator<String> iterator = frrStatsSet.iterator(); iterator.hasNext();) {
                String frrStats = iterator.next();
                JSONObject frrStatJson = new JSONObject(frrStats);
                if (getValue(frrStatJson, USER_ID).equals(String.valueOf(userId))) {
                    iterator.remove();
                    break;
                }
            }

            mSharedPreferences.edit().putStringSet(KEY, frrStatsSet).apply();
        } catch (JSONException ignored) {
        }
    }

    /**
     * Persist frr data for a specific user.
     */
+14 −0
Original line number Diff line number Diff line
@@ -211,6 +211,20 @@ public class AuthenticationStatsPersisterTest {
        assertThat(mStringSetArgumentCaptor.getValue()).contains(expectedFrrStats);
    }

    @Test
    public void removeFrrStats_existingUser_shouldUpdateRecord() throws JSONException {
        AuthenticationStats authenticationStats = new AuthenticationStats(USER_ID_1,
                300 /* totalAttempts */, 10 /* rejectedAttempts */,
                0 /* enrollmentNotifications */, BiometricsProtoEnums.MODALITY_FACE);
        when(mSharedPreferences.getStringSet(eq(KEY), anySet())).thenReturn(
                Set.of(buildFrrStats(authenticationStats)));

        mAuthenticationStatsPersister.removeFrrStats(USER_ID_1);

        verify(mEditor).putStringSet(eq(KEY), mStringSetArgumentCaptor.capture());
        assertThat(mStringSetArgumentCaptor.getValue()).doesNotContain(authenticationStats);
    }

    private String buildFrrStats(AuthenticationStats authenticationStats)
            throws JSONException {
        if (authenticationStats.getModality() == BiometricsProtoEnums.MODALITY_FACE) {