blob: caa39a0954f7f23306d869437df31efb9f0469b7 [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 com.android.cts.rollback.lib;
import android.content.Intent;
import android.content.pm.PackageInstaller;
import androidx.test.InstrumentationRegistry;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
/**
* Helper class for installing test apps.
*/
public class Install {
private final boolean mIsMultiPackage;
private final TestApp[] mTestApps;
private boolean mIsStaged = false;
private boolean mEnableRollback = false;
private Install(boolean isMultiPackage, TestApp... testApps) {
mIsMultiPackage = isMultiPackage;
mTestApps = testApps;
}
/**
* Creates an Install builder to install a single package.
*/
public static Install single(TestApp testApp) {
return new Install(false, testApp);
}
/**
* Creates an Install builder to install using multiPackage.
*/
public static Install multi(TestApp... testApps) {
return new Install(true, testApps);
}
/**
* Makes the install a staged install.
*/
public Install setStaged() {
mIsStaged = true;
return this;
}
/**
* Enables rollback for the install.
*/
public Install setEnableRollback() {
mEnableRollback = true;
return this;
}
private static PackageInstaller getPackageInstaller() {
return InstrumentationRegistry.getContext().getPackageManager().getPackageInstaller();
}
/**
* Creates an empty install session with appropriate install params set.
*
* @return the session id of the newly created session
*/
private int createEmptyInstallSession(boolean multiPackage, boolean isApex)
throws IOException {
PackageInstaller.SessionParams params = new PackageInstaller.SessionParams(
PackageInstaller.SessionParams.MODE_FULL_INSTALL);
if (multiPackage) {
params.setMultiPackage();
}
if (isApex) {
params.setInstallAsApex();
}
if (mIsStaged) {
params.setStaged();
}
params.setEnableRollback(mEnableRollback);
return getPackageInstaller().createSession(params);
}
/**
* Creates an install session for the given test app.
*
* @return the session id of the newly created session.
*/
private int createInstallSession(TestApp app) throws IOException {
int sessionId = createEmptyInstallSession(/*multiPackage*/false, app.isApex());
PackageInstaller.Session session = getPackageInstaller().openSession(sessionId);
ClassLoader loader = TestApp.class.getClassLoader();
for (String resourceName : app.getResourceNames()) {
try (OutputStream os = session.openWrite(resourceName, 0, -1);
InputStream is = loader.getResourceAsStream(resourceName);) {
byte[] buffer = new byte[4096];
int n;
while ((n = is.read(buffer)) >= 0) {
os.write(buffer, 0, n);
}
}
}
session.close();
return sessionId;
}
/**
* Commits the install.
*/
public void commit() throws IOException, InterruptedException {
final int sessionId;
final PackageInstaller.Session session;
if (mIsMultiPackage) {
sessionId = createEmptyInstallSession(/*multiPackage*/ true, /*isApex*/false);
session = getPackageInstaller().openSession(sessionId);
for (TestApp app : mTestApps) {
session.addChildSessionId(createInstallSession(app));
}
} else {
assert mTestApps.length == 1;
sessionId = createInstallSession(mTestApps[0]);
session = getPackageInstaller().openSession(sessionId);
}
session.commit(LocalIntentSender.getIntentSender());
Intent result = LocalIntentSender.getIntentSenderResult();
int status = result.getIntExtra(PackageInstaller.EXTRA_STATUS,
PackageInstaller.STATUS_FAILURE);
if (status == -1) {
throw new AssertionError("PENDING USER ACTION");
} else if (status > 0) {
String message = result.getStringExtra(PackageInstaller.EXTRA_STATUS_MESSAGE);
throw new AssertionError(message == null ? "UNKNOWN FAILURE" : message);
}
if (mIsStaged) {
Utils.waitForSessionReady(sessionId);
}
}
}