1 /* 2 * Copyright (C) 2017 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 android.packageinstaller.admin.cts; 17 18 import static org.junit.Assert.assertEquals; 19 import static org.junit.Assert.assertFalse; 20 import static org.junit.Assert.assertNotNull; 21 import static org.junit.Assert.assertNull; 22 import static org.junit.Assert.assertTrue; 23 import static org.junit.Assume.assumeTrue; 24 25 import android.app.admin.DevicePolicyManager; 26 import android.content.BroadcastReceiver; 27 import android.content.ComponentName; 28 import android.content.Context; 29 import android.content.Intent; 30 import android.content.IntentFilter; 31 import android.content.pm.PackageInstaller; 32 import android.content.pm.ResolveInfo; 33 import android.os.Process; 34 import android.os.UserHandle; 35 import android.os.UserManager; 36 import android.text.TextUtils; 37 38 import com.android.bedstead.harrier.annotations.RequireRunOnSystemUser; 39 import com.android.bedstead.harrier.BedsteadJUnit4; 40 import com.android.cts.install.lib.Install; 41 import com.android.cts.install.lib.InstallUtils; 42 import com.android.cts.install.lib.TestApp; 43 import com.android.cts.install.lib.Uninstall; 44 45 import org.junit.After; 46 import org.junit.Before; 47 import org.junit.Test; 48 import org.junit.runner.RunWith; 49 50 import java.util.concurrent.CountDownLatch; 51 import java.util.concurrent.TimeUnit; 52 53 /** 54 * This class tests {@link PackageInstaller#ACTION_SESSION_COMMITTED} is properly sent to the 55 * launcher app. 56 */ 57 @RunWith(BedsteadJUnit4.class) 58 @RequireRunOnSystemUser 59 public class SessionCommitBroadcastTest extends BasePackageInstallTest { 60 61 private static final long BROADCAST_TIMEOUT_SECS = 20; 62 private ComponentName mDefaultLauncher; 63 private ComponentName mThisAppLauncher; 64 private SessionCommitReceiver mReceiver; 65 66 @Before setUpTest()67 public void setUpTest() throws Exception { 68 mDefaultLauncher = ComponentName.unflattenFromString(getDefaultLauncher()); 69 mThisAppLauncher = new ComponentName(mContext, LauncherActivity.class); 70 mReceiver = new SessionCommitReceiver(); 71 } 72 73 @After tearDownTest()74 public void tearDownTest() throws Exception { 75 mContext.unregisterReceiver(mReceiver); 76 Uninstall.packages(TestApp.A); 77 } 78 79 @Test testBroadcastNotReceivedForDifferentLauncher()80 public void testBroadcastNotReceivedForDifferentLauncher() throws Exception { 81 if (mDefaultLauncher.equals(mThisAppLauncher)) { 82 // Find a different launcher 83 Intent homeIntent = new Intent(Intent.ACTION_MAIN) 84 .addCategory(Intent.CATEGORY_HOME) 85 .addCategory(Intent.CATEGORY_DEFAULT); 86 for (ResolveInfo info : mPackageManager.queryIntentActivities(homeIntent, 0)) { 87 mDefaultLauncher = 88 new ComponentName(info.activityInfo.packageName, info.activityInfo.name); 89 if (!mDefaultLauncher.equals(mThisAppLauncher)) { 90 setLauncher(mDefaultLauncher.flattenToString()); 91 break; 92 } 93 } 94 } 95 96 assertFalse("No default launcher found", mDefaultLauncher.equals(mThisAppLauncher)); 97 // install the app 98 assertInstallPackage(); 99 // Broadcast not received 100 assertNull(mReceiver.blockingGetIntent()); 101 102 tryUninstallPackage(); 103 } 104 verifySessionIntent(Intent intent)105 private void verifySessionIntent(Intent intent) { 106 assertNotNull(intent); 107 PackageInstaller.SessionInfo info = intent 108 .getParcelableExtra(PackageInstaller.EXTRA_SESSION); 109 assertEquals(TEST_APP_PKG, info.getAppPackageName()); 110 } 111 112 @Test testBroadcastNotReceivedForUpdateInstall()113 public void testBroadcastNotReceivedForUpdateInstall() throws Exception { 114 try { 115 setLauncher(mThisAppLauncher.flattenToString()); 116 117 int sessionId = Install.single(TestApp.A1).commit(); 118 assertEquals(1, InstallUtils.getInstalledVersion(TestApp.A)); 119 // Check the broadcast is received for a new install and session id matches 120 Intent intent = mReceiver.blockingGetIntent(); 121 PackageInstaller.SessionInfo info = 122 intent.getParcelableExtra(PackageInstaller.EXTRA_SESSION); 123 assertEquals(sessionId, info.getSessionId()); 124 125 mContext.unregisterReceiver(mReceiver); 126 mReceiver = new SessionCommitReceiver(); 127 Install.single(TestApp.A2).commit(); 128 assertEquals(2, InstallUtils.getInstalledVersion(TestApp.A)); 129 130 // Check no broadcast is received for an update install 131 intent = mReceiver.blockingGetIntent(); 132 assertNull(intent); 133 } finally { 134 // Revert to default launcher 135 setLauncher(mDefaultLauncher.flattenToString()); 136 } 137 } 138 139 @Test testBroadcastReceivedForNewInstall()140 public void testBroadcastReceivedForNewInstall() throws Exception { 141 setLauncher(mThisAppLauncher.flattenToString()); 142 143 // install the app 144 assertInstallPackage(); 145 146 verifySessionIntent(mReceiver.blockingGetIntent()); 147 mContext.unregisterReceiver(mReceiver); 148 forceUninstall(); 149 mReceiver = new SessionCommitReceiver(); 150 assertInstallPackage(); 151 verifySessionIntent(mReceiver.blockingGetIntent()); 152 153 tryUninstallPackage(); 154 // Revert to default launcher 155 setLauncher(mDefaultLauncher.flattenToString()); 156 } 157 158 @Test testBroadcastReceivedForEnablingApp()159 public void testBroadcastReceivedForEnablingApp() throws Exception { 160 assumeTrue("Cannot add multiple users", UserManager.supportsMultipleUsers()); 161 162 setLauncher(mThisAppLauncher.flattenToString()); 163 164 ComponentName cn = new ComponentName(mContext, BasicAdminReceiver.class); 165 UserHandle user = mDevicePolicyManager.createAndManageUser(cn, 166 "Test User " + System.currentTimeMillis(), cn, 167 null, DevicePolicyManager.SKIP_SETUP_WIZARD); 168 int userId = user.getIdentifier(); 169 assertTrue(TextUtils.join(" ", runShellCommand("am start-user " + userId)) 170 .toLowerCase().contains("success")); 171 172 // Install app for the second user 173 assertTrue(TextUtils.join(" ", runShellCommand( 174 "pm install -r --user " + userId + " " + TEST_APP_LOCATION)) 175 .toLowerCase().contains("success")); 176 177 // Enable the app for this user 178 runShellCommand("cmd package install-existing --user " + 179 Process.myUserHandle().getIdentifier() + " " + TEST_APP_PKG); 180 verifySessionIntent(mReceiver.blockingGetIntent()); 181 182 // Cleanup 183 setLauncher(mDefaultLauncher.flattenToString()); 184 mDevicePolicyManager.removeUser(cn, user); 185 forceUninstall(); 186 } 187 getDefaultLauncher()188 private String getDefaultLauncher() throws Exception { 189 final String PREFIX = "Launcher: ComponentInfo{"; 190 final String POSTFIX = "}"; 191 for (String s : runShellCommand("cmd shortcut get-default-launcher")) { 192 if (s.startsWith(PREFIX) && s.endsWith(POSTFIX)) { 193 return s.substring(PREFIX.length(), s.length() - POSTFIX.length()); 194 } 195 } 196 throw new Exception("Default launcher not found"); 197 } 198 setLauncher(String component)199 private void setLauncher(String component) throws Exception { 200 runShellCommand("cmd package set-home-activity --user " 201 + mInstrumentation.getContext().getUserId() + " " + component); 202 } 203 204 private class SessionCommitReceiver extends BroadcastReceiver { 205 206 private final CountDownLatch mLatch = new CountDownLatch(1); 207 private Intent mIntent; 208 SessionCommitReceiver()209 SessionCommitReceiver() { 210 mContext.registerReceiver(this, 211 new IntentFilter(PackageInstaller.ACTION_SESSION_COMMITTED), 212 Context.RECEIVER_EXPORTED); 213 } 214 215 @Override onReceive(Context context, Intent intent)216 public void onReceive(Context context, Intent intent) { 217 assertNull(mIntent); 218 mIntent = intent; 219 mLatch.countDown(); 220 } 221 blockingGetIntent()222 public Intent blockingGetIntent() throws Exception { 223 mLatch.await(BROADCAST_TIMEOUT_SECS, TimeUnit.SECONDS); 224 return mIntent; 225 } 226 } 227 } 228