1 /* 2 * Copyright (C) 2015 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.cts.packageinstaller; 18 19 import android.app.UiAutomation; 20 import android.content.Intent; 21 import android.content.pm.PackageInstaller; 22 import android.content.pm.PackageManager; 23 import android.content.pm.ResolveInfo; 24 import android.os.UserHandle; 25 import android.provider.Settings; 26 import android.support.test.uiautomator.By; 27 import android.support.test.uiautomator.BySelector; 28 import android.support.test.uiautomator.UiObject2; 29 import android.support.test.uiautomator.Until; 30 import android.util.Log; 31 32 import java.util.regex.Pattern; 33 34 /** 35 * This class tests manual package install and uninstall by a device owner. 36 */ 37 public final class ManualPackageInstallTest extends BasePackageInstallTest { 38 39 private static final String TAG = ManualPackageInstallTest.class.getSimpleName(); 40 41 private static final int AUTOMATOR_WAIT_TIMEOUT = 5000; 42 private static final int INSTALL_WAIT_TIME = 5000; 43 44 private static final BySelector INSTALL_BUTTON_SELECTOR = By.text(Pattern.compile("Install", 45 Pattern.CASE_INSENSITIVE)); 46 47 private UiAutomation mUiAutomation; 48 private boolean mIsAutomotive; 49 50 @Override setUp()51 protected void setUp() throws Exception { 52 super.setUp(); 53 mUiAutomation = getInstrumentation().getUiAutomation(); 54 mIsAutomotive = mPackageManager.hasSystemFeature(PackageManager.FEATURE_AUTOMOTIVE); 55 } 56 testManualInstallSucceeded()57 public void testManualInstallSucceeded() throws Exception { 58 assertInstallPackage(); 59 } 60 testManualInstallBlocked()61 public void testManualInstallBlocked() throws Exception { 62 synchronized (mPackageInstallerTimeoutLock) { 63 mCallbackReceived = false; 64 mCallbackStatus = PACKAGE_INSTALLER_STATUS_UNDEFINED; 65 } 66 // Calls the original installPackage which does not click through the install button. 67 Log.d(TAG, "Installing " + TEST_APP_LOCATION); 68 super.installPackage(TEST_APP_LOCATION); 69 synchronized (mPackageInstallerTimeoutLock) { 70 try { 71 mPackageInstallerTimeoutLock.wait(PACKAGE_INSTALLER_TIMEOUT_MS); 72 } catch (InterruptedException e) { 73 Thread.currentThread().interrupt(); 74 Log.e(TAG, "Interrupted", e); 75 } 76 assertTrue(mCallbackReceived); 77 assertEquals(PackageInstaller.STATUS_PENDING_USER_ACTION, mCallbackStatus); 78 } 79 80 mCallbackIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); 81 Log.d(TAG, "Starting " + mCallbackIntent + " on user " + UserHandle.myUserId()); 82 mContext.startActivity(mCallbackIntent); 83 84 automateDismissInstallBlockedDialog(); 85 86 // Assuming installation is not synchronous, we should wait a while before checking. 87 Thread.sleep(INSTALL_WAIT_TIME); 88 assertFalse(isPackageInstalled(TEST_APP_PKG)); 89 } 90 91 @Override installPackage(String packageLocation)92 protected void installPackage(String packageLocation) throws Exception { 93 super.installPackage(packageLocation); 94 95 synchronized (mPackageInstallerTimeoutLock) { 96 try { 97 mPackageInstallerTimeoutLock.wait(PACKAGE_INSTALLER_TIMEOUT_MS); 98 } catch (InterruptedException e) { 99 } 100 assertTrue(mCallbackReceived); 101 assertEquals(PackageInstaller.STATUS_PENDING_USER_ACTION, mCallbackStatus); 102 } 103 104 // Use a receiver to listen for package install. 105 synchronized (mPackageInstallerTimeoutLock) { 106 mCallbackReceived = false; 107 mCallbackStatus = PACKAGE_INSTALLER_STATUS_UNDEFINED; 108 } 109 110 mCallbackIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); 111 mContext.startActivity(mCallbackIntent); 112 113 automateInstallClick(); 114 } 115 automateInstallClick()116 private void automateInstallClick() { 117 mDevice.wait(Until.hasObject(INSTALL_BUTTON_SELECTOR), AUTOMATOR_WAIT_TIMEOUT); 118 UiObject2 button = mDevice.findObject(INSTALL_BUTTON_SELECTOR); 119 assertNotNull("Install button not found", button); 120 button.click(); 121 } 122 automateDismissInstallBlockedDialog()123 private void automateDismissInstallBlockedDialog() { 124 BySelector selector = getPopUpImageSelector(); 125 mDevice.wait(Until.hasObject(selector), AUTOMATOR_WAIT_TIMEOUT); 126 UiObject2 icon = mDevice.findObject(selector); 127 assertNotNull("Policy transparency dialog icon not found: " + selector, icon); 128 // "OK" button only present in the dialog if it is blocked by policy. 129 UiObject2 button = mDevice.findObject(getPopUpButtonSelector()); 130 assertNotNull("OK button not found", button); 131 button.click(); 132 } 133 getSettingsPackageName()134 private String getSettingsPackageName() { 135 String settingsPackageName = mIsAutomotive 136 ? "com.android.car.settings" 137 : "com.android.settings"; 138 mUiAutomation.adoptShellPermissionIdentity("android.permission.INTERACT_ACROSS_USERS"); 139 try { 140 ResolveInfo resolveInfo = mPackageManager.resolveActivityAsUser( 141 new Intent(Settings.ACTION_SETTINGS), PackageManager.MATCH_SYSTEM_ONLY, 142 UserHandle.USER_SYSTEM); 143 if (resolveInfo != null && resolveInfo.activityInfo != null) { 144 settingsPackageName = resolveInfo.activityInfo.packageName; 145 } 146 } finally { 147 mUiAutomation.dropShellPermissionIdentity(); 148 } 149 Log.d(TAG, "getSettingsPackageName(): returning " + settingsPackageName); 150 return settingsPackageName; 151 } 152 getPopUpButtonSelector()153 private BySelector getPopUpButtonSelector() { 154 return By.clazz(android.widget.Button.class.getName()) 155 .res("android:id/button1") 156 .pkg(getSettingsPackageName()); 157 } 158 getPopUpImageSelector()159 private BySelector getPopUpImageSelector() { 160 final String settingsPackageName = getSettingsPackageName(); 161 final String resId = mIsAutomotive ? "car_ui_alert_icon" : "admin_support_icon"; 162 return By.clazz(android.widget.ImageView.class.getName()) 163 .res(settingsPackageName + ":id/" + resId) 164 .pkg(settingsPackageName); 165 } 166 } 167