blob: ac7596749584faea05dc2293aa6a46ee1b34d428 [file] [log] [blame]
/*
* Copyright (C) 2021 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.bedstead.testapp;
import static com.android.compatibility.common.util.FileUtils.readInputStreamFully;
import android.content.Context;
import android.os.Bundle;
import android.os.UserHandle;
import androidx.annotation.Nullable;
import com.android.bedstead.nene.TestApis;
import com.android.bedstead.nene.exceptions.NeneException;
import com.android.bedstead.nene.packages.Package;
import com.android.bedstead.nene.users.UserReference;
import com.android.bedstead.nene.users.Users;
import com.android.bedstead.testapp.processor.annotations.TestAppSender;
import com.android.queryable.info.ActivityInfo;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.Objects;
import java.util.Set;
/** Represents a single test app which can be installed and interacted with. */
@TestAppSender
public final class TestApp {
// Must be instrumentation context to access resources
private static final Context sContext = TestApis.context().instrumentationContext();
private final TestAppDetails mDetails;
TestApp(TestAppDetails details) {
if (details == null) {
throw new NullPointerException();
}
mDetails = details;
}
/**
* Get a {@link Package} for the {@link TestApp}.
*
* <p>This will only be resolvable after the app is installed.
*/
public Package pkg() {
return TestApis.packages().find(packageName());
}
/**
* Install the {@link TestApp} on the device for the instrumented user.
*
* <p>See {@link Users#instrumented()}
*/
public TestAppInstance install() {
return install(TestApis.users().instrumented());
}
/**
* Install the {@link TestApp} on the device for the given {@link UserReference}.
*/
public TestAppInstance install(UserReference user) {
try {
pkg().installBytes(user, this::apkBytes);
} catch (NeneException e) {
throw new NeneException("Error while installing TestApp " + this, e);
}
return new TestAppInstance(this, user);
}
/**
* Install the {@link TestApp} on the device for the given {@link UserHandle}.
*/
public TestAppInstance install(UserHandle user) {
install(TestApis.users().find(user));
return instance(user);
}
/**
* Uninstall the {@link TestApp} on the device from the instrumented user.
*
* <p>See {@link Users#instrumented()}
*/
public void uninstall() {
uninstall(TestApis.users().instrumented());
}
/**
* Uninstall the {@link TestApp} from the device from all users.
*/
public void uninstallFromAllUsers() {
pkg().uninstallFromAllUsers();
}
/**
* Uninstall the {@link TestApp} on the device from the given {@link UserReference}.
*/
public void uninstall(UserReference user) {
pkg().uninstall(user);
}
/**
* Uninstall the {@link TestApp} on the device from the given {@link UserHandle}.
*/
public void uninstall(UserHandle user) {
uninstall(TestApis.users().find(user));
}
/**
* Get a reference to the specific instance of this test app on a given user.
*
* <p>This does not check if the user exists, or if the test app is installed on the user.
*/
public TestAppInstance instance(UserHandle user) {
return instance(TestApis.users().find(user));
}
/**
* Get a reference to the specific instance of this test app on a given user.
*
* <p>This does not check if the user exists, or if the test app is installed on the user.
*/
public TestAppInstance instance(UserReference user) {
if (user == null) {
throw new NullPointerException();
}
return new TestAppInstance(this, user);
}
private byte[] apkBytes() {
try (InputStream inputStream =
sContext.getResources().openRawResource(mDetails.mResourceIdentifier)) {
return readInputStreamFully(inputStream);
} catch (IOException e) {
throw new NeneException("Error when reading TestApp bytes", e);
}
}
/** Write the APK file to the given {@link File}. */
public void writeApkFile(File outputFile) throws IOException {
outputFile.getParentFile().mkdirs();
try (FileOutputStream output = new FileOutputStream(outputFile)) {
output.write(apkBytes());
}
}
/** The package name of the test app. */
public String packageName() {
return mDetails.mApp.getPackageName();
}
/** The testOnly attribute for the test app. */
public boolean testOnly() {
return mDetails.mApp.getTestOnly();
}
/** The minSdkVersion of the test app. */
public int minSdkVersion() {
return mDetails.mApp.getUsesSdk().getMinSdkVersion();
}
/** The maxSdkVersion of the test app. */
public int maxSdkVersion() {
return mDetails.mApp.getUsesSdk().getMaxSdkVersion();
}
/** The targetSdkVersion of the test app. */
public int targetSdkVersion() {
return mDetails.mApp.getUsesSdk().getTargetSdkVersion();
}
/** The permissions declared by the test app. */
public Set<String> permissions() {
return mDetails.mPermissions;
}
/** The activities which exist in the test app. */
public Set<ActivityInfo> activities() {
return mDetails.mActivities;
}
/**
* The metadata declared by the test app.
*
* <p>Note that currently all values are of type String.
*/
public Bundle metadata() {
return mDetails.mMetadata;
}
@Override
public String toString() {
return "TestApp{"
+ "packageName=" + packageName()
+ ", details=" + mDetails
+ "}";
}
/** The shared user id of the test app, if any. */
@Nullable
public String sharedUserId() {
return mDetails.sharedUserId();
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (!(o instanceof TestApp)) return false;
TestApp testApp = (TestApp) o;
return mDetails.mApp.getPackageName().equals(testApp.mDetails.mApp.getPackageName());
}
@Override
public int hashCode() {
return Objects.hash(mDetails.mApp.getPackageName());
}
}