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.managedprovisioning.task; 18 19 import static android.app.admin.DevicePolicyManager.ACTION_PROVISION_MANAGED_DEVICE; 20 import static com.android.managedprovisioning.task.InstallPackageTask.ERROR_INSTALLATION_FAILED; 21 import static com.android.managedprovisioning.task.InstallPackageTask.ERROR_PACKAGE_INVALID; 22 import static org.mockito.Matchers.any; 23 import static org.mockito.Matchers.anyInt; 24 import static org.mockito.Matchers.anyString; 25 import static org.mockito.Matchers.eq; 26 import static org.mockito.Mockito.never; 27 import static org.mockito.Mockito.verify; 28 import static org.mockito.Mockito.verifyNoMoreInteractions; 29 import static org.mockito.Mockito.when; 30 31 import android.content.Context; 32 import android.content.pm.IPackageInstallObserver; 33 import android.content.pm.PackageManager; 34 import android.net.Uri; 35 import android.test.AndroidTestCase; 36 import android.test.suitebuilder.annotation.SmallTest; 37 38 import com.android.managedprovisioning.common.SettingsFacade; 39 import com.android.managedprovisioning.model.ProvisioningParams; 40 41 import org.mockito.ArgumentCaptor; 42 import org.mockito.Mock; 43 import org.mockito.MockitoAnnotations; 44 45 public class InstallPackageTaskTest extends AndroidTestCase { 46 private static final String TEST_PACKAGE_NAME = "com.android.test"; 47 private static final String OTHER_PACKAGE_NAME = "com.android.other"; 48 private static final String TEST_PACKAGE_LOCATION = "/sdcard/TestPackage.apk"; 49 private static final ProvisioningParams TEST_PARAMS = new ProvisioningParams.Builder() 50 .setDeviceAdminPackageName(TEST_PACKAGE_NAME) 51 .setProvisioningAction(ACTION_PROVISION_MANAGED_DEVICE) 52 .build(); 53 private static final int TEST_USER_ID = 123; 54 55 @Mock private Context mContext; 56 @Mock private PackageManager mPackageManager; 57 @Mock private AbstractProvisioningTask.Callback mCallback; 58 @Mock private DownloadPackageTask mDownloadPackageTask; 59 private InstallPackageTask mTask; 60 private final SettingsFacade mSettingsFacade = new SettingsFacadeStub(); 61 62 @Override setUp()63 protected void setUp() throws Exception { 64 super.setUp(); 65 // this is necessary for mockito to work 66 System.setProperty("dexmaker.dexcache", getContext().getCacheDir().toString()); 67 MockitoAnnotations.initMocks(this); 68 69 when(mContext.getPackageManager()).thenReturn(mPackageManager); 70 when(mContext.getPackageName()).thenReturn(getContext().getPackageName()); 71 72 mTask = new InstallPackageTask(mSettingsFacade, mDownloadPackageTask, mContext, TEST_PARAMS, 73 mCallback); 74 } 75 76 @SmallTest testNoDownloadLocation()77 public void testNoDownloadLocation() { 78 // GIVEN no package was downloaded 79 when(mDownloadPackageTask.getDownloadedPackageLocation()).thenReturn(null); 80 81 // WHEN running the InstallPackageTask without specifying an install location 82 mTask.run(TEST_USER_ID); 83 // THEN no package is installed, but we get a success callback 84 verify(mPackageManager, never()).installPackage( 85 any(Uri.class), 86 any(IPackageInstallObserver.class), 87 anyInt(), 88 anyString()); 89 verify(mCallback).onSuccess(mTask); 90 verifyNoMoreInteractions(mCallback); 91 assertTrue(mSettingsFacade.isPackageVerifierEnabled(mContext)); 92 } 93 94 @SmallTest testSuccess()95 public void testSuccess() throws Exception { 96 // GIVEN a package was downloaded to TEST_LOCATION 97 when(mDownloadPackageTask.getDownloadedPackageLocation()).thenReturn(TEST_PACKAGE_LOCATION); 98 99 // WHEN running the InstallPackageTask specifying an install location 100 mTask.run(TEST_USER_ID); 101 102 // THEN package installed is invoked with an install observer 103 IPackageInstallObserver observer = verifyPackageInstalled(); 104 105 // WHEN the package installed callback is invoked with success 106 observer.packageInstalled(TEST_PACKAGE_NAME, PackageManager.INSTALL_SUCCEEDED); 107 108 // THEN we receive a success callback 109 verify(mCallback).onSuccess(mTask); 110 verifyNoMoreInteractions(mCallback); 111 assertTrue(mSettingsFacade.isPackageVerifierEnabled(mContext)); 112 } 113 114 @SmallTest testInstallFailedVersionDowngrade()115 public void testInstallFailedVersionDowngrade() throws Exception { 116 // GIVEN a package was downloaded to TEST_LOCATION 117 when(mDownloadPackageTask.getDownloadedPackageLocation()).thenReturn(TEST_PACKAGE_LOCATION); 118 119 // WHEN running the InstallPackageTask with a package already at a higher version 120 mTask.run(TEST_USER_ID); 121 122 // THEN package installed is invoked with an install observer 123 IPackageInstallObserver observer = verifyPackageInstalled(); 124 125 // WHEN the package installed callback is invoked with version downgrade error 126 observer.packageInstalled(null, PackageManager.INSTALL_FAILED_VERSION_DOWNGRADE); 127 128 // THEN we get a success callback, because an existing version of the DPC is present 129 verify(mCallback).onSuccess(mTask); 130 verifyNoMoreInteractions(mCallback); 131 assertTrue(mSettingsFacade.isPackageVerifierEnabled(mContext)); 132 } 133 134 @SmallTest testInstallFailedOtherError()135 public void testInstallFailedOtherError() throws Exception { 136 // GIVEN a package was downloaded to TEST_LOCATION 137 when(mDownloadPackageTask.getDownloadedPackageLocation()).thenReturn(TEST_PACKAGE_LOCATION); 138 139 // WHEN running the InstallPackageTask with a package already at a higher version 140 mTask.run(TEST_USER_ID); 141 142 // THEN package installed is invoked with an install observer 143 IPackageInstallObserver observer = verifyPackageInstalled(); 144 145 // WHEN the package installed callback is invoked with version downgrade error 146 observer.packageInstalled(null, PackageManager.INSTALL_FAILED_INVALID_APK); 147 148 // THEN we get a success callback, because an existing version of the DPC is present 149 verify(mCallback).onError(mTask, ERROR_INSTALLATION_FAILED); 150 verifyNoMoreInteractions(mCallback); 151 assertTrue(mSettingsFacade.isPackageVerifierEnabled(mContext)); 152 } 153 154 @SmallTest testDifferentPackageName()155 public void testDifferentPackageName() throws Exception { 156 // GIVEN a package was downloaded to TEST_LOCATION 157 when(mDownloadPackageTask.getDownloadedPackageLocation()).thenReturn(TEST_PACKAGE_LOCATION); 158 159 // WHEN running the InstallPackageTask with a package already at a higher version 160 mTask.run(TEST_USER_ID); 161 162 // THEN package installed is invoked with an install observer 163 IPackageInstallObserver observer = verifyPackageInstalled(); 164 165 // WHEN the package installed callback is invoked with version downgrade error 166 observer.packageInstalled(OTHER_PACKAGE_NAME, PackageManager.INSTALL_SUCCEEDED); 167 168 // THEN we get a success callback, because an existing version of the DPC is present 169 verify(mCallback).onError(mTask, ERROR_PACKAGE_INVALID); 170 verifyNoMoreInteractions(mCallback); 171 assertTrue(mSettingsFacade.isPackageVerifierEnabled(mContext)); 172 } 173 verifyPackageInstalled()174 private IPackageInstallObserver verifyPackageInstalled() { 175 ArgumentCaptor<IPackageInstallObserver> observerCaptor 176 = ArgumentCaptor.forClass(IPackageInstallObserver.class); 177 ArgumentCaptor<Integer> flagsCaptor = ArgumentCaptor.forClass(Integer.class); 178 // THEN the package is installed and we get a success callback 179 verify(mPackageManager).installPackage( 180 eq(Uri.parse("file://" + TEST_PACKAGE_LOCATION)), 181 observerCaptor.capture(), 182 flagsCaptor.capture(), 183 eq(getContext().getPackageName())); 184 // make sure that the flags value has been set 185 assertTrue(0 != (flagsCaptor.getValue() & PackageManager.INSTALL_REPLACE_EXISTING)); 186 return observerCaptor.getValue(); 187 } 188 189 private static class SettingsFacadeStub extends SettingsFacade { 190 private boolean mPackageVerifierEnabled = true; 191 192 @Override isPackageVerifierEnabled(Context c)193 public boolean isPackageVerifierEnabled(Context c) { 194 return mPackageVerifierEnabled; 195 } 196 197 @Override setPackageVerifierEnabled(Context c, boolean packageVerifierEnabled)198 public void setPackageVerifierEnabled(Context c, boolean packageVerifierEnabled) { 199 mPackageVerifierEnabled = packageVerifierEnabled; 200 } 201 } 202 } 203