1 /* 2 * Copyright (C) 2019 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.compat; 18 19 import static android.os.Process.myUserHandle; 20 21 import static com.android.launcher3.Flags.FLAG_ENABLE_SUPPORT_FOR_ARCHIVING; 22 23 import static com.google.common.truth.Truth.assertThat; 24 25 import android.content.pm.PackageInstaller.SessionParams; 26 import android.content.pm.PackageManager; 27 import android.graphics.Bitmap; 28 import android.platform.test.annotations.RequiresFlagsEnabled; 29 import android.platform.test.flag.junit.CheckFlagsRule; 30 import android.platform.test.flag.junit.DeviceFlagsValueProvider; 31 import android.text.TextUtils; 32 33 import androidx.test.ext.junit.runners.AndroidJUnit4; 34 import androidx.test.filters.LargeTest; 35 36 import com.android.launcher3.Launcher; 37 import com.android.launcher3.LauncherState; 38 import com.android.launcher3.util.BaseLauncherActivityTest; 39 import com.android.launcher3.util.LauncherBindableItemsContainer.ItemOperator; 40 import com.android.launcher3.util.TestUtil; 41 42 import org.junit.After; 43 import org.junit.Before; 44 import org.junit.Rule; 45 import org.junit.Test; 46 import org.junit.runner.RunWith; 47 48 import java.io.IOException; 49 import java.util.Arrays; 50 import java.util.UUID; 51 52 /** 53 * Test to verify promise icon flow. 54 */ 55 @LargeTest 56 @RunWith(AndroidJUnit4.class) 57 public class PromiseIconUiTest extends BaseLauncherActivityTest<Launcher> { 58 59 @Rule 60 public final CheckFlagsRule mCheckFlagsRule = 61 DeviceFlagsValueProvider.createCheckFlagsRule(); 62 63 public static final String PACKAGE_NAME = "test.promise.app"; 64 public static final String DUMMY_PACKAGE = "com.example.android.aardwolf"; 65 public static final String DUMMY_LABEL = "Aardwolf"; 66 67 private int mSessionId = -1; 68 69 @Before setUp()70 public void setUp() throws Exception { 71 loadLauncherSync(); 72 goToState(LauncherState.NORMAL); 73 mSessionId = -1; 74 } 75 76 @After tearDown()77 public void tearDown() throws IOException { 78 if (mSessionId > -1) { 79 targetContext().getPackageManager().getPackageInstaller().abandonSession(mSessionId); 80 } 81 TestUtil.uninstallDummyApp(); 82 } 83 84 /** 85 * Create a session and return the id. 86 */ createSession(String packageName, String label, Bitmap icon)87 private int createSession(String packageName, String label, Bitmap icon) throws Throwable { 88 SessionParams params = new SessionParams(SessionParams.MODE_FULL_INSTALL); 89 params.setAppPackageName(packageName); 90 params.setAppLabel(label); 91 params.setAppIcon(icon); 92 params.setInstallReason(PackageManager.INSTALL_REASON_USER); 93 return targetContext().getPackageManager().getPackageInstaller().createSession(params); 94 } 95 96 @Test testPromiseIcon_addedFromEligibleSession()97 public void testPromiseIcon_addedFromEligibleSession() throws Throwable { 98 final String appLabel = "Test Promise App " + UUID.randomUUID().toString(); 99 final ItemOperator findPromiseApp = (info, view) -> 100 info != null && TextUtils.equals(info.title, appLabel); 101 102 // Create and add test session 103 mSessionId = createSession(PACKAGE_NAME, appLabel, 104 Bitmap.createBitmap(100, 100, Bitmap.Config.ALPHA_8)); 105 106 // Verify promise icon is added 107 waitForLauncherCondition("Test Promise App not found on workspace", launcher -> 108 launcher.getWorkspace().getFirstMatch(findPromiseApp) != null); 109 110 // Remove session 111 targetContext().getPackageManager().getPackageInstaller().abandonSession(mSessionId); 112 mSessionId = -1; 113 114 // Verify promise icon is removed 115 waitForLauncherCondition("Test Promise App not removed from workspace", launcher -> 116 launcher.getWorkspace().getFirstMatch(findPromiseApp) == null); 117 } 118 119 @Test testPromiseIcon_notAddedFromIneligibleSession()120 public void testPromiseIcon_notAddedFromIneligibleSession() throws Throwable { 121 final String appLabel = "Test Promise App " + UUID.randomUUID().toString(); 122 final ItemOperator findPromiseApp = (info, view) -> 123 info != null && TextUtils.equals(info.title, appLabel); 124 125 // Create and add test session without icon or label 126 mSessionId = createSession(PACKAGE_NAME, null, null); 127 128 // Sleep for duration of animation if a view was to be added + some buffer time. 129 Thread.sleep(Launcher.NEW_APPS_PAGE_MOVE_DELAY + Launcher.NEW_APPS_ANIMATION_DELAY + 500); 130 131 // Verify promise icon is not added 132 waitForLauncherCondition("Test Promise App not found on workspace", launcher -> 133 launcher.getWorkspace().getFirstMatch(findPromiseApp) == null); 134 } 135 136 @Test 137 @RequiresFlagsEnabled(FLAG_ENABLE_SUPPORT_FOR_ARCHIVING) testPromiseIcon_addedArchivedApp()138 public void testPromiseIcon_addedArchivedApp() throws Throwable { 139 installDummyAppAndWaitForUIUpdate(); 140 assertThat(executeShellCommand( 141 String.format("pm archive --user %d %s", 142 myUserHandle().getIdentifier(), DUMMY_PACKAGE))) 143 .isEqualTo("Success\n"); 144 145 // Create and add test session 146 mSessionId = createSession(DUMMY_PACKAGE, /* label= */ "", 147 Bitmap.createBitmap(100, 100, Bitmap.Config.ALPHA_8)); 148 149 // Verify promise icon is added to all apps view. The icon may not be added to the 150 // workspace even if there might be no icon present for archived app. But icon will 151 // always be in all apps view. In case an icon is not added, an exception would be thrown. 152 goToState(LauncherState.ALL_APPS); 153 154 // Wait for the promise icon to be added. 155 waitForLauncherCondition( 156 DUMMY_PACKAGE + " app was not found on all apps after being archived", 157 launcher -> Arrays.stream(launcher.getAppsView().getAppsStore().getApps()) 158 .filter(info -> DUMMY_LABEL.equals(info.title.toString())) 159 .findAny() 160 .isPresent()); 161 } 162 installDummyAppAndWaitForUIUpdate()163 private void installDummyAppAndWaitForUIUpdate() throws IOException { 164 TestUtil.installDummyApp(); 165 loadLauncherSync(); 166 } 167 } 168