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

Commit e85d5889 authored by lbill's avatar lbill
Browse files

Fix Settings crash on non face service support devices

Doing some improvement for stability:

1. Check hasSystemFeature(PackageManager.FEATURE_FACE) for non-face
   service devices.
2. Wrap addAuthenticatorsRegisteredCallback()
3. Find mPreference before addAuthenticatorsRegisteredCallback

Bug: 276680407
Bug: 278174667
Bug: 277647959
Bug: 277725506
Test: m RunSettingsRoboTests -j30 ROBOTEST_FILTER= \
      FaceSettingsFooterPreferenceControllerTest
Change-Id: I81346b6eb8c44106c5e52867d69c8736203dd558
parent ebb97daa
Loading
Loading
Loading
Loading
+29 −20
Original line number Original line Diff line number Diff line
@@ -18,6 +18,7 @@ package com.android.settings.biometrics.face;


import android.content.Context;
import android.content.Context;
import android.content.Intent;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.hardware.biometrics.SensorProperties;
import android.hardware.biometrics.SensorProperties;
import android.hardware.face.FaceManager;
import android.hardware.face.FaceManager;
import android.hardware.face.FaceSensorPropertiesInternal;
import android.hardware.face.FaceSensorPropertiesInternal;
@@ -49,32 +50,17 @@ public class FaceSettingsFooterPreferenceController extends BasePreferenceContro
    public FaceSettingsFooterPreferenceController(Context context, String preferenceKey) {
    public FaceSettingsFooterPreferenceController(Context context, String preferenceKey) {
        super(context, preferenceKey);
        super(context, preferenceKey);
        mProvider = FeatureFactory.getFactory(context).getFaceFeatureProvider();
        mProvider = FeatureFactory.getFactory(context).getFaceFeatureProvider();
        FaceManager faceManager = context.getSystemService(FaceManager.class);
        faceManager.addAuthenticatorsRegisteredCallback(
                new IFaceAuthenticatorsRegisteredCallback.Stub() {
                    @Override
                    public void onAllAuthenticatorsRegistered(
                            @NonNull List<FaceSensorPropertiesInternal> sensors) {
                        if (sensors.isEmpty()) {
                            Log.e(TAG, "No sensors");
                            return;
                        }

                        boolean isFaceStrong = sensors.get(0).sensorStrength
                                == SensorProperties.STRENGTH_STRONG;
                        if (mIsFaceStrong == isFaceStrong) {
                            return;
                        }
                        mIsFaceStrong = isFaceStrong;
                        updateState(mPreference);
                    }
                });
    }
    }


    @Override
    @Override
    public void displayPreference(PreferenceScreen screen) {
    public void displayPreference(PreferenceScreen screen) {
        super.displayPreference(screen);
        super.displayPreference(screen);
        mPreference = screen.findPreference(mPreferenceKey);
        mPreference = screen.findPreference(mPreferenceKey);
        if (screen.getContext().getPackageManager().hasSystemFeature(PackageManager.FEATURE_FACE)) {
            addAuthenticatorsRegisteredCallback(screen.getContext());
        } else {
            Log.w(TAG, "Not support FEATURE_FACE");
        }
    }
    }


    @Override
    @Override
@@ -105,4 +91,27 @@ public class FaceSettingsFooterPreferenceController extends BasePreferenceContro
        preference.setTitle(AnnotationSpan.linkify(
        preference.setTitle(AnnotationSpan.linkify(
                mContext.getText(footerRes), linkInfo));
                mContext.getText(footerRes), linkInfo));
    }
    }

    private void addAuthenticatorsRegisteredCallback(Context context) {
        final FaceManager faceManager = context.getSystemService(FaceManager.class);
        faceManager.addAuthenticatorsRegisteredCallback(
                new IFaceAuthenticatorsRegisteredCallback.Stub() {
                    @Override
                    public void onAllAuthenticatorsRegistered(
                            @NonNull List<FaceSensorPropertiesInternal> sensors) {
                        if (sensors.isEmpty()) {
                            Log.e(TAG, "No sensors");
                            return;
                        }

                        boolean isFaceStrong = sensors.get(0).sensorStrength
                                == SensorProperties.STRENGTH_STRONG;
                        if (mIsFaceStrong == isFaceStrong) {
                            return;
                        }
                        mIsFaceStrong = isFaceStrong;
                        updateState(mPreference);
                    }
                });
    }
}
}
+59 −1
Original line number Original line Diff line number Diff line
@@ -18,10 +18,14 @@ package com.android.settings.biometrics.face;


import static com.google.common.truth.Truth.assertThat;
import static com.google.common.truth.Truth.assertThat;


import static org.mockito.ArgumentMatchers.any;
import static org.mockito.Mockito.never;
import static org.mockito.Mockito.spy;
import static org.mockito.Mockito.spy;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;


