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 package android.packageinstaller.admin.cts; 17 18 import android.app.PendingIntent; 19 import android.app.admin.DevicePolicyManager; 20 import android.content.BroadcastReceiver; 21 import android.content.ComponentName; 22 import android.content.Context; 23 import android.content.Intent; 24 import android.content.IntentFilter; 25 import android.content.IntentSender; 26 import android.content.pm.PackageInfo; 27 import android.content.pm.PackageInstaller; 28 import android.content.pm.PackageManager; 29 import android.os.ParcelFileDescriptor; 30 import android.os.Process; 31 import android.support.test.uiautomator.UiDevice; 32 import android.test.InstrumentationTestCase; 33 34 import java.io.BufferedReader; 35 import java.io.File; 36 import java.io.FileInputStream; 37 import java.io.InputStream; 38 import java.io.InputStreamReader; 39 import java.io.OutputStream; 40 import java.util.ArrayList; 41 42 /** 43 * Base test case for testing PackageInstaller. 44 */ 45 public class BasePackageInstallTest extends InstrumentationTestCase { 46 protected static final String TEST_APP_LOCATION = 47 "/data/local/tmp/cts/packageinstaller/CtsEmptyTestApp.apk"; 48 protected static final String TEST_APP_PKG = "android.packageinstaller.emptytestapp.cts"; 49 protected static final int PACKAGE_INSTALLER_TIMEOUT_MS = 60000; // 60 seconds 50 private static final String ACTION_INSTALL_COMMIT = 51 "com.android.cts.deviceowner.INTENT_PACKAGE_INSTALL_COMMIT"; 52 protected static final int PACKAGE_INSTALLER_STATUS_UNDEFINED = -1000; 53 public static final String PACKAGE_NAME = SilentPackageInstallTest.class.getPackage().getName(); 54 55 protected Context mContext; 56 protected UiDevice mDevice; 57 protected DevicePolicyManager mDevicePolicyManager; 58 protected PackageManager mPackageManager; 59 private PackageInstaller mPackageInstaller; 60 private PackageInstaller.Session mSession; 61 protected boolean mCallbackReceived; 62 protected int mCallbackStatus; 63 protected Intent mCallbackIntent; 64 65 protected boolean mHasFeature; 66 67 protected final Object mPackageInstallerTimeoutLock = new Object(); 68 69 private final BroadcastReceiver mBroadcastReceiver = new BroadcastReceiver() { 70 @Override 71 public void onReceive(Context context, Intent intent) { 72 synchronized (mPackageInstallerTimeoutLock) { 73 mCallbackStatus = intent.getIntExtra(PackageInstaller.EXTRA_STATUS, 74 PACKAGE_INSTALLER_STATUS_UNDEFINED); 75 if (mCallbackStatus == PackageInstaller.STATUS_SUCCESS) { 76 mContext.unregisterReceiver(this); 77 assertEquals(TEST_APP_PKG, intent.getStringExtra( 78 PackageInstaller.EXTRA_PACKAGE_NAME)); 79 } else if (mCallbackStatus == PackageInstaller.STATUS_PENDING_USER_ACTION) { 80 mCallbackIntent = (Intent) intent.getExtras().get(Intent.EXTRA_INTENT); 81 } 82 mCallbackReceived = true; 83 mPackageInstallerTimeoutLock.notify(); 84 } 85 } 86 }; 87 88 @Override setUp()89 protected void setUp() throws Exception { 90 super.setUp(); 91 mContext = getInstrumentation().getContext(); 92 mDevice = UiDevice.getInstance(getInstrumentation()); 93 mDevicePolicyManager = (DevicePolicyManager) 94 mContext.getSystemService(Context.DEVICE_POLICY_SERVICE); 95 mPackageManager = mContext.getPackageManager(); 96 mPackageInstaller = mPackageManager.getPackageInstaller(); 97 assertNotNull(mPackageInstaller); 98 99 mHasFeature = mPackageManager.hasSystemFeature(PackageManager.FEATURE_DEVICE_ADMIN); 100 101 if (mHasFeature) { 102 forceUninstall(); 103 // check that app is not already installed 104 assertFalse(isPackageInstalled(TEST_APP_PKG)); 105 } 106 } 107 108 @Override tearDown()109 protected void tearDown() throws Exception { 110 if (mDevicePolicyManager.isDeviceOwnerApp(PACKAGE_NAME) || 111 mDevicePolicyManager.isProfileOwnerApp(PACKAGE_NAME)) { 112 mDevicePolicyManager.setUninstallBlocked(getWho(), TEST_APP_PKG, false); 113 } 114 try { 115 mContext.unregisterReceiver(mBroadcastReceiver); 116 } catch (IllegalArgumentException e) { 117 // ignore 118 } 119 if (mSession != null) { 120 mSession.abandon(); 121 } 122 123 super.tearDown(); 124 } 125 getWho()126 protected static ComponentName getWho() { 127 return new ComponentName(PACKAGE_NAME, BasicAdminReceiver.class.getName()); 128 } 129 assertInstallPackage()130 protected void assertInstallPackage() throws Exception { 131 assertFalse(isPackageInstalled(TEST_APP_PKG)); 132 synchronized (mPackageInstallerTimeoutLock) { 133 mCallbackReceived = false; 134 mCallbackStatus = PACKAGE_INSTALLER_STATUS_UNDEFINED; 135 } 136 installPackage(TEST_APP_LOCATION); 137 synchronized (mPackageInstallerTimeoutLock) { 138 try { 139 mPackageInstallerTimeoutLock.wait(PACKAGE_INSTALLER_TIMEOUT_MS); 140 } catch (InterruptedException e) { 141 } 142 assertTrue(mCallbackReceived); 143 assertEquals(PackageInstaller.STATUS_SUCCESS, mCallbackStatus); 144 } 145 assertTrue(isPackageInstalled(TEST_APP_PKG)); 146 } 147 tryUninstallPackage()148 protected boolean tryUninstallPackage() throws Exception { 149 assertTrue(isPackageInstalled(TEST_APP_PKG)); 150 synchronized (mPackageInstallerTimeoutLock) { 151 mCallbackReceived = false; 152 mCallbackStatus = PACKAGE_INSTALLER_STATUS_UNDEFINED; 153 } 154 mPackageInstaller.uninstall(TEST_APP_PKG, getCommitCallback(0)); 155 synchronized (mPackageInstallerTimeoutLock) { 156 try { 157 mPackageInstallerTimeoutLock.wait(PACKAGE_INSTALLER_TIMEOUT_MS); 158 } catch (InterruptedException e) { 159 } 160 assertTrue(mCallbackReceived); 161 return mCallbackStatus == PackageInstaller.STATUS_SUCCESS; 162 } 163 } 164 installPackage(String packageLocation)165 protected void installPackage(String packageLocation) throws Exception { 166 PackageInstaller.SessionParams params = new PackageInstaller.SessionParams( 167 PackageInstaller.SessionParams.MODE_FULL_INSTALL); 168 params.setAppPackageName(TEST_APP_PKG); 169 int sessionId = mPackageInstaller.createSession(params); 170 mSession = mPackageInstaller.openSession(sessionId); 171 172 File file = new File(packageLocation); 173 InputStream in = new FileInputStream(file); 174 OutputStream out = mSession.openWrite("SilentPackageInstallerTest", 0, file.length()); 175 byte[] buffer = new byte[65536]; 176 int c; 177 while ((c = in.read(buffer)) != -1) { 178 out.write(buffer, 0, c); 179 } 180 mSession.fsync(out); 181 out.close(); 182 mSession.commit(getCommitCallback(sessionId)); 183 mSession.close(); 184 } 185 getCommitCallback(int sessionId)186 private IntentSender getCommitCallback(int sessionId) { 187 // Create an intent-filter and register the receiver 188 String action = ACTION_INSTALL_COMMIT + "." + sessionId; 189 IntentFilter intentFilter = new IntentFilter(); 190 intentFilter.addAction(action); 191 mContext.registerReceiver(mBroadcastReceiver, intentFilter); 192 193 // Create a PendingIntent and use it to generate the IntentSender 194 Intent broadcastIntent = new Intent(action); 195 PendingIntent pendingIntent = PendingIntent.getBroadcast( 196 mContext, 197 sessionId, 198 broadcastIntent, 199 PendingIntent.FLAG_UPDATE_CURRENT); 200 return pendingIntent.getIntentSender(); 201 } 202 isPackageInstalled(String packageName)203 protected boolean isPackageInstalled(String packageName) { 204 try { 205 PackageInfo pi = mPackageManager.getPackageInfo(packageName, 0); 206 return pi != null; 207 } catch (PackageManager.NameNotFoundException e) { 208 return false; 209 } 210 } 211 getInstallReason(String packageName)212 protected int getInstallReason(String packageName) { 213 return mPackageManager.getInstallReason(packageName, Process.myUserHandle()); 214 } 215 forceUninstall()216 protected void forceUninstall() throws Exception { 217 runShellCommand("pm uninstall " + TEST_APP_PKG); 218 } 219 runShellCommand(String command)220 public ArrayList<String> runShellCommand(String command) throws Exception { 221 ParcelFileDescriptor pfd = getInstrumentation().getUiAutomation() 222 .executeShellCommand(command); 223 224 ArrayList<String> ret = new ArrayList<>(); 225 // Read the input stream fully. 226 try (BufferedReader r = new BufferedReader( 227 new InputStreamReader(new ParcelFileDescriptor.AutoCloseInputStream(pfd)))) { 228 String line; 229 while ((line = r.readLine()) != null) { 230 ret.add(line); 231 } 232 } 233 return ret; 234 } 235 } 236