[4/n] FRR data cleanup

Add logic to delete data when removing a user.

Bug: 258872351
Test: AuthenticationStatsPersisterTest
Change-Id: I5f89ffbeeb0f01fbaffe22e7a372d05a6e22093d
This commit is contained in:
Wenhui Yang
2023-08-07 17:19:33 +00:00
parent 0c596f11e2
commit f37c7ec77f
3 changed files with 59 additions and 0 deletions

View File

@@ -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.

View File

@@ -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.
*/

View File

@@ -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) {