• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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