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.launcher3.allapps;
18 
19 import static androidx.test.core.app.ApplicationProvider.getApplicationContext;
20 
21 import static com.android.launcher3.allapps.UserProfileManager.STATE_DISABLED;
22 import static com.android.launcher3.allapps.UserProfileManager.STATE_ENABLED;
23 import static com.android.launcher3.model.BgDataModel.Callbacks.FLAG_PRIVATE_PROFILE_QUIET_MODE_ENABLED;
24 import static com.android.launcher3.util.Executors.UI_HELPER_EXECUTOR;
25 import static com.android.launcher3.util.rule.TestStabilityRule.LOCAL;
26 import static com.android.launcher3.util.rule.TestStabilityRule.PLATFORM_POSTSUBMIT;
27 
28 import static org.junit.Assert.assertEquals;
29 import static org.mockito.ArgumentMatchers.any;
30 import static org.mockito.ArgumentMatchers.anyInt;
31 import static org.mockito.Mockito.doNothing;
32 import static org.mockito.Mockito.doReturn;
33 import static org.mockito.Mockito.spy;
34 import static org.mockito.Mockito.when;
35 
36 import android.app.PendingIntent;
37 import android.content.Context;
38 import android.content.Intent;
39 import android.content.pm.LauncherApps;
40 import android.content.pm.PackageManager;
41 import android.content.pm.ResolveInfo;
42 import android.content.res.Resources;
43 import android.os.Process;
44 import android.os.UserHandle;
45 import android.os.UserManager;
46 
47 import androidx.test.runner.AndroidJUnit4;
48 
49 import com.android.launcher3.logging.StatsLogManager;
50 import com.android.launcher3.pm.UserCache;
51 import com.android.launcher3.util.ActivityContextWrapper;
52 import com.android.launcher3.util.ApiWrapper;
53 import com.android.launcher3.util.UserIconInfo;
54 import com.android.launcher3.util.rule.TestStabilityRule;
55 
56 import org.junit.Before;
57 import org.junit.Rule;
58 import org.junit.Test;
59 import org.junit.rules.TestRule;
60 import org.junit.runner.RunWith;
61 import org.mockito.ArgumentCaptor;
62 import org.mockito.Mock;
63 import org.mockito.Mockito;
64 import org.mockito.MockitoAnnotations;
65 
66 import java.util.ArrayList;
67 import java.util.Arrays;
68 
69 @RunWith(AndroidJUnit4.class)
70 public class PrivateProfileManagerTest {
71 
72     @Rule(order = 0)
73     public TestRule testStabilityRule = new TestStabilityRule();
74 
75     private static final UserHandle MAIN_HANDLE = Process.myUserHandle();
76     private static final UserHandle PRIVATE_HANDLE = new UserHandle(11);
77     private static final UserIconInfo MAIN_ICON_INFO =
78             new UserIconInfo(MAIN_HANDLE, UserIconInfo.TYPE_MAIN);
79     private static final UserIconInfo PRIVATE_ICON_INFO =
80             new UserIconInfo(PRIVATE_HANDLE, UserIconInfo.TYPE_PRIVATE);
81 
82     private PrivateProfileManager mPrivateProfileManager;
83     @Mock
84     private ActivityAllAppsContainerView mAllApps;
85     @Mock
86     private StatsLogManager mStatsLogManager;
87     @Mock
88     private UserCache mUserCache;
89     @Mock
90     private UserManager mUserManager;
91     @Mock
92     private Context mContext;
93     @Mock
94     private AllAppsStore<?> mAllAppsStore;
95     @Mock
96     private PackageManager mPackageManager;
97     @Mock
98     private LauncherApps mLauncherApps;
99     @Mock
100     private AllAppsRecyclerView mAllAppsRecyclerView;
101     @Mock
102     private Resources mResources;
103 
104     @Before
setUp()105     public void setUp() {
106         MockitoAnnotations.initMocks(this);
107         when(mUserCache.getUserProfiles())
108                 .thenReturn(Arrays.asList(MAIN_HANDLE, PRIVATE_HANDLE));
109         when(mUserCache.getUserInfo(Process.myUserHandle())).thenReturn(MAIN_ICON_INFO);
110         when(mUserCache.getUserInfo(PRIVATE_HANDLE)).thenReturn(PRIVATE_ICON_INFO);
111         when(mAllApps.getContext()).thenReturn(mContext);
112         when(mContext.getResources()).thenReturn(mResources);
113         when(mContext.getApplicationContext()).thenReturn(getApplicationContext());
114         when(mAllApps.getAppsStore()).thenReturn(mAllAppsStore);
115         when(mAllApps.getActiveRecyclerView()).thenReturn(mAllAppsRecyclerView);
116         when(mContext.getPackageManager()).thenReturn(mPackageManager);
117         when(mPackageManager.resolveActivity(any(), any())).thenReturn(new ResolveInfo());
118         when(mContext.getSystemService(LauncherApps.class)).thenReturn(mLauncherApps);
119         when(mLauncherApps.getAppMarketActivityIntent(any(), any())).thenReturn(PendingIntent
120                 .getActivity(new ActivityContextWrapper(getApplicationContext()), 0,
121                         new Intent(), PendingIntent.FLAG_IMMUTABLE).getIntentSender());
122         when(mContext.getPackageName())
123                 .thenReturn("com.android.launcher3.tests.privateProfileManager");
124         when(mLauncherApps.getPreInstalledSystemPackages(any())).thenReturn(new ArrayList<>());
125         mPrivateProfileManager = new PrivateProfileManager(mUserManager,
126                 mAllApps, mStatsLogManager, mUserCache);
127     }
128 
129     @Test
lockPrivateProfile_requestsQuietModeAsTrue()130     public void lockPrivateProfile_requestsQuietModeAsTrue() throws Exception {
131         when(mAllAppsStore.hasModelFlag(FLAG_PRIVATE_PROFILE_QUIET_MODE_ENABLED)).thenReturn(false);
132 
133         mPrivateProfileManager.setQuietMode(true /* lock */);
134 
135         awaitTasksCompleted();
136         Mockito.verify(mUserManager).requestQuietModeEnabled(true, PRIVATE_HANDLE);
137     }
138 
139     @Test
unlockPrivateProfile_requestsQuietModeAsFalse()140     public void unlockPrivateProfile_requestsQuietModeAsFalse() throws Exception {
141         when(mAllAppsStore.hasModelFlag(FLAG_PRIVATE_PROFILE_QUIET_MODE_ENABLED)).thenReturn(true);
142 
143         mPrivateProfileManager.setQuietMode(false /* unlock */);
144 
145         awaitTasksCompleted();
146         Mockito.verify(mUserManager).requestQuietModeEnabled(false, PRIVATE_HANDLE);
147     }
148 
149     @Test
quietModeFlagPresent_privateSpaceIsResetToDisabled()150     public void quietModeFlagPresent_privateSpaceIsResetToDisabled() {
151         PrivateProfileManager privateProfileManager = spy(mPrivateProfileManager);
152         doNothing().when(privateProfileManager).addPrivateSpaceDecorator(anyInt());
153         doNothing().when(privateProfileManager).executeLock();
154         doReturn(mAllAppsRecyclerView).when(privateProfileManager).getMainRecyclerView();
155         when(mAllAppsStore.hasModelFlag(FLAG_PRIVATE_PROFILE_QUIET_MODE_ENABLED))
156                 .thenReturn(false, true);
157 
158         // In first call the state should be disabled.
159         privateProfileManager.reset();
160         assertEquals("Profile State is not Disabled", STATE_ENABLED,
161                 privateProfileManager.getCurrentState());
162 
163         // In the next call the state should be disabled.
164         privateProfileManager.reset();
165         assertEquals("Profile State is not Disabled", STATE_DISABLED,
166                 privateProfileManager.getCurrentState());
167     }
168 
169     @Test
transitioningToUnlocked_resetCallsPostUnlock()170     public void transitioningToUnlocked_resetCallsPostUnlock() throws Exception {
171         PrivateProfileManager privateProfileManager = spy(mPrivateProfileManager);
172         doNothing().when(privateProfileManager).addPrivateSpaceDecorator(anyInt());
173         doReturn(mAllAppsRecyclerView).when(privateProfileManager).getMainRecyclerView();
174         when(mAllAppsStore.hasModelFlag(FLAG_PRIVATE_PROFILE_QUIET_MODE_ENABLED))
175                 .thenReturn(false);
176         doNothing().when(privateProfileManager).expandPrivateSpace();
177         when(privateProfileManager.getCurrentState()).thenReturn(STATE_DISABLED);
178 
179         privateProfileManager.setQuietMode(false /* unlock */);
180         privateProfileManager.reset();
181 
182         awaitTasksCompleted();
183         Mockito.verify(privateProfileManager).postUnlock();
184     }
185 
186     @Test
transitioningToLocked_resetCallsExecuteLock()187     public void transitioningToLocked_resetCallsExecuteLock() throws Exception {
188         PrivateProfileManager privateProfileManager = spy(mPrivateProfileManager);
189         doNothing().when(privateProfileManager).addPrivateSpaceDecorator(anyInt());
190         doNothing().when(privateProfileManager).executeLock();
191         doReturn(mAllAppsRecyclerView).when(privateProfileManager).getMainRecyclerView();
192         when(mAllAppsStore.hasModelFlag(FLAG_PRIVATE_PROFILE_QUIET_MODE_ENABLED))
193                 .thenReturn(true);
194         doNothing().when(privateProfileManager).expandPrivateSpace();
195         when(privateProfileManager.getCurrentState()).thenReturn(STATE_ENABLED);
196 
197         privateProfileManager.setQuietMode(true /* lock */);
198         privateProfileManager.reset();
199 
200         awaitTasksCompleted();
201         Mockito.verify(privateProfileManager).executeLock();
202     }
203 
204     @Test
205     @TestStabilityRule.Stability(flavors = LOCAL | PLATFORM_POSTSUBMIT) // b/339109319
openPrivateSpaceSettings_triggersCorrectIntent()206     public void openPrivateSpaceSettings_triggersCorrectIntent() {
207         Intent expectedIntent = ApiWrapper.INSTANCE.get(mContext).getPrivateSpaceSettingsIntent();
208         ArgumentCaptor<Intent> acIntent = ArgumentCaptor.forClass(Intent.class);
209         mPrivateProfileManager.setPrivateSpaceSettingsAvailable(true);
210 
211         mContext.startActivity(expectedIntent);
212 
213         Mockito.verify(mContext).startActivity(acIntent.capture());
214         assertEquals("Intent Action is different",
215                 expectedIntent == null ? null : expectedIntent.toUri(0),
216                 acIntent.getValue() == null ? null : acIntent.getValue().toUri(0));
217     }
218 
awaitTasksCompleted()219     private static void awaitTasksCompleted() throws Exception {
220         UI_HELPER_EXECUTOR.submit(() -> null).get();
221     }
222 }
223