• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2022 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 package com.android.server;
18 
19 import static org.mockito.ArgumentMatchers.anyInt;
20 import static org.mockito.ArgumentMatchers.anyString;
21 import static org.mockito.Mockito.doReturn;
22 import static org.mockito.Mockito.eq;
23 import static org.mockito.Mockito.mock;
24 import static org.mockito.Mockito.never;
25 import static org.mockito.Mockito.spy;
26 import static org.mockito.Mockito.times;
27 import static org.mockito.Mockito.verify;
28 import static org.mockito.Mockito.when;
29 
30 import android.app.job.JobScheduler;
31 import android.content.Context;
32 import android.content.pm.PackageManager;
33 import android.content.pm.PackageManagerInternal;
34 import android.hardware.biometrics.ComponentInfoInternal;
35 import android.hardware.biometrics.SensorProperties;
36 import android.hardware.face.FaceManager;
37 import android.hardware.face.FaceSensorProperties;
38 import android.hardware.face.FaceSensorPropertiesInternal;
39 import android.hardware.face.IFaceAuthenticatorsRegisteredCallback;
40 import android.hardware.fingerprint.FingerprintManager;
41 import android.hardware.fingerprint.FingerprintSensorProperties;
42 import android.hardware.fingerprint.FingerprintSensorPropertiesInternal;
43 import android.hardware.fingerprint.IFingerprintAuthenticatorsRegisteredCallback;
44 import android.os.Bundle;
45 import android.os.RemoteException;
46 import android.os.ResultReceiver;
47 import android.os.SystemProperties;
48 import android.provider.DeviceConfig;
49 
50 import androidx.test.core.app.ApplicationProvider;
51 import androidx.test.ext.junit.runners.AndroidJUnit4;
52 
53 import com.android.internal.os.IBinaryTransparencyService;
54 import com.android.internal.util.FrameworkStatsLog;
55 import com.android.server.pm.BackgroundInstallControlCallbackHelper;
56 import com.android.server.pm.BackgroundInstallControlService;
57 import com.android.server.pm.pkg.PackageStateInternal;
58 
59 import org.junit.After;
60 import org.junit.Assert;
61 import org.junit.Before;
62 import org.junit.Test;
63 import org.junit.runner.RunWith;
64 import org.mockito.ArgumentCaptor;
65 import org.mockito.Captor;
66 import org.mockito.Mock;
67 import org.mockito.MockitoAnnotations;
68 
69 import java.io.FileDescriptor;
70 import java.util.List;
71 
72 @RunWith(AndroidJUnit4.class)
73 public class BinaryTransparencyServiceTest {
74     private static final String TAG = "BinaryTransparencyServiceTest";
75 
76     private static final String TEST_PKG_NAME = "testPackageName";
77     private static final long TEST_VERSION_CODE = 1L;
78 
79     private Context mContext;
80     private BinaryTransparencyService mBinaryTransparencyService;
81     private BinaryTransparencyService.BinaryTransparencyServiceImpl mTestInterface;
82     private String mOriginalBiometricsFlag;
83 
84     @Mock
85     private BinaryTransparencyService.BiometricLogger mBiometricLogger;
86     @Mock
87     private FingerprintManager mFpManager;
88     @Mock
89     private FaceManager mFaceManager;
90     @Mock
91     private PackageManager mPackageManager;
92     @Mock
93     private PackageManagerInternal mPackageManagerInternal;
94     @Mock
95     private BinaryTransparencyService.BicCallbackHandler.IBicAppInfoHelper mBicAppInfoHelper;
96 
97     @Captor
98     private ArgumentCaptor<IFingerprintAuthenticatorsRegisteredCallback>
99             mFpAuthenticatorsRegisteredCaptor;
100     @Captor
101     private ArgumentCaptor<IFaceAuthenticatorsRegisteredCallback>
102             mFaceAuthenticatorsRegisteredCaptor;
103 
104     @Captor
105     private ArgumentCaptor<IBinaryTransparencyService.AppInfo> appInfoCaptor;
106 
107     @Before
setUp()108     public void setUp() {
109         MockitoAnnotations.initMocks(this);
110 
111         mContext = spy(ApplicationProvider.getApplicationContext());
112         LocalServices.removeServiceForTest(PackageManagerInternal.class);
113         LocalServices.addService(PackageManagerInternal.class, mPackageManagerInternal);
114 
115         mBinaryTransparencyService = new BinaryTransparencyService(mContext, mBiometricLogger);
116         mTestInterface = mBinaryTransparencyService.new BinaryTransparencyServiceImpl();
117         mOriginalBiometricsFlag = DeviceConfig.getProperty(DeviceConfig.NAMESPACE_BIOMETRICS,
118                 BinaryTransparencyService.KEY_ENABLE_BIOMETRIC_PROPERTY_VERIFICATION);
119     }
120 
121     @After
tearDown()122     public void tearDown() {
123         DeviceConfig.setProperty(DeviceConfig.NAMESPACE_BIOMETRICS,
124                 BinaryTransparencyService.KEY_ENABLE_BIOMETRIC_PROPERTY_VERIFICATION,
125                 mOriginalBiometricsFlag, false /* makeDefault */);
126         LocalServices.removeServiceForTest(PackageManagerInternal.class);
127     }
128 
prepSignedInfo()129     private void prepSignedInfo() {
130         // simulate what happens on boot completed phase
131         // but we avoid calling JobScheduler.schedule by returning a null.
132         doReturn(null).when(mContext).getSystemService(JobScheduler.class);
133         mBinaryTransparencyService.onBootPhase(SystemService.PHASE_BOOT_COMPLETED);
134     }
135 
prepApexInfo()136     private void prepApexInfo() throws RemoteException {
137         // simulates what happens to apex info after computations are done.
138         String[] args = {"get", "apex_info"};
139         mTestInterface.onShellCommand(FileDescriptor.in, FileDescriptor.out, FileDescriptor.err,
140                 args, null, new ResultReceiver(null));
141     }
142 
prepBiometricsTesting()143     private void prepBiometricsTesting() {
144         when(mContext.getPackageManager()).thenReturn(mPackageManager);
145         when(mPackageManager.hasSystemFeature(PackageManager.FEATURE_FINGERPRINT)).thenReturn(true);
146         when(mPackageManager.hasSystemFeature(PackageManager.FEATURE_FACE)).thenReturn(true);
147         when(mContext.getSystemService(FingerprintManager.class)).thenReturn(mFpManager);
148         when(mContext.getSystemService(FaceManager.class)).thenReturn(mFaceManager);
149     }
150 
151     @Test
getSignedImageInfo_preInitialize_returnsUninitializedString()152     public void getSignedImageInfo_preInitialize_returnsUninitializedString() {
153         String result = mTestInterface.getSignedImageInfo();
154         Assert.assertNotNull("VBMeta digest value should not be null", result);
155         Assert.assertEquals(BinaryTransparencyService.VBMETA_DIGEST_UNINITIALIZED, result);
156     }
157 
158     @Test
getSignedImageInfo_postInitialize_returnsNonErrorStrings()159     public void getSignedImageInfo_postInitialize_returnsNonErrorStrings() {
160         prepSignedInfo();
161         String result = mTestInterface.getSignedImageInfo();
162         Assert.assertNotNull("Initialized VBMeta digest string should not be null", result);
163         Assert.assertNotEquals("VBMeta digest value is uninitialized",
164                 BinaryTransparencyService.VBMETA_DIGEST_UNINITIALIZED, result);
165         Assert.assertNotEquals("VBMeta value should not be unavailable",
166                 BinaryTransparencyService.VBMETA_DIGEST_UNAVAILABLE, result);
167     }
168 
169     @Test
getSignedImageInfo_postInitialize_returnsCorrectValue()170     public void getSignedImageInfo_postInitialize_returnsCorrectValue() {
171         prepSignedInfo();
172         String result = mTestInterface.getSignedImageInfo();
173         Assert.assertEquals(
174                 SystemProperties.get(BinaryTransparencyService.SYSPROP_NAME_VBETA_DIGEST,
175                         BinaryTransparencyService.VBMETA_DIGEST_UNAVAILABLE), result);
176     }
177 
178     @Test
testCollectBiometricProperties_disablesFeature()179     public void testCollectBiometricProperties_disablesFeature() {
180         DeviceConfig.setProperty(DeviceConfig.NAMESPACE_BIOMETRICS,
181                 BinaryTransparencyService.KEY_ENABLE_BIOMETRIC_PROPERTY_VERIFICATION,
182                 Boolean.FALSE.toString(),
183                 false /* makeDefault */);
184 
185         mBinaryTransparencyService.collectBiometricProperties();
186 
187         verify(mBiometricLogger, never()).logStats(anyInt(), anyInt(), anyInt(), anyInt(),
188                 anyString(), anyString(), anyString(), anyString(), anyString());
189     }
190 
191     @Test
testCollectBiometricProperties_enablesFeature_logsFingerprintProperties()192     public void testCollectBiometricProperties_enablesFeature_logsFingerprintProperties()
193             throws RemoteException {
194         prepBiometricsTesting();
195         DeviceConfig.setProperty(DeviceConfig.NAMESPACE_BIOMETRICS,
196                 BinaryTransparencyService.KEY_ENABLE_BIOMETRIC_PROPERTY_VERIFICATION,
197                 Boolean.TRUE.toString(),
198                 false /* makeDefault */);
199         final List<FingerprintSensorPropertiesInternal> props = List.of(
200                 new FingerprintSensorPropertiesInternal(
201                         1 /* sensorId */,
202                         SensorProperties.STRENGTH_STRONG,
203                         5 /* maxEnrollmentsPerUser */,
204                         List.of(new ComponentInfoInternal("sensor" /* componentId */,
205                                 "vendor/model/revision" /* hardwareVersion */,
206                                 "1.01" /* firmwareVersion */, "00000001" /* serialNumber */,
207                                 "" /* softwareVersion */)),
208                         FingerprintSensorProperties.TYPE_REAR,
209                         true /* resetLockoutRequiresHardwareAuthToken */));
210 
211         mBinaryTransparencyService.collectBiometricProperties();
212 
213         verify(mFpManager).addAuthenticatorsRegisteredCallback(mFpAuthenticatorsRegisteredCaptor
214                 .capture());
215         mFpAuthenticatorsRegisteredCaptor.getValue().onAllAuthenticatorsRegistered(props);
216 
217         verify(mBiometricLogger, times(1)).logStats(
218                 eq(1) /* sensorId */,
219                 eq(FrameworkStatsLog
220                         .BIOMETRIC_PROPERTIES_COLLECTED__MODALITY__MODALITY_FINGERPRINT),
221                 eq(FrameworkStatsLog
222                         .BIOMETRIC_PROPERTIES_COLLECTED__SENSOR_TYPE__SENSOR_FP_REAR),
223                 eq(FrameworkStatsLog
224                         .BIOMETRIC_PROPERTIES_COLLECTED__SENSOR_STRENGTH__STRENGTH_STRONG),
225                 eq("sensor") /* componentId */,
226                 eq("vendor/model/revision") /* hardwareVersion */,
227                 eq("1.01") /* firmwareVersion */,
228                 eq("00000001") /* serialNumber */,
229                 eq("") /* softwareVersion */
230         );
231     }
232 
233     @Test
testCollectBiometricProperties_enablesFeature_logsFaceProperties()234     public void testCollectBiometricProperties_enablesFeature_logsFaceProperties()
235             throws RemoteException {
236         prepBiometricsTesting();
237         DeviceConfig.setProperty(DeviceConfig.NAMESPACE_BIOMETRICS,
238                 BinaryTransparencyService.KEY_ENABLE_BIOMETRIC_PROPERTY_VERIFICATION,
239                 Boolean.TRUE.toString(),
240                 false /* makeDefault */);
241         final List<FaceSensorPropertiesInternal> props = List.of(
242                 new FaceSensorPropertiesInternal(
243                         1 /* sensorId */,
244                         SensorProperties.STRENGTH_CONVENIENCE,
245                         1 /* maxEnrollmentsPerUser */,
246                         List.of(new ComponentInfoInternal("sensor" /* componentId */,
247                                 "vendor/model/revision" /* hardwareVersion */,
248                                 "1.01" /* firmwareVersion */, "00000001" /* serialNumber */,
249                                 "" /* softwareVersion */)),
250                         FaceSensorProperties.TYPE_RGB,
251                         true /* supportsFaceDetection */,
252                         true /* supportsSelfIllumination */,
253                         true /* resetLockoutRequiresHardwareAuthToken */));
254 
255         mBinaryTransparencyService.collectBiometricProperties();
256 
257         verify(mFaceManager).addAuthenticatorsRegisteredCallback(mFaceAuthenticatorsRegisteredCaptor
258                 .capture());
259         mFaceAuthenticatorsRegisteredCaptor.getValue().onAllAuthenticatorsRegistered(props);
260 
261         verify(mBiometricLogger, times(1)).logStats(
262                 eq(1) /* sensorId */,
263                 eq(FrameworkStatsLog
264                         .BIOMETRIC_PROPERTIES_COLLECTED__MODALITY__MODALITY_FACE),
265                 eq(FrameworkStatsLog
266                         .BIOMETRIC_PROPERTIES_COLLECTED__SENSOR_TYPE__SENSOR_FACE_RGB),
267                 eq(FrameworkStatsLog
268                         .BIOMETRIC_PROPERTIES_COLLECTED__SENSOR_STRENGTH__STRENGTH_CONVENIENCE),
269                 eq("sensor") /* componentId */,
270                 eq("vendor/model/revision") /* hardwareVersion */,
271                 eq("1.01") /* firmwareVersion */,
272                 eq("00000001") /* serialNumber */,
273                 eq("") /* softwareVersion */
274         );
275     }
276 
277     @Test
BicCallbackHandler_uploads_mba_metrics()278     public void BicCallbackHandler_uploads_mba_metrics() {
279         Bundle data = setupBicCallbackHandlerTest(false,
280             BinaryTransparencyService.MBA_STATUS_NEW_INSTALL);
281 
282         BinaryTransparencyService.BicCallbackHandler handler =
283             new BinaryTransparencyService.BicCallbackHandler(mBicAppInfoHelper);
284         handler.sendResult(data);
285 
286         verify(mBicAppInfoHelper, times(1)).writeAppInfoToLog(appInfoCaptor.capture());
287         Assert.assertEquals(TEST_PKG_NAME, appInfoCaptor.getValue().packageName);
288         Assert.assertEquals(TEST_VERSION_CODE, appInfoCaptor.getValue().longVersion);
289     }
290 
291     @Test
BicCallbackHandler_uploads_mba_metrics_for_preloads()292     public void BicCallbackHandler_uploads_mba_metrics_for_preloads() {
293         Bundle data = setupBicCallbackHandlerTest(true,
294             BinaryTransparencyService.MBA_STATUS_UPDATED_PRELOAD);
295 
296         BinaryTransparencyService.BicCallbackHandler handler =
297             new BinaryTransparencyService.BicCallbackHandler(mBicAppInfoHelper);
298         handler.sendResult(data);
299 
300         verify(mBicAppInfoHelper, times(1)).writeAppInfoToLog(appInfoCaptor.capture());
301         Assert.assertEquals(TEST_PKG_NAME, appInfoCaptor.getValue().packageName);
302         Assert.assertEquals(TEST_VERSION_CODE, appInfoCaptor.getValue().longVersion);
303     }
304 
305     @Test
BicCallbackHandler_uploads_mba_metrics_for_uninstalls()306     public void BicCallbackHandler_uploads_mba_metrics_for_uninstalls() {
307         Bundle data = new Bundle();
308         data.putString(BackgroundInstallControlCallbackHelper.FLAGGED_PACKAGE_NAME_KEY,
309             TEST_PKG_NAME);
310         data.putInt(BackgroundInstallControlCallbackHelper.INSTALL_EVENT_TYPE_KEY,
311             BackgroundInstallControlService.INSTALL_EVENT_TYPE_UNINSTALL);
312 
313         BinaryTransparencyService.BicCallbackHandler handler =
314                 new BinaryTransparencyService.BicCallbackHandler(mBicAppInfoHelper);
315         handler.sendResult(data);
316 
317         verify(mBicAppInfoHelper, times(1)).writeAppInfoToLog(appInfoCaptor.capture());
318         Assert.assertEquals(TEST_PKG_NAME ,appInfoCaptor.getValue().packageName);
319         Assert.assertEquals(BinaryTransparencyService.MBA_STATUS_UNINSTALLED,
320             appInfoCaptor.getValue().mbaStatus);
321     }
322 
setupBicCallbackHandlerTest(boolean isUpdatedSystemApp, int expectedBtsMbaStatus)323     private Bundle setupBicCallbackHandlerTest(boolean isUpdatedSystemApp,
324             int expectedBtsMbaStatus) {
325         Bundle data = new Bundle();
326         data.putString(BackgroundInstallControlCallbackHelper.FLAGGED_PACKAGE_NAME_KEY,
327             TEST_PKG_NAME);
328         data.putInt(BackgroundInstallControlCallbackHelper.INSTALL_EVENT_TYPE_KEY,
329             BackgroundInstallControlService.INSTALL_EVENT_TYPE_INSTALL);
330         PackageStateInternal mockPackageState = mock(PackageStateInternal.class);
331         when(mPackageManagerInternal.getPackageStateInternal(TEST_PKG_NAME))
332             .thenReturn(mockPackageState);
333         when(mockPackageState.isUpdatedSystemApp()).thenReturn(isUpdatedSystemApp);
334         IBinaryTransparencyService.AppInfo appInfo = new IBinaryTransparencyService.AppInfo();
335         appInfo.packageName = TEST_PKG_NAME;
336         appInfo.longVersion = TEST_VERSION_CODE;
337         when(mBicAppInfoHelper.collectAppInfo(mockPackageState, expectedBtsMbaStatus))
338             .thenReturn(List.of(appInfo));
339         return data;
340     }
341 }
342