import android.content.Context;
import android.content.Context;
import android.content.pm.PackageManager;
import android.hardware.face.FaceManager;
import android.hardware.face.FaceManager;
import android.hardware.face.FaceSensorProperties;
import android.hardware.face.FaceSensorProperties;
import android.hardware.face.FaceSensorPropertiesInternal;
import android.hardware.face.FaceSensorPropertiesInternal;
@@ -59,6 +63,8 @@ public class FaceSettingsFooterPreferenceControllerTest {
    private static final String PREF_KEY = "security_face_footer";
    private static final String PREF_KEY = "security_face_footer";
    @Mock
    @Mock
    private FaceManager mFaceManager;
    private FaceManager mFaceManager;
    @Mock
    PackageManager mPackageManager;
    @Captor
    @Captor
    private ArgumentCaptor<IFaceAuthenticatorsRegisteredCallback> mCaptor;
    private ArgumentCaptor<IFaceAuthenticatorsRegisteredCallback> mCaptor;
    private Preference mPreference;
    private Preference mPreference;
@@ -71,8 +77,20 @@ public class FaceSettingsFooterPreferenceControllerTest {
        if (Looper.myLooper() == null) {
        if (Looper.myLooper() == null) {
            Looper.prepare(); // needed to create the preference screen
            Looper.prepare(); // needed to create the preference screen
        }
        }
        ShadowApplication.getInstance().setSystemService(Context.FACE_SERVICE, mFaceManager);
        when(mContext.getPackageManager()).thenReturn(mPackageManager);
        when(mPackageManager.hasSystemFeature(PackageManager.FEATURE_FINGERPRINT)).thenReturn(true);
    }

    private void setupHasFaceFeature() {
        when(mPackageManager.hasSystemFeature(PackageManager.FEATURE_FACE)).thenReturn(true);
    }

    private void setupNoFaceFeature() {
        when(mPackageManager.hasSystemFeature(PackageManager.FEATURE_FACE)).thenReturn(false);
    }


    private void displayFaceSettingsFooterPreferenceController() {
        ShadowApplication.getInstance().setSystemService(Context.FACE_SERVICE, mFaceManager);
        mController = new FaceSettingsFooterPreferenceController(mContext, PREF_KEY);
        mController = new FaceSettingsFooterPreferenceController(mContext, PREF_KEY);
        PreferenceScreen screen = new PreferenceManager(mContext).createPreferenceScreen(mContext);
        PreferenceScreen screen = new PreferenceManager(mContext).createPreferenceScreen(mContext);
        mPreference = new FooterPreference(mContext);
        mPreference = new FooterPreference(mContext);
@@ -82,13 +100,24 @@ public class FaceSettingsFooterPreferenceControllerTest {
        mController.displayPreference(screen);
        mController.displayPreference(screen);
    }
    }


    private void createFaceSettingsFooterPreferenceController() {
        ShadowApplication.getInstance().setSystemService(Context.FACE_SERVICE, mFaceManager);
        mController = new FaceSettingsFooterPreferenceController(mContext, PREF_KEY);
    }

    @Test
    @Test
    public void isSliceable_returnFalse() {
    public void isSliceable_returnFalse() {
        setupHasFaceFeature();
        displayFaceSettingsFooterPreferenceController();

        assertThat(mController.isSliceable()).isFalse();
        assertThat(mController.isSliceable()).isFalse();
    }
    }


    @Test
    @Test
    public void testString_faceNotClass3() throws RemoteException {
    public void testString_faceNotClass3() throws RemoteException {
        setupHasFaceFeature();
        displayFaceSettingsFooterPreferenceController();

        verify(mFaceManager).addAuthenticatorsRegisteredCallback(mCaptor.capture());
        verify(mFaceManager).addAuthenticatorsRegisteredCallback(mCaptor.capture());
        mController.updateState(mPreference);
        mController.updateState(mPreference);


@@ -112,6 +141,9 @@ public class FaceSettingsFooterPreferenceControllerTest {


    @Test
    @Test
    public void testString_faceClass3() throws RemoteException {
    public void testString_faceClass3() throws RemoteException {
        setupHasFaceFeature();
        displayFaceSettingsFooterPreferenceController();

        verify(mFaceManager).addAuthenticatorsRegisteredCallback(mCaptor.capture());
        verify(mFaceManager).addAuthenticatorsRegisteredCallback(mCaptor.capture());
        mController.updateState(mPreference);
        mController.updateState(mPreference);


@@ -132,4 +164,30 @@ public class FaceSettingsFooterPreferenceControllerTest {
        assertThat(mPreference.getTitle().toString()).isEqualTo(
        assertThat(mPreference.getTitle().toString()).isEqualTo(
                mContext.getString(R.string.security_settings_face_settings_footer_class3));
                mContext.getString(R.string.security_settings_face_settings_footer_class3));
    }
    }

    @Test
    public void testSupportFaceFeature_shouldAddAuthenticatorsRegisteredCallback() {
        setupHasFaceFeature();
        displayFaceSettingsFooterPreferenceController();

        verify(mFaceManager).addAuthenticatorsRegisteredCallback(any());
    }

    @Test
    public void testNoFaceFeature_shouldNotAddAuthenticatorsRegisteredCallback() {
        setupNoFaceFeature();
        displayFaceSettingsFooterPreferenceController();

        verify(mContext, never()).getSystemService(FaceManager.class);
        verify(mFaceManager, never()).addAuthenticatorsRegisteredCallback(any());
    }

    @Test
    public void testHasFaceFeature_shouldNotAddAuthenticatorsRegisteredCallback_inCtor() {
        setupHasFaceFeature();
        createFaceSettingsFooterPreferenceController();

        verify(mContext, never()).getSystemService(FaceManager.class);
        verify(mFaceManager, never()).addAuthenticatorsRegisteredCallback(any());
    }
}
}