1 /*
2  * Copyright (C) 2023 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.healthconnect;
18 
19 import static org.mockito.ArgumentMatchers.any;
20 import static org.mockito.ArgumentMatchers.anyInt;
21 import static org.mockito.ArgumentMatchers.anyString;
22 import static org.mockito.Mockito.doNothing;
23 import static org.mockito.Mockito.eq;
24 import static org.mockito.Mockito.timeout;
25 import static org.mockito.Mockito.times;
26 import static org.mockito.Mockito.verify;
27 import static org.mockito.Mockito.when;
28 
29 import android.Manifest;
30 import android.app.job.JobScheduler;
31 import android.content.Context;
32 import android.content.pm.PackageInfo;
33 import android.content.pm.PackageManager;
34 import android.content.pm.PermissionGroupInfo;
35 import android.content.pm.PermissionInfo;
36 import android.os.UserHandle;
37 import android.os.UserManager;
38 import android.permission.PermissionManager;
39 
40 import androidx.test.platform.app.InstrumentationRegistry;
41 
42 import com.android.dx.mockito.inline.extended.ExtendedMockito;
43 import com.android.modules.utils.testing.ExtendedMockitoRule;
44 import com.android.server.SystemService;
45 import com.android.server.appop.AppOpsManagerLocal;
46 import com.android.server.healthconnect.backuprestore.BackupRestore;
47 import com.android.server.healthconnect.migration.MigrationStateChangeJob;
48 import com.android.server.healthconnect.storage.datatypehelpers.HealthDataCategoryPriorityHelper;
49 import com.android.server.healthconnect.storage.datatypehelpers.PreferenceHelper;
50 
51 import com.google.common.truth.Truth;
52 
53 import org.junit.Before;
54 import org.junit.Rule;
55 import org.junit.Test;
56 import org.mockito.Mock;
57 import org.mockito.quality.Strictness;
58 
59 public class HealthConnectManagerServiceTest {
60 
61     private static final String HEALTH_CONNECT_DAILY_JOB_NAMESPACE = "HEALTH_CONNECT_DAILY_JOB";
62     private static final String HEALTH_CONNECT_IMPORT_EXPORT_JOBS_NAMESPACE =
63             "HEALTH_CONNECT_IMPORT_EXPORT_JOBS";
64     private static final String ANDROID_SERVER_PACKAGE_NAME = "com.android.server";
65 
66     @Rule
67     public final ExtendedMockitoRule mExtendedMockitoRule =
68             new ExtendedMockitoRule.Builder(this)
69                     .mockStatic(PreferenceHelper.class)
70                     .mockStatic(BackupRestore.BackupRestoreJobService.class)
71                     .mockStatic(HealthDataCategoryPriorityHelper.class)
72                     .setStrictness(Strictness.LENIENT)
73                     .build();
74 
75     @Mock Context mContext;
76     @Mock private SystemService.TargetUser mMockTargetUser;
77     @Mock private JobScheduler mJobScheduler;
78     @Mock private UserManager mUserManager;
79     @Mock private PackageManager mPackageManager;
80     @Mock private PermissionManager mPermissionManager;
81     @Mock private AppOpsManagerLocal mAppOpsManagerLocal;
82     @Mock private PreferenceHelper mPreferenceHelper;
83     @Mock private HealthDataCategoryPriorityHelper mHealthDataCategoryPriorityHelper;
84     private HealthConnectManagerService mHealthConnectManagerService;
85 
86     @Before
setUp()87     public void setUp() throws PackageManager.NameNotFoundException {
88         InstrumentationRegistry.getInstrumentation()
89                 .getUiAutomation()
90                 .adoptShellPermissionIdentity(Manifest.permission.READ_DEVICE_CONFIG);
91 
92         when(mJobScheduler.forNamespace(HEALTH_CONNECT_DAILY_JOB_NAMESPACE))
93                 .thenReturn(mJobScheduler);
94         when(mJobScheduler.forNamespace(MigrationStateChangeJob.class.toString()))
95                 .thenReturn(mJobScheduler);
96         when(mJobScheduler.forNamespace(HEALTH_CONNECT_IMPORT_EXPORT_JOBS_NAMESPACE))
97                 .thenReturn(mJobScheduler);
98         PermissionGroupInfo permissionGroupInfo = new PermissionGroupInfo();
99         permissionGroupInfo.packageName = "test";
100         PackageInfo mockPackageInfo = new PackageInfo();
101         mockPackageInfo.permissions = new PermissionInfo[1];
102         mockPackageInfo.permissions[0] = new PermissionInfo();
103 
104         when(mPackageManager.getPermissionGroupInfo(
105                         eq(android.health.connect.HealthPermissions.HEALTH_PERMISSION_GROUP),
106                         eq(0)))
107                 .thenThrow(new PackageManager.NameNotFoundException());
108         when(mPackageManager.getPackageInfo(
109                         anyString(),
110                         eq(PackageManager.PackageInfoFlags.of(PackageManager.GET_PERMISSIONS))))
111                 .thenThrow(new PackageManager.NameNotFoundException());
112         when(mContext.getSystemService(JobScheduler.class)).thenReturn(mJobScheduler);
113         when(mContext.getSystemService(UserManager.class)).thenReturn(mUserManager);
114         when(mContext.getSystemService(PackageManager.class)).thenReturn(mPackageManager);
115         when(mContext.getPackageManager()).thenReturn(mPackageManager);
116         when(mContext.getSystemService(PermissionManager.class)).thenReturn(mPermissionManager);
117         when(mContext.getSystemService(AppOpsManagerLocal.class)).thenReturn(mAppOpsManagerLocal);
118         when(mContext.getUser()).thenReturn(UserHandle.CURRENT);
119         when(mContext.getPackageName()).thenReturn(ANDROID_SERVER_PACKAGE_NAME);
120         when(mContext.getDatabasePath(anyString()))
121                 .thenReturn(
122                         InstrumentationRegistry.getInstrumentation()
123                                 .getContext()
124                                 .getDatabasePath("mock"));
125         when(mContext.createContextAsUser(any(), anyInt())).thenReturn(mContext);
126         when(mMockTargetUser.getUserHandle()).thenReturn(UserHandle.CURRENT);
127         when(mContext.getApplicationContext()).thenReturn(mContext);
128         when(PreferenceHelper.getInstance()).thenReturn(mPreferenceHelper);
129         when(HealthDataCategoryPriorityHelper.getInstance())
130                 .thenReturn(mHealthDataCategoryPriorityHelper);
131         doNothing()
132                 .when(mHealthDataCategoryPriorityHelper)
133                 .maybeAddContributingAppsToPriorityList(mContext);
134         mHealthConnectManagerService = new HealthConnectManagerService(mContext);
135     }
136 
137     @Test
testCreateService()138     public void testCreateService() {
139         Truth.assertThat(mHealthConnectManagerService).isNotNull();
140     }
141 
142     @Test
testUserSupport()143     public void testUserSupport() {
144         when(mUserManager.isProfile()).thenReturn(true);
145         Truth.assertThat(mHealthConnectManagerService.isUserSupported(mMockTargetUser)).isFalse();
146         when(mUserManager.isProfile()).thenReturn(false);
147         Truth.assertThat(mHealthConnectManagerService.isUserSupported(mMockTargetUser)).isTrue();
148     }
149 
150     @Test
testUserSwitch()151     public void testUserSwitch() {
152         when(mUserManager.isUserUnlocked(any())).thenReturn(false);
153         mHealthConnectManagerService.onUserSwitching(mMockTargetUser, mMockTargetUser);
154         verify(mJobScheduler, times(0)).cancelAll();
155         when(mUserManager.isUserUnlocked(any())).thenReturn(true);
156         mHealthConnectManagerService.onUserSwitching(mMockTargetUser, mMockTargetUser);
157         verify(mJobScheduler, times(1)).cancelAll();
158         verify(mJobScheduler, timeout(5000).times(1)).schedule(any());
159         ExtendedMockito.verify(
160                 () -> BackupRestore.BackupRestoreJobService.cancelAllJobs(eq(mContext)));
161         verify(mHealthDataCategoryPriorityHelper).maybeAddContributingAppsToPriorityList(any());
162     }
163 }
164