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 com.android.cts.packageinstaller; 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.support.test.uiautomator.UiDevice; 30 import android.test.InstrumentationTestCase; 31 32 import com.android.cts.packageinstaller.ClearDeviceOwnerTest.BasicAdminReceiver; 33 34 import java.io.File; 35 import java.io.FileInputStream; 36 import java.io.InputStream; 37 import java.io.OutputStream; 38 39 /** 40 * Base test case for testing PackageInstaller. 41 */ 42 public class BasePackageInstallTest extends InstrumentationTestCase { 43 protected static final String TEST_APP_LOCATION = "/data/local/tmp/CtsSimpleApp.apk"; 44 protected static final String TEST_APP_PKG = "com.android.cts.launcherapps.simpleapp"; 45 protected static final int PACKAGE_INSTALLER_TIMEOUT_MS = 60000; // 60 seconds 46 private static final String ACTION_INSTALL_COMMIT = 47 "com.android.cts.deviceowner.INTENT_PACKAGE_INSTALL_COMMIT"; 48 protected static final int PACKAGE_INSTALLER_STATUS_UNDEFINED = -1000; 49 public static final String PACKAGE_NAME = BasePackageInstallTest.class.getPackage().getName(); 50 51 protected Context mContext; 52 protected UiDevice mDevice; 53 protected DevicePolicyManager mDevicePolicyManager; 54 protected PackageManager mPackageManager; 55 private PackageInstaller mPackageInstaller; 56 private PackageInstaller.Session mSession; 57 protected boolean mCallbackReceived; 58 protected int mCallbackStatus; 59 protected Intent mCallbackIntent; 60 61 protected final Object mPackageInstallerTimeoutLock = new Object(); 62 63 private final BroadcastReceiver mBroadcastReceiver = new BroadcastReceiver() { 64 @Override 65 public void onReceive(Context context, Intent intent) { 66 synchronized (mPackageInstallerTimeoutLock) { 67 mCallbackStatus = intent.getIntExtra(PackageInstaller.EXTRA_STATUS, 68 PACKAGE_INSTALLER_STATUS_UNDEFINED); 69 if (mCallbackStatus == PackageInstaller.STATUS_SUCCESS) { 70 mContext.unregisterReceiver(this); 71 assertEquals(TEST_APP_PKG, intent.getStringExtra( 72 PackageInstaller.EXTRA_PACKAGE_NAME)); 73 } else if (mCallbackStatus == PackageInstaller.STATUS_PENDING_USER_ACTION) { 74 mCallbackIntent = (Intent) intent.getExtras().get(Intent.EXTRA_INTENT); 75 } 76 mCallbackReceived = true; 77 mPackageInstallerTimeoutLock.notify(); 78 } 79 } 80 }; 81 82 @Override setUp()83 protected void setUp() throws Exception { 84 super.setUp(); 85 mContext = getInstrumentation().getContext(); 86 mDevice = UiDevice.getInstance(getInstrumentation()); 87 mDevicePolicyManager = (DevicePolicyManager) 88 mContext.getSystemService(Context.DEVICE_POLICY_SERVICE); 89 mPackageManager = mContext.getPackageManager(); 90 mPackageInstaller = mPackageManager.getPackageInstaller(); 91 assertNotNull(mPackageInstaller); 92 93 // check that app is not already installed 94 assertFalse(isPackageInstalled(TEST_APP_PKG)); 95 } 96 97 @Override tearDown()98 protected void tearDown() throws Exception { 99 if (mDevicePolicyManager.isDeviceOwnerApp(PACKAGE_NAME) || 100 mDevicePolicyManager.isProfileOwnerApp(PACKAGE_NAME)) { 101 mDevicePolicyManager.setUninstallBlocked(getWho(), TEST_APP_PKG, false); 102 } 103 try { 104 mContext.unregisterReceiver(mBroadcastReceiver); 105 } catch (IllegalArgumentException e) { 106 // ignore 107 } 108 if (mSession != null) { 109 mSession.abandon(); 110 } 111 super.tearDown(); 112 } 113 getWho()114 protected static ComponentName getWho() { 115 return new ComponentName(PACKAGE_NAME, BasicAdminReceiver.class.getName()); 116 } 117 assertInstallPackage()118 protected void assertInstallPackage() throws Exception { 119 assertFalse(isPackageInstalled(TEST_APP_PKG)); 120 assertTrue(executeAndWaitForPckageInstallCallback(() -> installPackage(TEST_APP_LOCATION))); 121 assertTrue(isPackageInstalled(TEST_APP_PKG)); 122 } 123 installPackage(String packageLocation)124 protected void installPackage(String packageLocation) throws Exception { 125 PackageInstaller.SessionParams params = new PackageInstaller.SessionParams( 126 PackageInstaller.SessionParams.MODE_FULL_INSTALL); 127 int sessionId = mPackageInstaller.createSession(params); 128 mSession = mPackageInstaller.openSession(sessionId); 129 130 File file = new File(packageLocation); 131 InputStream in = new FileInputStream(file); 132 OutputStream out = mSession.openWrite("SilentPackageInstallerTest", 0, file.length()); 133 byte[] buffer = new byte[65536]; 134 int c; 135 while ((c = in.read(buffer)) != -1) { 136 out.write(buffer, 0, c); 137 } 138 mSession.fsync(out); 139 out.close(); 140 mSession.commit(getCommitCallback(sessionId)); 141 mSession.close(); 142 } 143 getCommitCallback(int sessionId)144 private IntentSender getCommitCallback(int sessionId) { 145 // Create an intent-filter and register the receiver 146 String action = ACTION_INSTALL_COMMIT + "." + sessionId; 147 IntentFilter intentFilter = new IntentFilter(); 148 intentFilter.addAction(action); 149 mContext.registerReceiver(mBroadcastReceiver, intentFilter, 150 Context.RECEIVER_EXPORTED_UNAUDITED); 151 152 // Create a PendingIntent and use it to generate the IntentSender 153 Intent broadcastIntent = new Intent(action).setPackage(mContext.getPackageName()); 154 PendingIntent pendingIntent = PendingIntent.getBroadcast( 155 mContext, 156 sessionId, 157 broadcastIntent, 158 PendingIntent.FLAG_UPDATE_CURRENT | PendingIntent.FLAG_MUTABLE); 159 return pendingIntent.getIntentSender(); 160 } 161 isPackageInstalled(String packageName)162 protected boolean isPackageInstalled(String packageName) { 163 try { 164 PackageInfo pi = mPackageManager.getPackageInfo(packageName, 0); 165 return pi != null; 166 } catch (PackageManager.NameNotFoundException e) { 167 return false; 168 } 169 } 170 tryUninstallPackage()171 protected boolean tryUninstallPackage() throws Exception { 172 assertTrue(isPackageInstalled(TEST_APP_PKG)); 173 return executeAndWaitForPckageInstallCallback( 174 () -> mPackageInstaller.uninstall(TEST_APP_PKG, getCommitCallback(0))); 175 } 176 177 private interface ExceptionRunnable { run()178 void run() throws Exception; 179 } executeAndWaitForPckageInstallCallback(ExceptionRunnable task)180 private boolean executeAndWaitForPckageInstallCallback(ExceptionRunnable task) throws Exception { 181 synchronized (mPackageInstallerTimeoutLock) { 182 mCallbackReceived = false; 183 mCallbackStatus = PACKAGE_INSTALLER_STATUS_UNDEFINED; 184 } 185 task.run(); 186 synchronized (mPackageInstallerTimeoutLock) { 187 try { 188 mPackageInstallerTimeoutLock.wait(PACKAGE_INSTALLER_TIMEOUT_MS); 189 } catch (InterruptedException e) { 190 } 191 assertTrue(mCallbackReceived); 192 return mCallbackStatus == PackageInstaller.STATUS_SUCCESS; 193 } 194 } 195 } 196