blob: 281df8f3cec097e7567cc92d2a0e62432f7222d7 [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 android.scopedstorage.cts.host;
import static com.google.common.truth.Truth.assertThat;
import static org.junit.Assume.assumeFalse;
import static org.junit.Assume.assumeTrue;
import android.platform.test.annotations.AppModeFull;
import com.android.tradefed.device.DeviceNotAvailableException;
import com.android.tradefed.device.contentprovider.ContentProviderHandler;
import com.android.tradefed.targetprep.TargetSetupError;
import com.android.tradefed.testtype.DeviceJUnit4ClassRunner;
import com.android.tradefed.util.CommandResult;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
/**
* Runs the AppCloning tests.
*/
@RunWith(DeviceJUnit4ClassRunner.class)
@AppModeFull
public class AppCloningHostTest extends BaseHostTestCase {
private static final String APP_A = "CtsScopedStorageTestAppA.apk";
private static final String APP_A_PACKAGE = "android.scopedstorage.cts.testapp.A.withres";
private static final String CONTENT_PROVIDER_URL = "content://android.tradefed.contentprovider";
private static final int CLONE_PROFILE_DIRECTORY_CREATION_TIMEOUT_MS = 20000;
private String mCloneUserId;
private ContentProviderHandler mContentProviderHandler;
@Before
public void setup() throws Exception {
assumeFalse("Device is in headless system user mode", isHeadlessSystemUserMode());
assumeTrue(isAtLeastS());
String output = executeShellCommand(
"pm create-user --profileOf 0 --user-type android.os.usertype.profile.CLONE "
+ "testUser");
mCloneUserId = output.substring(output.lastIndexOf(' ') + 1).replaceAll("[^0-9]", "");
assertThat(mCloneUserId).isNotEmpty();
CommandResult out = executeShellV2Command("am start-user -w %s", mCloneUserId);
assertThat(out.getStderr()).isEmpty();
mContentProviderHandler = new ContentProviderHandler(getDevice());
mContentProviderHandler.setUp();
}
@After
public void tearDown() throws Exception {
if (isHeadlessSystemUserMode() || !isAtLeastS()) return;
mContentProviderHandler.tearDown();
executeShellCommand("pm remove-user %s", mCloneUserId);
}
@Test
public void testInstallAppTwice() throws Exception {
installAppAsUser(APP_A, getCurrentUserId());
installAppAsUser(APP_A, Integer.valueOf(mCloneUserId));
uninstallPackage(APP_A_PACKAGE);
}
@Test
public void testCreateCloneUserFile() throws Exception {
CommandResult out;
// Check that the clone user directories exist
eventually(() -> {
// Wait for finish.
assertThat(isSuccessful(
runContentProviderCommand("query", mCloneUserId, "/sdcard", ""))).isTrue();
}, CLONE_PROFILE_DIRECTORY_CREATION_TIMEOUT_MS);
// Create a file on the clone user storage
out = executeShellV2Command("touch /sdcard/testFile.txt");
assertThat(isSuccessful(out)).isTrue();
eventually(() -> {
// Wait for finish.
assertThat(isSuccessful(
runContentProviderCommand("write", mCloneUserId, "/sdcard/testFile.txt",
"< /sdcard/testFile.txt"))).isTrue();
}, CLONE_PROFILE_DIRECTORY_CREATION_TIMEOUT_MS);
// Check that the above created file exists on the clone user storage
out = runContentProviderCommand("query", mCloneUserId, "/sdcard/testFile.txt", "");
assertThat(isSuccessful(out)).isTrue();
// Cleanup the created file
out = runContentProviderCommand("delete", mCloneUserId, "/sdcard/testFile.txt", "");
assertThat(isSuccessful(out)).isTrue();
}
@Test
public void testPrivateAppDataDirectoryForCloneUser() throws Exception {
installAppAsUser(APP_A, Integer.valueOf(mCloneUserId));
eventually(() -> {
// Wait for finish.
assertThat(isPackageInstalled(APP_A_PACKAGE, mCloneUserId)).isTrue();
}, CLONE_PROFILE_DIRECTORY_CREATION_TIMEOUT_MS);
}
private void installAppAsUser(String packageFile, int userId)
throws TargetSetupError, DeviceNotAvailableException {
installPackageAsUser(packageFile, false, userId, "-t");
}
private CommandResult runContentProviderCommand(String commandType, String userId,
String relativePath, String args) throws Exception {
String fullUri = CONTENT_PROVIDER_URL + relativePath;
return executeShellV2Command("content %s --user %s --uri %s %s",
commandType, userId, fullUri, args);
}
}