Skip to content

Commit aaa906b

Browse files
Ensure UTP is multi-linux-user compatible.
PiperOrigin-RevId: 858721730
1 parent 5b83cd9 commit aaa906b

9 files changed

Lines changed: 37 additions & 52 deletions

File tree

services/CHANGELOG.md

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,14 +2,21 @@
22

33
{{date}}
44

5+
<!-- disableFinding(LINE_OVER_80) -->
56
`androidx.test.services:test-services:{version}` `androidx.test.services:storage:{version}` are released.
67

78
**Bug Fixes**
89

10+
* Ensure TestStorage library is multi-linux-user compatible.
11+
912
**New Features**
1013

1114
**Breaking Changes**
1215

16+
* The location where TestStorage stores files has changed. This is non-breaking
17+
if using the TestStorage API, but breaking if tests depended on the explicit
18+
location of the files (e.g., by reading them without using TestStorage).
19+
1320
**API Changes**
1421

1522
* Update to minSdkVersion 23 and remove all related logic for SDKs < 23

services/storage/java/androidx/test/services/storage/file/BUILD

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,6 @@ android_library(
1515
name = "file",
1616
srcs = glob(["*.java"]),
1717
deps = [
18-
"//opensource/androidx:annotation",
1918
"//runner/monitor",
2019
"//services/storage/java/androidx/test/services/storage:test_storage_constants",
2120
],

services/storage/java/androidx/test/services/storage/file/HostedFile.java

Lines changed: 5 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -17,13 +17,11 @@
1717

1818
import android.content.Context;
1919
import android.net.Uri;
20+
import android.os.Build;
2021
import android.os.Environment;
21-
import android.os.UserManager;
2222
import android.provider.OpenableColumns;
23-
import android.util.Log;
2423
import androidx.test.services.storage.TestStorageConstants;
2524
import java.io.File;
26-
import java.util.concurrent.atomic.AtomicBoolean;
2725

2826
import androidx.annotation.RestrictTo;
2927
import androidx.annotation.RestrictTo.Scope;
@@ -38,8 +36,6 @@ public final class HostedFile {
3836

3937
private static final String TAG = "HostedFile";
4038

41-
private static final AtomicBoolean loggedOutputDir = new AtomicBoolean(false);
42-
4339
/** An enum of the columns returned by the hosted file service. */
4440
public enum HostedFileColumn {
4541
NAME("name", String.class, 3 /* Cursor.FIELD_TYPE_STRING since api 11 */, 0),
@@ -152,20 +148,11 @@ public static File getInputRootDirectory(Context context) {
152148
}
153149

154150
public static File getOutputRootDirectory(Context context) {
155-
UserManager userManager = (UserManager) context.getSystemService(Context.USER_SERVICE);
156-
if (userManager.isSystemUser()) {
157-
return Environment.getExternalStorageDirectory();
151+
// Use a reliably self-writable directory.
152+
if (Build.VERSION.SDK_INT >= 29) {
153+
return context.getExternalFilesDir(null);
158154
} else {
159-
// using legacy external storage for output in automotive devices where tests run as
160-
// a secondary user has been flaky. So use local storage instead.
161-
if (!loggedOutputDir.getAndSet(true)) {
162-
// limit log spam by only logging choice once
163-
Log.d(
164-
TAG,
165-
"Secondary user detected. Choosing local storage as output root dir: "
166-
+ context.getCacheDir().getAbsolutePath());
167-
}
168-
return context.getCacheDir();
155+
return Environment.getExternalStorageDirectory();
169156
}
170157
}
171158

services/storage/java/androidx/test/services/storage/provider/BUILD

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ android_library(
1515
manifest = "AndroidManifest.xml",
1616
deps = [
1717
"//runner/monitor",
18+
"//services/storage",
1819
"//services/storage/java/androidx/test/services/storage:storage_service_pb_java_proto_lite",
1920
"//services/storage/java/androidx/test/services/storage:test_storage_constants",
2021
"//services/storage/java/androidx/test/services/storage/file",

services/storage/java/androidx/test/services/storage/provider/InternalUseOnlyFilesContentProvider.java

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -25,9 +25,10 @@ public final class InternalUseOnlyFilesContentProvider extends AbstractFileConte
2525

2626
@Override
2727
protected File getHostedDirectory(Context context) {
28-
// use input root directory here, as TestArgsContentProvider also uses this directory
28+
// Uses the output root directory since the provider is Read/Write and only the output directory
29+
// is guaranteed to be writable.
2930
return new File(
30-
HostedFile.getInputRootDirectory(context),
31+
HostedFile.getOutputRootDirectory(context),
3132
TestStorageConstants.ON_DEVICE_PATH_INTERNAL_USE);
3233
}
3334

services/storage/java/androidx/test/services/storage/provider/TestArgsContentProvider.java

Lines changed: 20 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -25,15 +25,18 @@
2525
import android.net.Uri;
2626
import android.util.Log;
2727
import androidx.test.services.storage.TestStorageConstants;
28+
import androidx.test.services.storage.TestStorageException;
2829
import androidx.test.services.storage.TestStorageServiceProto.TestArgument;
2930
import androidx.test.services.storage.TestStorageServiceProto.TestArguments;
3031
import androidx.test.services.storage.file.HostedFile;
32+
import androidx.test.services.storage.file.HostedFile.FileHost;
3133
import androidx.test.services.storage.file.PropertyFile;
3234
import androidx.test.services.storage.file.PropertyFile.Authority;
35+
import androidx.test.services.storage.internal.TestStorageUtil;
3336
import java.io.File;
3437
import java.io.FileInputStream;
3538
import java.io.IOException;
36-
import java.lang.reflect.Method;
39+
import java.io.InputStream;
3740
import java.util.HashMap;
3841
import java.util.Map;
3942
import java.util.Map.Entry;
@@ -48,17 +51,6 @@
4851
public final class TestArgsContentProvider extends ContentProvider {
4952

5053
private static final String TAG = "TestArgCP";
51-
private static final String ANDROID_TEST_SERVER_SPEC_FORMAT = "_server_address";
52-
53-
private static final String SYSTEM_PROPERTY_CLAZZ = "android.os.SystemProperties";
54-
private static final String GET_METHOD = "get";
55-
56-
private String systemPropertyClassName;
57-
private Method getString;
58-
59-
void setSystemPropertyClassNameForTest(String className) {
60-
this.systemPropertyClassName = className;
61-
}
6254

6355
@Override
6456
public int delete(Uri arg0, String arg1, String[] arg2) {
@@ -119,13 +111,28 @@ private Map<String, String> buildArgMapFromFile() {
119111
}
120112

121113
private static TestArguments readProtoFromFile(Context context) {
114+
// File written by the InternalUseOnlyFilesContentProvider
115+
Uri testArgsProtoUri =
116+
HostedFile.buildUri(FileHost.INTERNAL_USE_ONLY, TestStorageConstants.TEST_ARGS_FILE_NAME);
117+
118+
try (InputStream testArgsProtoInputStream =
119+
TestStorageUtil.getInputStream(testArgsProtoUri, context.getContentResolver())) {
120+
Log.i(TAG, "Parsing test args from URI: " + testArgsProtoUri);
121+
return TestArguments.parseFrom(testArgsProtoInputStream);
122+
} catch (IOException | TestStorageException e) {
123+
Log.i(
124+
TAG,
125+
"Test args file not found via URI: " + testArgsProtoUri + ". Checking file system...");
126+
}
127+
128+
// File written directly to /sdcard/
122129
File testArgsFile =
123130
new File(
124131
HostedFile.getInputRootDirectory(context),
125132
TestStorageConstants.ON_DEVICE_PATH_INTERNAL_USE
126133
+ TestStorageConstants.TEST_ARGS_FILE_NAME);
127134
if (!testArgsFile.exists()) {
128-
Log.i(TAG, "Test args file not found at " + testArgsFile.getAbsolutePath());
135+
Log.i(TAG, "Test args file also not found at " + testArgsFile.getAbsolutePath());
129136
return TestArguments.getDefaultInstance();
130137
}
131138
try {

services/storage/javatests/androidx/test/services/storage/BUILD

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,6 @@ axt_android_library_test(
3030
],
3131
deps = [
3232
"//core/java/androidx/test/core",
33-
"//runner/monitor/java/androidx/test:monitor",
3433
"//services/storage/java/androidx/test/services/storage",
3534
"//services/storage/java/androidx/test/services/storage/file",
3635
"@maven//:com_google_truth_truth",

services/storage/javatests/androidx/test/services/storage/TestStorageTest.java

Lines changed: 0 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -19,11 +19,8 @@
1919
import static com.google.common.truth.Truth.assertThat;
2020
import static junit.framework.TestCase.fail;
2121
import static org.junit.Assert.assertEquals;
22-
import static org.junit.Assume.assumeTrue;
2322

24-
import android.content.Context;
2523
import android.net.Uri;
26-
import android.os.UserManager;
2724
import androidx.test.services.storage.file.HostedFile;
2825
import androidx.test.services.storage.internal.TestStorageUtil;
2926
import java.io.BufferedReader;
@@ -113,19 +110,11 @@ public void addOutputProperties() throws Exception {
113110

114111
@Test
115112
public void writeInternalFile() throws IOException {
116-
// known not to work in multi-user mode
117-
assumeTrue(isSystemUser());
118113
try (OutputStream output = testStorage.openInternalOutputFile("path/to/file")) {
119114
output.write(new byte[] {'h', 'e', 'l', 'l', 'o'});
120115
}
121116
}
122117

123-
private static boolean isSystemUser() {
124-
125-
UserManager um = ((UserManager) getApplicationContext().getSystemService(Context.USER_SERVICE));
126-
return um.isSystemUser();
127-
}
128-
129118
@Test
130119
public void readWriteOverwriteReadFile() throws IOException {
131120
try (OutputStream output = testStorage.openOutputFile("path/to/file")) {

services/storage/javatests/androidx/test/services/storage/provider/TestArgsContentProviderTest.java

Lines changed: 1 addition & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -31,11 +31,7 @@
3131
import java.util.HashMap;
3232
import java.util.Map;
3333

34-
/**
35-
* Unit tests for {@link TestArgsContentProvider}.
36-
*
37-
* TODO(b/145236542): Converts the tests to JUnit4.
38-
*/
34+
/** Unit tests for {@link TestArgsContentProvider}. */
3935
public class TestArgsContentProviderTest extends ProviderTestCase2<TestArgsContentProvider> {
4036

4137
private static final String[] ARGS = {"arg1", "arg2", "arg3", "someth_server_address"};
@@ -50,7 +46,6 @@ public TestArgsContentProviderTest() {
5046
@Override
5147
public void setUp() throws Exception {
5248
super.setUp();
53-
getProvider().setSystemPropertyClassNameForTest(FakeSystemProperties.class.getName());
5449
}
5550

5651
@Override

0 commit comments

Comments
 (0)