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.trust;
18 
19 import static android.content.pm.PackageManager.PERMISSION_GRANTED;
20 
21 import static com.android.dx.mockito.inline.extended.ExtendedMockito.any;
22 import static com.android.dx.mockito.inline.extended.ExtendedMockito.anyInt;
23 import static com.android.dx.mockito.inline.extended.ExtendedMockito.argThat;
24 import static com.android.dx.mockito.inline.extended.ExtendedMockito.doReturn;
25 import static com.android.dx.mockito.inline.extended.ExtendedMockito.eq;
26 import static com.android.dx.mockito.inline.extended.ExtendedMockito.mock;
27 import static com.android.dx.mockito.inline.extended.ExtendedMockito.mockitoSession;
28 import static com.android.dx.mockito.inline.extended.ExtendedMockito.verify;
29 import static com.android.dx.mockito.inline.extended.ExtendedMockito.when;
30 
31 import static com.google.common.truth.Truth.assertThat;
32 
33 import static org.mockito.ArgumentMatchers.anyBoolean;
34 
35 import android.Manifest;
36 import android.annotation.Nullable;
37 import android.app.trust.ITrustListener;
38 import android.app.trust.ITrustManager;
39 import android.content.BroadcastReceiver;
40 import android.content.ComponentName;
41 import android.content.Context;
42 import android.content.Intent;
43 import android.content.IntentFilter;
44 import android.content.pm.ApplicationInfo;
45 import android.content.pm.PackageManager;
46 import android.content.pm.ResolveInfo;
47 import android.content.pm.ServiceInfo;
48 import android.net.Uri;
49 import android.os.Handler;
50 import android.os.IBinder;
51 import android.os.RemoteException;
52 import android.os.ServiceManager;
53 import android.os.UserHandle;
54 import android.os.test.TestLooper;
55 import android.provider.Settings;
56 import android.service.trust.TrustAgentService;
57 import android.testing.TestableContext;
58 import android.view.IWindowManager;
59 import android.view.WindowManagerGlobal;
60 
61 import androidx.test.core.app.ApplicationProvider;
62 
63 import com.android.internal.widget.LockPatternUtils;
64 import com.android.server.LocalServices;
65 import com.android.server.SystemService;
66 import com.android.server.SystemServiceManager;
67 
68 import com.google.android.collect.Lists;
69 
70 import org.junit.After;
71 import org.junit.Before;
72 import org.junit.Rule;
73 import org.junit.Test;
74 import org.mockito.ArgumentCaptor;
75 import org.mockito.ArgumentMatcher;
76 import org.mockito.Mock;
77 import org.mockito.MockitoSession;
78 import org.mockito.junit.MockitoJUnit;
79 import org.mockito.junit.MockitoRule;
80 
81 import java.util.ArrayList;
82 import java.util.Collections;
83 import java.util.Random;
84 
85 public class TrustManagerServiceTest {
86 
87     @Rule
88     public MockitoRule mMockitoRule = MockitoJUnit.rule();
89     @Rule
90     public final MockContext mMockContext = new MockContext(
91             ApplicationProvider.getApplicationContext());
92 
93     private static final String URI_SCHEME_PACKAGE = "package";
94     private static final int TEST_USER_ID = UserHandle.USER_SYSTEM;
95 
96     private final TestLooper mLooper = new TestLooper();
97     private final ArrayList<ResolveInfo> mTrustAgentResolveInfoList = new ArrayList<>();
98     private final LockPatternUtils mLockPatternUtils = new LockPatternUtils(mMockContext);
99     private final TrustManagerService mService = new TrustManagerService(mMockContext);
100 
101     @Mock
102     private PackageManager mPackageManagerMock;
103 
104     @Before
setUp()105     public void setUp() {
106         resetTrustAgentLockSettings();
107         LocalServices.addService(SystemServiceManager.class, mock(SystemServiceManager.class));
108 
109         ArgumentMatcher<Intent> trustAgentIntentMatcher = new ArgumentMatcher<Intent>() {
110             @Override
111             public boolean matches(Intent argument) {
112                 return TrustAgentService.SERVICE_INTERFACE.equals(argument.getAction());
113             }
114         };
115         when(mPackageManagerMock.queryIntentServicesAsUser(argThat(trustAgentIntentMatcher),
116                 anyInt(), anyInt())).thenReturn(mTrustAgentResolveInfoList);
117         when(mPackageManagerMock.checkPermission(any(), any())).thenReturn(
118                 PackageManager.PERMISSION_GRANTED);
119         mMockContext.setMockPackageManager(mPackageManagerMock);
120     }
121 
122     @After
tearDown()123     public void tearDown() {
124         resetTrustAgentLockSettings();
125         LocalServices.removeServiceForTest(SystemServiceManager.class);
126     }
127 
128     @Test
firstBootCompleted_systemTrustAgentsEnabled()129     public void firstBootCompleted_systemTrustAgentsEnabled() {
130         ComponentName systemTrustAgent1 = ComponentName.unflattenFromString(
131                 "com.android/.SystemTrustAgent");
132         ComponentName systemTrustAgent2 = ComponentName.unflattenFromString(
133                 "com.android/.AnotherSystemTrustAgent");
134         ComponentName userTrustAgent1 = ComponentName.unflattenFromString(
135                 "com.user/.UserTrustAgent");
136         ComponentName userTrustAgent2 = ComponentName.unflattenFromString(
137                 "com.user/.AnotherUserTrustAgent");
138         addTrustAgent(systemTrustAgent1, /* isSystemApp= */ true);
139         addTrustAgent(systemTrustAgent2, /* isSystemApp= */ true);
140         addTrustAgent(userTrustAgent1, /* isSystemApp= */ false);
141         addTrustAgent(userTrustAgent2, /* isSystemApp= */ false);
142 
143         bootService();
144 
145         assertThat(mLockPatternUtils.getEnabledTrustAgents(TEST_USER_ID)).containsExactly(
146                 systemTrustAgent1, systemTrustAgent2);
147         assertThat(mLockPatternUtils.getKnownTrustAgents(TEST_USER_ID)).containsExactly(
148                 systemTrustAgent1, systemTrustAgent2, userTrustAgent1, userTrustAgent2);
149     }
150 
151     @Test
firstBootCompleted_defaultTrustAgentEnabled()152     public void firstBootCompleted_defaultTrustAgentEnabled() {
153         ComponentName systemTrustAgent = ComponentName.unflattenFromString(
154                 "com.android/.SystemTrustAgent");
155         ComponentName defaultTrustAgent = ComponentName.unflattenFromString(
156                 "com.user/.DefaultTrustAgent");
157         addTrustAgent(systemTrustAgent, /* isSystemApp= */ true);
158         addTrustAgent(defaultTrustAgent, /* isSystemApp= */ false);
159         mMockContext.getOrCreateTestableResources().addOverride(
160                 com.android.internal.R.string.config_defaultTrustAgent,
161                 defaultTrustAgent.flattenToString());
162 
163         bootService();
164 
165         assertThat(mLockPatternUtils.getEnabledTrustAgents(TEST_USER_ID)).containsExactly(
166                 defaultTrustAgent);
167         assertThat(mLockPatternUtils.getKnownTrustAgents(TEST_USER_ID)).containsExactly(
168                 systemTrustAgent, defaultTrustAgent);
169     }
170 
171     @Test
serviceBooted_knownAgentsNotSet_enabledAgentsNotUpdated()172     public void serviceBooted_knownAgentsNotSet_enabledAgentsNotUpdated() {
173         ComponentName trustAgent1 = ComponentName.unflattenFromString(
174                 "com.android/.SystemTrustAgent");
175         ComponentName trustAgent2 = ComponentName.unflattenFromString(
176                 "com.android/.AnotherSystemTrustAgent");
177         initializeEnabledAgents(trustAgent1);
178         addTrustAgent(trustAgent1, /* isSystemApp= */ true);
179         addTrustAgent(trustAgent2, /* isSystemApp= */ true);
180 
181         bootService();
182 
183         assertThat(mLockPatternUtils.getEnabledTrustAgents(TEST_USER_ID)).containsExactly(
184                 trustAgent1);
185         assertThat(mLockPatternUtils.getKnownTrustAgents(TEST_USER_ID)).containsExactly(
186                 trustAgent1, trustAgent2);
187     }
188 
189     @Test
serviceBooted_knownAgentsSet_enabledAgentsUpdated()190     public void serviceBooted_knownAgentsSet_enabledAgentsUpdated() {
191         ComponentName trustAgent1 = ComponentName.unflattenFromString(
192                 "com.android/.SystemTrustAgent");
193         ComponentName trustAgent2 = ComponentName.unflattenFromString(
194                 "com.android/.AnotherSystemTrustAgent");
195         initializeEnabledAgents(trustAgent1);
196         initializeKnownAgents(trustAgent1);
197         addTrustAgent(trustAgent1, /* isSystemApp= */ true);
198         addTrustAgent(trustAgent2, /* isSystemApp= */ true);
199 
200         bootService();
201 
202         assertThat(mLockPatternUtils.getEnabledTrustAgents(TEST_USER_ID)).containsExactly(
203                 trustAgent1, trustAgent2);
204         assertThat(mLockPatternUtils.getKnownTrustAgents(TEST_USER_ID)).containsExactly(
205                 trustAgent1, trustAgent2);
206     }
207 
208     @Test
newSystemTrustAgent_setToEnabledAndKnown()209     public void newSystemTrustAgent_setToEnabledAndKnown() {
210         bootService();
211         ComponentName newAgentComponentName = ComponentName.unflattenFromString(
212                 "com.android/.SystemTrustAgent");
213         addTrustAgent(newAgentComponentName, /* isSystemApp= */ true);
214 
215         mMockContext.sendPackageChangedBroadcast(newAgentComponentName);
216 
217         assertThat(mLockPatternUtils.getEnabledTrustAgents(TEST_USER_ID)).containsExactly(
218                 newAgentComponentName);
219         assertThat(mLockPatternUtils.getKnownTrustAgents(TEST_USER_ID)).containsExactly(
220                 newAgentComponentName);
221     }
222 
223     @Test
newSystemTrustAgent_notEnabledWhenDefaultAgentIsSet()224     public void newSystemTrustAgent_notEnabledWhenDefaultAgentIsSet() {
225         ComponentName defaultTrustAgent = ComponentName.unflattenFromString(
226                 "com.user/.DefaultTrustAgent");
227         addTrustAgent(defaultTrustAgent, /* isSystemApp= */ false);
228         mMockContext.getOrCreateTestableResources().addOverride(
229                 com.android.internal.R.string.config_defaultTrustAgent,
230                 defaultTrustAgent.flattenToString());
231         bootService();
232         ComponentName newAgentComponentName = ComponentName.unflattenFromString(
233                 "com.android/.SystemTrustAgent");
234         addTrustAgent(newAgentComponentName, /* isSystemApp= */ true);
235 
236         mMockContext.sendPackageChangedBroadcast(newAgentComponentName);
237 
238         assertThat(mLockPatternUtils.getEnabledTrustAgents(TEST_USER_ID)).containsExactly(
239                 defaultTrustAgent);
240         assertThat(mLockPatternUtils.getKnownTrustAgents(TEST_USER_ID)).containsExactly(
241                 defaultTrustAgent, newAgentComponentName);
242     }
243 
244     @Test
newNonSystemTrustAgent_notEnabledButMarkedAsKnown()245     public void newNonSystemTrustAgent_notEnabledButMarkedAsKnown() {
246         bootService();
247         ComponentName newAgentComponentName = ComponentName.unflattenFromString(
248                 "com.user/.UserTrustAgent");
249         addTrustAgent(newAgentComponentName, /* isSystemApp= */ false);
250 
251         mMockContext.sendPackageChangedBroadcast(newAgentComponentName);
252 
253         assertThat(mLockPatternUtils.getEnabledTrustAgents(TEST_USER_ID)).isEmpty();
254         assertThat(mLockPatternUtils.getKnownTrustAgents(TEST_USER_ID)).containsExactly(
255                 newAgentComponentName);
256     }
257 
258     @Test
existingTrustAgentChanged_notEnabled()259     public void existingTrustAgentChanged_notEnabled() {
260         ComponentName systemTrustAgent1 = ComponentName.unflattenFromString(
261                 "com.android/.SystemTrustAgent");
262         ComponentName systemTrustAgent2 = ComponentName.unflattenFromString(
263                 "com.android/.AnotherSystemTrustAgent");
264         addTrustAgent(systemTrustAgent1, /* isSystemApp= */ true);
265         addTrustAgent(systemTrustAgent2, /* isSystemApp= */ true);
266         bootService();
267         // Simulate user turning off systemTrustAgent2
268         mLockPatternUtils.setEnabledTrustAgents(Collections.singletonList(systemTrustAgent1),
269                 TEST_USER_ID);
270 
271         mMockContext.sendPackageChangedBroadcast(systemTrustAgent2);
272 
273         assertThat(mLockPatternUtils.getEnabledTrustAgents(TEST_USER_ID)).containsExactly(
274                 systemTrustAgent1);
275     }
276 
277     @Test
reportEnabledTrustAgentsChangedInformsListener()278     public void reportEnabledTrustAgentsChangedInformsListener() throws RemoteException {
279         final LockPatternUtils utils = mock(LockPatternUtils.class);
280         final TrustManagerService service = new TrustManagerService(mMockContext,
281                 new TrustManagerService.Injector(utils, mLooper.getLooper()));
282         final ITrustListener trustListener = mock(ITrustListener.class);
283         final IWindowManager windowManager = mock(IWindowManager.class);
284         final int userId = new Random().nextInt();
285 
286         mMockContext.getTestablePermissions().setPermission(Manifest.permission.TRUST_LISTENER,
287                 PERMISSION_GRANTED);
288 
289         when(utils.getKnownTrustAgents(anyInt())).thenReturn(new ArrayList<>());
290 
291         MockitoSession mockSession = mockitoSession()
292                 .initMocks(this)
293                 .mockStatic(ServiceManager.class)
294                 .mockStatic(WindowManagerGlobal.class)
295                 .startMocking();
296 
297         doReturn(windowManager).when(() -> {
298             WindowManagerGlobal.getWindowManagerService();
299         });
300 
301         service.onStart();
302         ArgumentCaptor<IBinder> binderArgumentCaptor = ArgumentCaptor.forClass(IBinder.class);
303         verify(() -> ServiceManager.addService(eq(Context.TRUST_SERVICE),
304                 binderArgumentCaptor.capture(), anyBoolean(), anyInt()));
305         ITrustManager manager = ITrustManager.Stub.asInterface(binderArgumentCaptor.getValue());
306         manager.registerTrustListener(trustListener);
307         mLooper.dispatchAll();
308         manager.reportEnabledTrustAgentsChanged(userId);
309         mLooper.dispatchAll();
310         verify(trustListener).onEnabledTrustAgentsChanged(eq(userId));
311         mockSession.finishMocking();
312     }
313 
addTrustAgent(ComponentName agentComponentName, boolean isSystemApp)314     private void addTrustAgent(ComponentName agentComponentName, boolean isSystemApp) {
315         ApplicationInfo applicationInfo = new ApplicationInfo();
316         if (isSystemApp) {
317             applicationInfo.flags = ApplicationInfo.FLAG_SYSTEM;
318         }
319 
320         ServiceInfo serviceInfo = new ServiceInfo();
321         serviceInfo.packageName = agentComponentName.getPackageName();
322         serviceInfo.name = agentComponentName.getClassName();
323         serviceInfo.applicationInfo = applicationInfo;
324 
325         ResolveInfo resolveInfo = new ResolveInfo();
326         resolveInfo.serviceInfo = serviceInfo;
327         mTrustAgentResolveInfoList.add(resolveInfo);
328     }
329 
initializeEnabledAgents(ComponentName... enabledAgents)330     private void initializeEnabledAgents(ComponentName... enabledAgents) {
331         mLockPatternUtils.setEnabledTrustAgents(Lists.newArrayList(enabledAgents), TEST_USER_ID);
332         Settings.Secure.putIntForUser(mMockContext.getContentResolver(),
333                 Settings.Secure.TRUST_AGENTS_INITIALIZED, 1, TEST_USER_ID);
334     }
335 
initializeKnownAgents(ComponentName... knownAgents)336     private void initializeKnownAgents(ComponentName... knownAgents) {
337         mLockPatternUtils.setKnownTrustAgents(Lists.newArrayList(knownAgents), TEST_USER_ID);
338         Settings.Secure.putIntForUser(mMockContext.getContentResolver(),
339                 Settings.Secure.KNOWN_TRUST_AGENTS_INITIALIZED, 1, TEST_USER_ID);
340     }
341 
bootService()342     private void bootService() {
343         mService.onBootPhase(SystemService.PHASE_SYSTEM_SERVICES_READY);
344         mService.onBootPhase(SystemService.PHASE_THIRD_PARTY_APPS_CAN_START);
345         mService.onBootPhase(SystemService.PHASE_BOOT_COMPLETED);
346     }
347 
resetTrustAgentLockSettings()348     private void resetTrustAgentLockSettings() {
349         mLockPatternUtils.setEnabledTrustAgents(Collections.emptyList(), TEST_USER_ID);
350         mLockPatternUtils.setKnownTrustAgents(Collections.emptyList(), TEST_USER_ID);
351     }
352 
353     /** A mock Context that allows the test process to send protected broadcasts. */
354     private static final class MockContext extends TestableContext {
355 
356         private final ArrayList<BroadcastReceiver> mPackageChangedBroadcastReceivers =
357                 new ArrayList<>();
358 
MockContext(Context base)359         MockContext(Context base) {
360             super(base);
361         }
362 
363         @Override
364         @Nullable
registerReceiverAsUser(BroadcastReceiver receiver, UserHandle user, IntentFilter filter, @Nullable String broadcastPermission, @Nullable Handler scheduler)365         public Intent registerReceiverAsUser(BroadcastReceiver receiver,
366                 UserHandle user, IntentFilter filter, @Nullable String broadcastPermission,
367                 @Nullable Handler scheduler) {
368 
369             if (filter.hasAction(Intent.ACTION_PACKAGE_CHANGED)) {
370                 mPackageChangedBroadcastReceivers.add(receiver);
371             }
372             return super.registerReceiverAsUser(receiver, user, filter, broadcastPermission,
373                     scheduler);
374         }
375 
sendPackageChangedBroadcast(ComponentName changedComponent)376         void sendPackageChangedBroadcast(ComponentName changedComponent) {
377             Intent intent = new Intent(
378                     Intent.ACTION_PACKAGE_CHANGED,
379                     Uri.fromParts(URI_SCHEME_PACKAGE,
380                             changedComponent.getPackageName(), /* fragment= */ null))
381                     .putExtra(Intent.EXTRA_CHANGED_COMPONENT_NAME_LIST,
382                             new String[]{changedComponent.getClassName()})
383                     .putExtra(Intent.EXTRA_USER_HANDLE, TEST_USER_ID)
384                     .putExtra(Intent.EXTRA_UID, UserHandle.of(TEST_USER_ID).getUid(1234));
385             for (BroadcastReceiver receiver : mPackageChangedBroadcastReceivers) {
386                 receiver.onReceive(this, intent);
387             }
388         }
389     }
390 }
391