blob: a433d801acaf664c9b7de453e57909c182536535 [file] [log] [blame]
/*
* Copyright (C) 2019 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package android.perftests.utils;
import android.app.PendingIntent;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.content.IntentSender;
import android.content.pm.PackageInstaller;
import android.content.res.Resources;
import android.util.Log;
import org.junit.Assert;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.LinkedBlockingQueue;
/**
* Installs packages included within the assets directory.
*/
public class TestPackageInstaller {
private static final String LOG_TAG = "TestPackageInstaller";
private static final String BROADCAST_ACTION =
"com.android.perftests.core.ACTION_INSTALL_COMMIT";
private final Context mContext;
public TestPackageInstaller(Context context) {
mContext = context;
}
/**
* Installs an APK located at the specified path in the assets directory.
**/
public InstalledPackage installPackage(String resourceName) throws IOException,
InterruptedException {
Log.d(LOG_TAG, "Installing resource APK '" + resourceName + "'");
LocalBroadcastReceiver intentSender = new LocalBroadcastReceiver(mContext);
// Initialize the package install session.
PackageInstaller packageInstaller = mContext.getPackageManager().getPackageInstaller();
PackageInstaller.SessionParams params = new PackageInstaller.SessionParams(
PackageInstaller.SessionParams.MODE_FULL_INSTALL);
params.setInstallAsInstantApp(false);
int sessionId = packageInstaller.createSession(params);
PackageInstaller.Session session = packageInstaller.openSession(sessionId);
// Copy the apk to the install session.
try (OutputStream os = session.openWrite("TestPackageInstaller", 0, -1);
InputStream is = mContext.getResources().getAssets().openNonAsset(resourceName)) {
if (is == null) {
throw new IOException("Resource " + resourceName + " not found");
}
byte[] buffer = new byte[4096];
int n;
while ((n = is.read(buffer)) >= 0) {
os.write(buffer, 0, n);
}
}
session.commit(intentSender.getIntentSender(sessionId));
session.close();
// Retrieve the results of the installation.
Intent intent = intentSender.getIntentSenderResult();
int status = intent.getIntExtra(PackageInstaller.EXTRA_STATUS,
PackageInstaller.STATUS_FAILURE);
Assert.assertEquals(PackageInstaller.STATUS_SUCCESS, status);
String packageName = intent.getStringExtra(PackageInstaller.EXTRA_PACKAGE_NAME);
return new InstalledPackage(sessionId, packageName);
}
public class InstalledPackage {
private int mSessionId;
private String mPackageName;
private InstalledPackage(int sessionId, String packageName) {
mSessionId = sessionId;
mPackageName = packageName;
}
public String getPackageName() {
return mPackageName;
}
public void uninstall() throws Exception {
Log.d(LOG_TAG, "Uninstalling package '" + mPackageName + "'");
LocalBroadcastReceiver intentSender = new LocalBroadcastReceiver(mContext);
PackageInstaller packageInstaller = mContext.getPackageManager().getPackageInstaller();
packageInstaller.uninstall(mPackageName, intentSender.getIntentSender(mSessionId));
int status = intentSender.getIntentSenderResult()
.getIntExtra(PackageInstaller.EXTRA_STATUS, PackageInstaller.STATUS_FAILURE);
Assert.assertEquals(PackageInstaller.STATUS_SUCCESS, status);
}
}
private class LocalBroadcastReceiver extends BroadcastReceiver {
private final BlockingQueue<Intent> mIntentSenderResults = new LinkedBlockingQueue<>();
private final Context mContext;
private LocalBroadcastReceiver(Context context) {
mContext = context;
}
@Override
public void onReceive(Context context, Intent intent) {
mIntentSenderResults.add(intent);
}
IntentSender getIntentSender(int sessionId) {
String action = BROADCAST_ACTION + "." + sessionId;
IntentFilter filter = new IntentFilter(action);
mContext.registerReceiver(this, filter);
Intent intent = new Intent(action);
PendingIntent pending = PendingIntent.getBroadcast(mContext, sessionId, intent,
PendingIntent.FLAG_UPDATE_CURRENT);
return pending.getIntentSender();
}
Intent getIntentSenderResult() throws InterruptedException {
return mIntentSenderResults.take();
}
}
}