Skip to content

Commit 0733bc6

Browse files
brettchabotcopybara-androidxtest
authored andcommitted
Make GrantPermissionRule use UiAutomation#grantRuntimePermissions on APIs >=28.
Previously GrantPermissionRule used 'adb shell pm grant' to grant permissions. This commit switches the logic to use grantRuntimePermissions instead when it is available. The hope being this will result in better performance and reliability especially in automotive multi user scenarios. PiperOrigin-RevId: 625877361
1 parent 7fd9cfe commit 0733bc6

File tree

5 files changed

+78
-2
lines changed

5 files changed

+78
-2
lines changed

runner/android_junit_runner/CHANGELOG.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
**Bug Fixes**
88

99
* When logging test exceptions, use Log's built-in support for throwables to avoid stack truncation
10-
10+
* Internal changes to support GrantPermissionRule using UiAutomation#grantRuntimePermissions
1111

1212
**New Features**
1313

runner/android_junit_runner/java/androidx/test/api/current_internal.txt

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,12 @@ package androidx.test.runner.permission {
88
method @VisibleForTesting protected void setAndroidRuntimeVersion(int);
99
}
1010

11+
@RequiresApi(28) @RestrictTo(androidx.annotation.RestrictTo.Scope.LIBRARY_GROUP) public class UiAutomationPermissionGranter implements androidx.test.internal.platform.content.PermissionGranter {
12+
ctor public UiAutomationPermissionGranter();
13+
method public void addPermissions(java.lang.String!...);
14+
method public void requestPermissions();
15+
}
16+
1117
}
1218

1319
package @RestrictTo(androidx.annotation.RestrictTo.Scope.LIBRARY_GROUP) @RestrictTo({androidx.annotation.RestrictTo.Scope.LIBRARY_GROUP}) androidx.test.services.events {
Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
1+
package androidx.test.runner.permission;
2+
3+
import android.app.UiAutomation;
4+
import android.content.Context;
5+
import android.content.pm.PackageManager;
6+
import android.util.Log;
7+
import androidx.annotation.NonNull;
8+
import androidx.annotation.RequiresApi;
9+
import androidx.annotation.RestrictTo;
10+
import androidx.annotation.RestrictTo.Scope;
11+
import androidx.test.internal.platform.content.PermissionGranter;
12+
import androidx.test.platform.app.InstrumentationRegistry;
13+
import java.util.Collections;
14+
import java.util.LinkedHashSet;
15+
import java.util.Set;
16+
17+
/**
18+
* A {@link PermissionGranter} that uses {@link
19+
* android.app.UiAutomation#grantRuntimePermission(String, String)}
20+
*
21+
* @hide
22+
*/
23+
@RestrictTo(Scope.LIBRARY_GROUP)
24+
@RequiresApi(28)
25+
public class UiAutomationPermissionGranter implements PermissionGranter {
26+
private static final String TAG = "UiAutomationPermGranter";
27+
private final Set<String> permissionsToGrant = new LinkedHashSet<>();
28+
29+
@Override
30+
public void addPermissions(@NonNull String... permissions) {
31+
Collections.addAll(permissionsToGrant, permissions);
32+
}
33+
34+
@Override
35+
public void requestPermissions() {
36+
Context targetContext = InstrumentationRegistry.getInstrumentation().getTargetContext();
37+
UiAutomation uiAutomation = InstrumentationRegistry.getInstrumentation().getUiAutomation();
38+
for (String permission : permissionsToGrant) {
39+
if (!isPermissionGranted(targetContext, permission)) {
40+
Log.i(
41+
TAG,
42+
String.format(
43+
"Attempting to grant %s to %s", permission, targetContext.getPackageName()));
44+
uiAutomation.grantRuntimePermission(targetContext.getPackageName(), permission);
45+
} else {
46+
Log.i(TAG, "Permission: " + permission + " is already granted!");
47+
}
48+
}
49+
}
50+
51+
private boolean isPermissionGranted(Context targetContext, String permission) {
52+
return targetContext.checkCallingOrSelfPermission(permission)
53+
== PackageManager.PERMISSION_GRANTED;
54+
}
55+
}

runner/rules/CHANGELOG.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,8 @@
66

77
**Bug Fixes**
88

9+
* Make GrantPermissionRule use UiAutomation to grant permissions on APIs > =28 to fix issues running on automotive.
10+
911
**New Features**
1012

1113
**Breaking Changes**

runner/rules/java/androidx/test/rule/GrantPermissionRule.java

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,11 +19,13 @@
1919
import static androidx.test.internal.util.Checks.checkNotNull;
2020

2121
import android.Manifest.permission;
22+
import android.os.Build.VERSION;
2223
import androidx.annotation.NonNull;
2324
import androidx.annotation.VisibleForTesting;
2425
import androidx.test.internal.platform.ServiceLoaderWrapper;
2526
import androidx.test.internal.platform.content.PermissionGranter;
2627
import androidx.test.runner.permission.PermissionRequester;
28+
import androidx.test.runner.permission.UiAutomationPermissionGranter;
2729
import java.util.Arrays;
2830
import java.util.LinkedHashSet;
2931
import java.util.Set;
@@ -76,7 +78,18 @@ public class GrantPermissionRule implements TestRule {
7678
private PermissionGranter permissionGranter;
7779

7880
private GrantPermissionRule() {
79-
this(ServiceLoaderWrapper.loadSingleService(PermissionGranter.class, PermissionRequester::new));
81+
PermissionGranter granter =
82+
ServiceLoaderWrapper.loadSingleServiceOrNull(PermissionGranter.class);
83+
if (granter == null) {
84+
if (VERSION.SDK_INT >= 28) {
85+
granter = new UiAutomationPermissionGranter();
86+
} else {
87+
// use the shell permission requester
88+
granter = new PermissionRequester();
89+
}
90+
}
91+
92+
setPermissionGranter(granter);
8093
}
8194

8295
@VisibleForTesting

0 commit comments

Comments
 (0)