Home | History | Annotate | Download | only in cts
      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
     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
    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 
    126     protected static ComponentName getWho() {
    127         return new ComponentName(PACKAGE_NAME, BasicAdminReceiver.class.getName());
    128     }
    129 
    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 
    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 
    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 
    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 
    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 
    212     protected int getInstallReason(String packageName) {
    213         return mPackageManager.getInstallReason(packageName, Process.myUserHandle());
    214     }
    215 
    216     protected void forceUninstall() throws Exception {
    217         runShellCommand("pm uninstall " + TEST_APP_PKG);
    218     }
    219 
    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