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.LauncherState.ALL_APPS; 19 import static com.android.launcher3.LauncherState.NORMAL; 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.util.Log; 30 import android.view.View; 31 32 import androidx.recyclerview.widget.RecyclerView.ViewHolder; 33 34 import com.android.launcher3.R; 35 import com.android.launcher3.allapps.ActivityAllAppsContainerView; 36 import com.android.launcher3.allapps.AllAppsPagedView; 37 import com.android.launcher3.allapps.WorkEduCard; 38 import com.android.launcher3.allapps.WorkPausedCard; 39 import com.android.launcher3.allapps.WorkProfileManager; 40 import com.android.launcher3.tapl.LauncherInstrumentation; 41 import com.android.launcher3.util.TestUtil; 42 import com.android.launcher3.util.rule.TestStabilityRule.Stability; 43 44 import org.junit.After; 45 import org.junit.Before; 46 import org.junit.Ignore; 47 import org.junit.Test; 48 49 import java.util.Objects; 50 import java.util.function.Predicate; 51 52 public class WorkProfileTest extends AbstractLauncherUiTest { 53 54 private static final int WORK_PAGE = ActivityAllAppsContainerView.AdapterHolder.WORK; 55 56 private int mProfileUserId; 57 private boolean mWorkProfileSetupSuccessful; 58 private final String TAG = "WorkProfileTest"; 59 60 @Before 61 @Override setUp()62 public void setUp() throws Exception { 63 super.setUp(); 64 String output = 65 mDevice.executeShellCommand( 66 "pm create-user --profileOf 0 --managed TestProfile"); 67 // b/203817455 68 updateWorkProfileSetupSuccessful("pm create-user", output); 69 70 String[] tokens = output.split("\\s+"); 71 mProfileUserId = Integer.parseInt(tokens[tokens.length - 1]); 72 StringBuilder logStr = new StringBuilder().append("profileId: ").append(mProfileUserId); 73 for (String str : tokens) { 74 logStr.append(str).append("\n"); 75 } 76 installDummyAppForUser(mProfileUserId); 77 updateWorkProfileSetupSuccessful("am start-user", output); 78 79 if (!mWorkProfileSetupSuccessful) { 80 return; // no need to setup launcher since all tests will skip. 81 } 82 83 mDevice.pressHome(); 84 waitForLauncherCondition("Launcher didn't start", Objects::nonNull); 85 waitForStateTransitionToEnd("Launcher internal state didn't switch to Normal", 86 () -> NORMAL); 87 waitForResumed("Launcher internal state is still Background"); 88 mLauncher.getWorkspace().switchToAllApps(); 89 waitForStateTransitionToEnd("Launcher internal state didn't switch to All Apps", 90 () -> ALL_APPS); 91 } 92 93 @After removeWorkProfile()94 public void removeWorkProfile() throws Exception { 95 executeOnLauncher(launcher -> { 96 if (launcher == null || launcher.getAppsView() == null) { 97 return; 98 } 99 launcher.getAppsView().getAppsStore().disableDeferUpdates(DEFER_UPDATES_TEST); 100 }); 101 TestUtil.uninstallDummyApp(); 102 mDevice.executeShellCommand("pm remove-user " + mProfileUserId); 103 } 104 waitForWorkTabSetup()105 private void waitForWorkTabSetup() { 106 // Added for b/243688989 flake to determine if we really are in allApps or not at this point 107 mLauncher.getAllApps(); 108 waitForLauncherCondition("Work tab not setup", launcher -> { 109 if (launcher.getAppsView().getContentView() instanceof AllAppsPagedView) { 110 launcher.getAppsView().getAppsStore().enableDeferUpdates(DEFER_UPDATES_TEST); 111 return true; 112 } 113 return false; 114 }, LauncherInstrumentation.WAIT_TIME_MS); 115 } 116 117 @Test 118 @Stability(flavors = LOCAL | PLATFORM_POSTSUBMIT) // b/243688989 workTabExists()119 public void workTabExists() { 120 assumeTrue(mWorkProfileSetupSuccessful); 121 waitForWorkTabSetup(); 122 waitForLauncherCondition("Personal tab is missing", 123 launcher -> launcher.getAppsView().isPersonalTabVisible(), 124 LauncherInstrumentation.WAIT_TIME_MS); 125 waitForLauncherCondition("Work tab is missing", 126 launcher -> launcher.getAppsView().isWorkTabVisible(), 127 LauncherInstrumentation.WAIT_TIME_MS); 128 } 129 130 @Test 131 @Ignore("b/243855320") 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 143 waitForLauncherCondition("work profile initial state check failed", launcher -> 144 manager.getWorkModeSwitch() != null 145 && manager.getCurrentState() == WorkProfileManager.STATE_ENABLED 146 && manager.getWorkModeSwitch().isEnabled(), 147 LauncherInstrumentation.WAIT_TIME_MS); 148 149 //start work profile toggle OFF test 150 executeOnLauncher(l -> { 151 // Ensure updates are not deferred so notification happens when apps pause. 152 l.getAppsView().getAppsStore().disableDeferUpdates(DEFER_UPDATES_TEST); 153 l.getAppsView().getWorkManager().getWorkModeSwitch().performClick(); 154 }); 155 156 waitForLauncherCondition("Work profile toggle OFF failed", launcher -> { 157 manager.reset(); // pulls current state from system 158 return manager.getCurrentState() == WorkProfileManager.STATE_DISABLED; 159 }, LauncherInstrumentation.WAIT_TIME_MS); 160 161 waitForWorkCard("Work paused card not shown", view -> view instanceof WorkPausedCard); 162 163 // start work profile toggle ON test 164 executeOnLauncher(l -> { 165 ActivityAllAppsContainerView<?> allApps = l.getAppsView(); 166 assertEquals("Work tab is not focused", allApps.getCurrentPage(), WORK_PAGE); 167 View workPausedCard = allApps.getActiveRecyclerView() 168 .findViewHolderForAdapterPosition(0).itemView; 169 workPausedCard.findViewById(R.id.enable_work_apps).performClick(); 170 }); 171 waitForLauncherCondition("Work profile toggle ON failed", launcher -> { 172 manager.reset(); // pulls current state from system 173 return manager.getCurrentState() == WorkProfileManager.STATE_ENABLED; 174 }, LauncherInstrumentation.WAIT_TIME_MS); 175 176 } 177 178 @Test 179 @Stability(flavors = LOCAL | PLATFORM_POSTSUBMIT) // b/243688989 testEdu()180 public void testEdu() { 181 assumeTrue(mWorkProfileSetupSuccessful); 182 waitForWorkTabSetup(); 183 executeOnLauncher(l -> { 184 l.getSharedPrefs().edit().putInt(WorkProfileManager.KEY_WORK_EDU_STEP, 0).commit(); 185 ((AllAppsPagedView) l.getAppsView().getContentView()).setCurrentPage(WORK_PAGE); 186 l.getAppsView().getWorkManager().reset(); 187 }); 188 189 waitForWorkCard("Work profile education not shown", view -> view instanceof WorkEduCard); 190 } 191 waitForWorkCard(String message, Predicate<View> workCardCheck)192 private void waitForWorkCard(String message, Predicate<View> workCardCheck) { 193 waitForLauncherCondition(message, l -> { 194 l.getAppsView().getAppsStore().disableDeferUpdates(DEFER_UPDATES_TEST); 195 ViewHolder holder = l.getAppsView().getActiveRecyclerView() 196 .findViewHolderForAdapterPosition(0); 197 try { 198 return holder != null && workCardCheck.test(holder.itemView); 199 } finally { 200 l.getAppsView().getAppsStore().enableDeferUpdates(DEFER_UPDATES_TEST); 201 } 202 }, LauncherInstrumentation.WAIT_TIME_MS); 203 } 204 updateWorkProfileSetupSuccessful(String cli, String output)205 private void updateWorkProfileSetupSuccessful(String cli, String output) { 206 Log.d(TAG, "updateWorkProfileSetupSuccessful, cli=" + cli + " " + "output=" + output); 207 if (output.startsWith("Success")) { 208 assertTrue(output, output.startsWith("Success")); 209 mWorkProfileSetupSuccessful = true; 210 } else { 211 mWorkProfileSetupSuccessful = false; 212 } 213 } 214 } 215