1 /* 2 * Copyright (C) 2021 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 package com.android.launcher3.ui; 17 18 import static com.android.launcher3.LauncherPrefs.WORK_EDU_STEP; 19 import static com.android.launcher3.LauncherState.ALL_APPS; 20 import static com.android.launcher3.allapps.AllAppsStore.DEFER_UPDATES_TEST; 21 import static com.android.launcher3.util.TestUtil.installDummyAppForUser; 22 import static com.android.launcher3.util.rule.TestStabilityRule.LOCAL; 23 import static com.android.launcher3.util.rule.TestStabilityRule.PLATFORM_POSTSUBMIT; 24 25 import static org.junit.Assert.assertEquals; 26 import static org.junit.Assert.assertTrue; 27 import static org.junit.Assume.assumeTrue; 28 29 import android.os.Process; 30 import android.util.Log; 31 import android.view.View; 32 33 import androidx.recyclerview.widget.RecyclerView.ViewHolder; 34 import androidx.test.ext.junit.runners.AndroidJUnit4; 35 import androidx.test.filters.LargeTest; 36 37 import com.android.launcher3.Launcher; 38 import com.android.launcher3.LauncherPrefs; 39 import com.android.launcher3.R; 40 import com.android.launcher3.allapps.ActivityAllAppsContainerView; 41 import com.android.launcher3.allapps.AllAppsPagedView; 42 import com.android.launcher3.allapps.WorkEduCard; 43 import com.android.launcher3.allapps.WorkPausedCard; 44 import com.android.launcher3.allapps.WorkProfileManager; 45 import com.android.launcher3.util.BaseLauncherActivityTest; 46 import com.android.launcher3.util.TestUtil; 47 import com.android.launcher3.util.rule.ScreenRecordRule; 48 import com.android.launcher3.util.rule.TestStabilityRule; 49 import com.android.launcher3.util.rule.TestStabilityRule.Stability; 50 51 import org.junit.After; 52 import org.junit.Before; 53 import org.junit.Rule; 54 import org.junit.Test; 55 import org.junit.runner.RunWith; 56 57 import java.util.function.Predicate; 58 59 @LargeTest 60 @RunWith(AndroidJUnit4.class) 61 public class WorkProfileTest extends BaseLauncherActivityTest<Launcher> { 62 63 private static final int WORK_PAGE = ActivityAllAppsContainerView.AdapterHolder.WORK; 64 public static final int WAIT_TIME_MS = 30000; 65 66 @Rule 67 public ScreenRecordRule mScreenRecordRule = new ScreenRecordRule(); 68 @Rule 69 public TestStabilityRule mTestStabilityRule = new TestStabilityRule(); 70 71 private int mProfileUserId; 72 private boolean mWorkProfileSetupSuccessful; 73 private static final String TAG = "WorkProfileTest"; 74 75 @Before setUp()76 public void setUp() throws Exception { 77 String output = executeShellCommand(String.format( 78 "pm create-user --profileOf %d --managed TestProfile", 79 Process.myUserHandle().getIdentifier())); 80 updateWorkProfileSetupSuccessful("pm create-user", output); 81 82 String[] tokens = output.split("\\s+"); 83 mProfileUserId = Integer.parseInt(tokens[tokens.length - 1]); 84 StringBuilder logStr = new StringBuilder().append("profileId: ").append(mProfileUserId); 85 for (String str : tokens) { 86 logStr.append(str).append("\n"); 87 } 88 installDummyAppForUser(mProfileUserId); 89 updateWorkProfileSetupSuccessful("am start-user", output); 90 91 if (!mWorkProfileSetupSuccessful) { 92 return; // no need to setup launcher since all tests will skip. 93 } 94 95 loadLauncherSync(); 96 goToState(ALL_APPS); 97 waitForState("Launcher internal state didn't switch to All Apps", () -> ALL_APPS); 98 } 99 100 @After removeWorkProfile()101 public void removeWorkProfile() throws Exception { 102 TestUtil.uninstallDummyApp(); 103 executeShellCommand("pm remove-user --wait " + mProfileUserId); 104 } 105 waitForWorkTabSetup()106 private void waitForWorkTabSetup() { 107 waitForLauncherCondition("Work tab not setup", launcher -> { 108 if (launcher.getAppsView().getContentView() instanceof AllAppsPagedView) { 109 launcher.getAppsView().getAppsStore().enableDeferUpdates(DEFER_UPDATES_TEST); 110 return true; 111 } 112 return false; 113 }, WAIT_TIME_MS); 114 } 115 116 @Test 117 @com.android.launcher3.util.rule.ScreenRecordRule.ScreenRecord // b/325383911 workTabExists()118 public void workTabExists() { 119 assumeTrue(mWorkProfileSetupSuccessful); 120 waitForWorkTabSetup(); 121 waitForLauncherCondition("Personal tab is missing", 122 launcher -> launcher.getAppsView().isPersonalTabVisible(), 123 WAIT_TIME_MS); 124 waitForLauncherCondition("Work tab is missing", 125 launcher -> launcher.getAppsView().isWorkTabVisible(), 126 WAIT_TIME_MS); 127 } 128 129 // Staging; will be promoted to presubmit if stable 130 @Stability(flavors = LOCAL | PLATFORM_POSTSUBMIT) 131 @Test toggleWorks()132 public void toggleWorks() { 133 assumeTrue(mWorkProfileSetupSuccessful); 134 waitForWorkTabSetup(); 135 executeOnLauncher(launcher -> { 136 AllAppsPagedView pagedView = (AllAppsPagedView) launcher.getAppsView().getContentView(); 137 pagedView.setCurrentPage(WORK_PAGE); 138 }); 139 140 WorkProfileManager manager = getFromLauncher(l -> l.getAppsView().getWorkManager()); 141 142 waitForLauncherCondition("work profile initial state check failed", launcher -> 143 manager.getWorkUtilityView() != null 144 && manager.getCurrentState() == WorkProfileManager.STATE_ENABLED 145 && manager.getWorkUtilityView().isEnabled(), 146 WAIT_TIME_MS); 147 148 //start work profile toggle OFF test 149 executeOnLauncher(l -> { 150 // Ensure updates are not deferred so notification happens when apps pause. 151 l.getAppsView().getAppsStore().disableDeferUpdates(DEFER_UPDATES_TEST); 152 l.getAppsView().getWorkManager().getWorkUtilityView().getWorkFAB().performClick(); 153 }); 154 155 waitForLauncherCondition("Work profile toggle OFF failed", launcher -> { 156 manager.reset(); // pulls current state from system 157 return manager.getCurrentState() == WorkProfileManager.STATE_DISABLED; 158 }, WAIT_TIME_MS); 159 160 waitForWorkCard("Work paused card not shown", view -> view instanceof WorkPausedCard); 161 162 // start work profile toggle ON test 163 executeOnLauncher(l -> { 164 ActivityAllAppsContainerView<?> allApps = l.getAppsView(); 165 assertEquals("Work tab is not focused", allApps.getCurrentPage(), WORK_PAGE); 166 View workPausedCard = allApps.getActiveRecyclerView() 167 .findViewHolderForAdapterPosition(0).itemView; 168 workPausedCard.findViewById(R.id.enable_work_apps).performClick(); 169 }); 170 waitForLauncherCondition("Work profile toggle ON failed", launcher -> { 171 manager.reset(); // pulls current state from system 172 return manager.getCurrentState() == WorkProfileManager.STATE_ENABLED; 173 }, WAIT_TIME_MS); 174 175 } 176 177 @Test testEdu()178 public void testEdu() { 179 assumeTrue(mWorkProfileSetupSuccessful); 180 waitForWorkTabSetup(); 181 executeOnLauncher(l -> { 182 LauncherPrefs.get(l).putSync(WORK_EDU_STEP.to(0)); 183 ((AllAppsPagedView) l.getAppsView().getContentView()).setCurrentPage(WORK_PAGE); 184 l.getAppsView().getWorkManager().reset(); 185 }); 186 187 waitForWorkCard("Work profile education not shown", view -> view instanceof WorkEduCard); 188 } 189 waitForWorkCard(String message, Predicate<View> workCardCheck)190 private void waitForWorkCard(String message, Predicate<View> workCardCheck) { 191 waitForLauncherCondition(message, l -> { 192 l.getAppsView().getAppsStore().disableDeferUpdates(DEFER_UPDATES_TEST); 193 ViewHolder holder = l.getAppsView().getActiveRecyclerView() 194 .findViewHolderForAdapterPosition(0); 195 try { 196 return holder != null && workCardCheck.test(holder.itemView); 197 } finally { 198 l.getAppsView().getAppsStore().enableDeferUpdates(DEFER_UPDATES_TEST); 199 } 200 }, WAIT_TIME_MS); 201 } 202 updateWorkProfileSetupSuccessful(String cli, String output)203 private void updateWorkProfileSetupSuccessful(String cli, String output) { 204 Log.d(TAG, "updateWorkProfileSetupSuccessful, cli=" + cli + " " + "output=" + output); 205 if (output.startsWith("Success")) { 206 assertTrue(output, output.startsWith("Success")); 207 mWorkProfileSetupSuccessful = true; 208 } else { 209 mWorkProfileSetupSuccessful = false; 210 } 211 } 212 } 213