Merge "Migrate apex/permission to packages/modules/Permission" into rvc-dev

This commit is contained in:
Baligh Uddin
2021-05-07 22:16:55 +00:00
committed by Android (Google) Code Review
34 changed files with 0 additions and 1640 deletions

View File

@@ -1,43 +0,0 @@
// 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.
apex {
name: "com.android.permission",
defaults: ["com.android.permission-defaults"],
manifest: "apex_manifest.json",
}
apex_defaults {
name: "com.android.permission-defaults",
updatable: true,
min_sdk_version: "R",
key: "com.android.permission.key",
certificate: ":com.android.permission.certificate",
java_libs: [
"framework-permission",
"service-permission",
],
apps: ["PermissionController"],
}
apex_key {
name: "com.android.permission.key",
public_key: "com.android.permission.avbpubkey",
private_key: "com.android.permission.pem",
}
android_app_certificate {
name: "com.android.permission.certificate",
certificate: "com.android.permission",
}

View File

@@ -1,6 +0,0 @@
svetoslavganov@google.com
moltmann@google.com
eugenesusla@google.com
zhanghai@google.com
evanseverson@google.com
ntmyren@google.com

View File

@@ -1,7 +0,0 @@
{
"presubmit" : [
{
"name" : "PermissionApexTests"
}
]
}

View File

@@ -1,4 +0,0 @@
{
"name": "com.android.permission",
"version": 300000000
}

View File

@@ -1,51 +0,0 @@
-----BEGIN RSA PRIVATE KEY-----
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
-----END RSA PRIVATE KEY-----

View File

@@ -1,35 +0,0 @@
-----BEGIN CERTIFICATE-----
MIIGKzCCBBOgAwIBAgIUezo3fQeVZsmLpm/dkpGWJ/G/MN8wDQYJKoZIhvcNAQEL
BQAwgaMxCzAJBgNVBAYTAlVTMRMwEQYDVQQIDApDYWxpZm9ybmlhMRYwFAYDVQQH
DA1Nb3VudGFpbiBWaWV3MRAwDgYDVQQKDAdBbmRyb2lkMRAwDgYDVQQLDAdBbmRy
b2lkMR8wHQYDVQQDDBZjb20uYW5kcm9pZC5wZXJtaXNzaW9uMSIwIAYJKoZIhvcN
AQkBFhNhbmRyb2lkQGFuZHJvaWQuY29tMCAXDTE5MTAwOTIxMzExOVoYDzQ3NTcw
OTA0MjEzMTE5WjCBozELMAkGA1UEBhMCVVMxEzARBgNVBAgMCkNhbGlmb3JuaWEx
FjAUBgNVBAcMDU1vdW50YWluIFZpZXcxEDAOBgNVBAoMB0FuZHJvaWQxEDAOBgNV
BAsMB0FuZHJvaWQxHzAdBgNVBAMMFmNvbS5hbmRyb2lkLnBlcm1pc3Npb24xIjAg
BgkqhkiG9w0BCQEWE2FuZHJvaWRAYW5kcm9pZC5jb20wggIiMA0GCSqGSIb3DQEB
AQUAA4ICDwAwggIKAoICAQCxefguRJ7E6tBCTEOeU2HJEGs6AQQapLz9hMed0aaJ
Qr7aTQiYJEk+sG4+jPYbjpxa8JDDzJHp+4g7DjfSb+dvT9n84A8lWaI/yRXTZTQN
Hu5m/bgHhi0LbySpiaFyodXBKUAnOhZyGPtYjtBFywFylueub8ryc1Z6UxxU7udH
1mkIr7sE48Qkq5SyjFROE96iFmYA+vS/JXOfS0NBHiMB4GBxx4V7kXpvrTI7hhZG
HiyhKvNh7wyHIhO9nDEw1rwtAH6CsL3YkQEVBeAU98m+0Au+qStLYkKHh2l8zT4W
7sVK1VSqfB+VqOUmeIGdzlBfqMsoXD+FJz6KnIdUHIwjFDjL7Xr+hd+7xve+Q3S+
U3Blk/U6atY8PM09wNfilG+SvwcKk5IgriDcu3rWKgIFxbUUaxLrDW7pLlu6wt/d
GGtKK+Bc0jF+9Z901Tl33i5xhc5yOktT0btkKs7lSeE6VzP/Nk5g0SuzixmuRoh9
f5Ge41N2ZCEHNXx3wZeVZwHIIPfYrL7Yql1Xoxbfs4ETFk6ChzVQcvjfDQQuK58J
uNc+TOCoI/qflXwGCwpuHl0ier8V5Z4tpMUl5rWyVR/QGRtLPvs2lLuxczDw1OXq
wEVtCMn9aNnd4y7R9PZ52hi53HAvDjpWefrLYi+Q04J6iGFQ1qAFBClK9DquBvmR
swIDAQABo1MwUTAdBgNVHQ4EFgQULpfus5s5SrqLkoUKyPXA0D1iHPMwHwYDVR0j
BBgwFoAULpfus5s5SrqLkoUKyPXA0D1iHPMwDwYDVR0TAQH/BAUwAwEB/zANBgkq
hkiG9w0BAQsFAAOCAgEAjxQG5EFv8V/9yV2glI53VOmlWMjfEgvUjd39s/XLyPlr
OzPOKSB0NFo8To3l4l+MsManxPK8y0OyfEVKbWVz9onv0ovo5MVokBmV/2G0jmsV
B4e9yjOq+DmqIvY/Qh63Ywb97sTgcFI8620MhQDbh2IpEGv4ZNV0H6rgXmgdSCBw
1EjBoYfFpN5aMgZjeyzZcq+d1IapdWqdhuEJQkMvoYS4WIumNIJlEXPQRoq/F5Ih
nszdbKI/jVyiGFa2oeZ3rja1Y6GCRU8TYEoKx1pjS8uQDOEDTwsG/QnUe9peEj0V
SsCkIidJWTomAmq9Tub9vpBe1zuTpuRAwxwR0qwgSxozV1Mvow1dJ19oFtHX0yD6
ZjCpRn5PW9kMvSWSlrcrFs1NJf0j1Cvf7bHpkEDqLqpMnnh9jaFQq3nzDY+MWcIR
jDcgQpI+AiE2/qtauZnFEVhbce49nCnk9+5bpTTIZJdzqeaExe5KXHwEtZLaEDh4
atLY9LuEvPsjmDIMOR6hycD9FvwGXhJOQBjESIWFwigtSb1Yud9n6201jw3MLJ4k
+WhkbmZgWy+xc+Mdm5H3XyB1lvHaHGkxu+QB9KyQuVQKwbUVcbwZIfTFPN6Zr/dS
ZXJqAbBhG/dBgF0LazuLaPVpibi+a3Y+tb9b8eXGkz4F97PWZIEDkELQ+9KOvhc=
-----END CERTIFICATE-----

View File

@@ -1,51 +0,0 @@
// Copyright (C) 2020 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.
filegroup {
name: "framework-permission-sources",
srcs: [
"java/**/*.java",
"java/**/*.aidl",
],
path: "java",
}
java_sdk_library {
name: "framework-permission",
defaults: ["framework-module-defaults"],
// Allow access to the stubs from anywhere.
visibility: ["//visibility:public"],
// Restrict access to implementation library.
impl_library_visibility: [
"//visibility:override", // Ignore the visibility property.
"//frameworks/base/apex/permission:__subpackages__",
],
srcs: [
":framework-permission-sources",
],
apex_available: [
"com.android.permission",
"test_com.android.permission",
],
permitted_packages: [
"android.permission",
"android.app.role",
],
hostdex: true,
installable: true,
}

View File

@@ -1 +0,0 @@
// Signature format: 2.0

View File

@@ -1 +0,0 @@
// Signature format: 2.0

View File

@@ -1 +0,0 @@
// Signature format: 2.0

View File

@@ -1 +0,0 @@
// Signature format: 2.0

View File

@@ -1 +0,0 @@
// Signature format: 2.0

View File

@@ -1 +0,0 @@
// Signature format: 2.0

View File

@@ -1,22 +0,0 @@
/*
* Copyright (C) 2020 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.permission;
/**
* @hide
*/
public class PermissionState {}

View File

@@ -1,50 +0,0 @@
// Copyright (C) 2020 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.
filegroup {
name: "service-permission-sources",
srcs: [
"java/**/*.java",
],
path: "java",
}
java_sdk_library {
name: "service-permission",
defaults: ["framework-system-server-module-defaults"],
visibility: [
"//frameworks/base/services/core",
"//frameworks/base/apex/permission",
"//frameworks/base/apex/permission/testing",
"//frameworks/base/apex/permission/tests",
"//frameworks/base/services/tests/mockingservicestests",
],
impl_library_visibility: [
"//visibility:override",
"//frameworks/base/apex/permission/tests",
"//frameworks/base/services/tests/mockingservicestests",
"//frameworks/base/services/tests/servicestests",
],
srcs: [
":service-permission-sources",
],
libs: [
"framework-permission",
],
apex_available: [
"com.android.permission",
"test_com.android.permission",
],
installable: true,
}

View File

@@ -1 +0,0 @@
// Signature format: 2.0

View File

@@ -1 +0,0 @@
// Signature format: 2.0

View File

@@ -1,46 +0,0 @@
// Signature format: 2.0
package com.android.permission.persistence {
public interface RuntimePermissionsPersistence {
method @NonNull public static com.android.permission.persistence.RuntimePermissionsPersistence createInstance();
method public void deleteForUser(@NonNull android.os.UserHandle);
method @Nullable public com.android.permission.persistence.RuntimePermissionsState readForUser(@NonNull android.os.UserHandle);
method public void writeForUser(@NonNull com.android.permission.persistence.RuntimePermissionsState, @NonNull android.os.UserHandle);
}
public final class RuntimePermissionsState {
ctor public RuntimePermissionsState(int, @Nullable String, @NonNull java.util.Map<java.lang.String,java.util.List<com.android.permission.persistence.RuntimePermissionsState.PermissionState>>, @NonNull java.util.Map<java.lang.String,java.util.List<com.android.permission.persistence.RuntimePermissionsState.PermissionState>>);
method @Nullable public String getFingerprint();
method @NonNull public java.util.Map<java.lang.String,java.util.List<com.android.permission.persistence.RuntimePermissionsState.PermissionState>> getPackagePermissions();
method @NonNull public java.util.Map<java.lang.String,java.util.List<com.android.permission.persistence.RuntimePermissionsState.PermissionState>> getSharedUserPermissions();
method public int getVersion();
field public static final int NO_VERSION = -1; // 0xffffffff
}
public static final class RuntimePermissionsState.PermissionState {
ctor public RuntimePermissionsState.PermissionState(@NonNull String, boolean, int);
method public int getFlags();
method @NonNull public String getName();
method public boolean isGranted();
}
}
package com.android.role.persistence {
public interface RolesPersistence {
method @NonNull public static com.android.role.persistence.RolesPersistence createInstance();
method public void deleteForUser(@NonNull android.os.UserHandle);
method @Nullable public com.android.role.persistence.RolesState readForUser(@NonNull android.os.UserHandle);
method public void writeForUser(@NonNull com.android.role.persistence.RolesState, @NonNull android.os.UserHandle);
}
public final class RolesState {
ctor public RolesState(int, @Nullable String, @NonNull java.util.Map<java.lang.String,java.util.Set<java.lang.String>>);
method @Nullable public String getPackagesHash();
method @NonNull public java.util.Map<java.lang.String,java.util.Set<java.lang.String>> getRoles();
method public int getVersion();
}
}

View File

@@ -1 +0,0 @@
// Signature format: 2.0

View File

@@ -1,40 +0,0 @@
/*
* Copyright (C) 2020 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.permission.persistence;
import android.annotation.NonNull;
/**
* Utility class for IO.
*
* @hide
*/
public class IoUtils {
private IoUtils() {}
/**
* Close 'closeable' ignoring any exceptions.
*/
public static void closeQuietly(@NonNull AutoCloseable closeable) {
try {
closeable.close();
} catch (Exception ignored) {
// Ignored.
}
}
}

View File

@@ -1,74 +0,0 @@
/*
* Copyright (C) 2020 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.permission.persistence;
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.annotation.SystemApi;
import android.annotation.SystemApi.Client;
import android.os.UserHandle;
/**
* Persistence for runtime permissions.
*
* TODO(b/147914847): Remove @hide when it becomes the default.
* @hide
*/
@SystemApi(client = Client.SYSTEM_SERVER)
public interface RuntimePermissionsPersistence {
/**
* Read the runtime permissions from persistence.
*
* This will perform I/O operations synchronously.
*
* @param user the user to read for
* @return the runtime permissions read
*/
@Nullable
RuntimePermissionsState readForUser(@NonNull UserHandle user);
/**
* Write the runtime permissions to persistence.
*
* This will perform I/O operations synchronously.
*
* @param runtimePermissions the runtime permissions to write
* @param user the user to write for
*/
void writeForUser(@NonNull RuntimePermissionsState runtimePermissions,
@NonNull UserHandle user);
/**
* Delete the runtime permissions from persistence.
*
* This will perform I/O operations synchronously.
*
* @param user the user to delete for
*/
void deleteForUser(@NonNull UserHandle user);
/**
* Create a new instance of {@link RuntimePermissionsPersistence} implementation.
*
* @return the new instance.
*/
@NonNull
static RuntimePermissionsPersistence createInstance() {
return new RuntimePermissionsPersistenceImpl();
}
}

View File

@@ -1,265 +0,0 @@
/*
* Copyright (C) 2020 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.permission.persistence;
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.content.ApexEnvironment;
import android.content.pm.PackageManager;
import android.os.UserHandle;
import android.util.ArrayMap;
import android.util.AtomicFile;
import android.util.Log;
import android.util.Xml;
import org.xmlpull.v1.XmlPullParser;
import org.xmlpull.v1.XmlPullParserException;
import org.xmlpull.v1.XmlSerializer;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
/**
* Persistence implementation for runtime permissions.
*
* TODO(b/147914847): Remove @hide when it becomes the default.
* @hide
*/
public class RuntimePermissionsPersistenceImpl implements RuntimePermissionsPersistence {
private static final String LOG_TAG = RuntimePermissionsPersistenceImpl.class.getSimpleName();
private static final String APEX_MODULE_NAME = "com.android.permission";
private static final String RUNTIME_PERMISSIONS_FILE_NAME = "runtime-permissions.xml";
private static final String TAG_PACKAGE = "package";
private static final String TAG_PERMISSION = "permission";
private static final String TAG_RUNTIME_PERMISSIONS = "runtime-permissions";
private static final String TAG_SHARED_USER = "shared-user";
private static final String ATTRIBUTE_FINGERPRINT = "fingerprint";
private static final String ATTRIBUTE_FLAGS = "flags";
private static final String ATTRIBUTE_GRANTED = "granted";
private static final String ATTRIBUTE_NAME = "name";
private static final String ATTRIBUTE_VERSION = "version";
@Nullable
@Override
public RuntimePermissionsState readForUser(@NonNull UserHandle user) {
File file = getFile(user);
try (FileInputStream inputStream = new AtomicFile(file).openRead()) {
XmlPullParser parser = Xml.newPullParser();
parser.setInput(inputStream, null);
return parseXml(parser);
} catch (FileNotFoundException e) {
Log.i(LOG_TAG, "runtime-permissions.xml not found");
return null;
} catch (XmlPullParserException | IOException e) {
throw new IllegalStateException("Failed to read runtime-permissions.xml: " + file , e);
}
}
@NonNull
private static RuntimePermissionsState parseXml(@NonNull XmlPullParser parser)
throws IOException, XmlPullParserException {
int type;
int depth;
int innerDepth = parser.getDepth() + 1;
while ((type = parser.next()) != XmlPullParser.END_DOCUMENT
&& ((depth = parser.getDepth()) >= innerDepth || type != XmlPullParser.END_TAG)) {
if (depth > innerDepth || type != XmlPullParser.START_TAG) {
continue;
}
if (parser.getName().equals(TAG_RUNTIME_PERMISSIONS)) {
return parseRuntimePermissions(parser);
}
}
throw new IllegalStateException("Missing <" + TAG_RUNTIME_PERMISSIONS
+ "> in runtime-permissions.xml");
}
@NonNull
private static RuntimePermissionsState parseRuntimePermissions(@NonNull XmlPullParser parser)
throws IOException, XmlPullParserException {
String versionValue = parser.getAttributeValue(null, ATTRIBUTE_VERSION);
int version = versionValue != null ? Integer.parseInt(versionValue)
: RuntimePermissionsState.NO_VERSION;
String fingerprint = parser.getAttributeValue(null, ATTRIBUTE_FINGERPRINT);
Map<String, List<RuntimePermissionsState.PermissionState>> packagePermissions =
new ArrayMap<>();
Map<String, List<RuntimePermissionsState.PermissionState>> sharedUserPermissions =
new ArrayMap<>();
int type;
int depth;
int innerDepth = parser.getDepth() + 1;
while ((type = parser.next()) != XmlPullParser.END_DOCUMENT
&& ((depth = parser.getDepth()) >= innerDepth || type != XmlPullParser.END_TAG)) {
if (depth > innerDepth || type != XmlPullParser.START_TAG) {
continue;
}
switch (parser.getName()) {
case TAG_PACKAGE: {
String packageName = parser.getAttributeValue(null, ATTRIBUTE_NAME);
List<RuntimePermissionsState.PermissionState> permissions = parsePermissions(
parser);
packagePermissions.put(packageName, permissions);
break;
}
case TAG_SHARED_USER: {
String sharedUserName = parser.getAttributeValue(null, ATTRIBUTE_NAME);
List<RuntimePermissionsState.PermissionState> permissions = parsePermissions(
parser);
sharedUserPermissions.put(sharedUserName, permissions);
break;
}
}
}
return new RuntimePermissionsState(version, fingerprint, packagePermissions,
sharedUserPermissions);
}
@NonNull
private static List<RuntimePermissionsState.PermissionState> parsePermissions(
@NonNull XmlPullParser parser) throws IOException, XmlPullParserException {
List<RuntimePermissionsState.PermissionState> permissions = new ArrayList<>();
int type;
int depth;
int innerDepth = parser.getDepth() + 1;
while ((type = parser.next()) != XmlPullParser.END_DOCUMENT
&& ((depth = parser.getDepth()) >= innerDepth || type != XmlPullParser.END_TAG)) {
if (depth > innerDepth || type != XmlPullParser.START_TAG) {
continue;
}
if (parser.getName().equals(TAG_PERMISSION)) {
String name = parser.getAttributeValue(null, ATTRIBUTE_NAME);
boolean granted = Boolean.parseBoolean(parser.getAttributeValue(null,
ATTRIBUTE_GRANTED));
int flags = Integer.parseInt(parser.getAttributeValue(null,
ATTRIBUTE_FLAGS), 16);
RuntimePermissionsState.PermissionState permission =
new RuntimePermissionsState.PermissionState(name, granted, flags);
permissions.add(permission);
}
}
return permissions;
}
@Override
public void writeForUser(@NonNull RuntimePermissionsState runtimePermissions,
@NonNull UserHandle user) {
File file = getFile(user);
AtomicFile atomicFile = new AtomicFile(file);
FileOutputStream outputStream = null;
try {
outputStream = atomicFile.startWrite();
XmlSerializer serializer = Xml.newSerializer();
serializer.setOutput(outputStream, StandardCharsets.UTF_8.name());
serializer.setFeature("http://xmlpull.org/v1/doc/features.html#indent-output", true);
serializer.startDocument(null, true);
serializeRuntimePermissions(serializer, runtimePermissions);
serializer.endDocument();
atomicFile.finishWrite(outputStream);
} catch (Exception e) {
Log.wtf(LOG_TAG, "Failed to write runtime-permissions.xml, restoring backup: " + file,
e);
atomicFile.failWrite(outputStream);
} finally {
IoUtils.closeQuietly(outputStream);
}
}
private static void serializeRuntimePermissions(@NonNull XmlSerializer serializer,
@NonNull RuntimePermissionsState runtimePermissions) throws IOException {
serializer.startTag(null, TAG_RUNTIME_PERMISSIONS);
int version = runtimePermissions.getVersion();
serializer.attribute(null, ATTRIBUTE_VERSION, Integer.toString(version));
String fingerprint = runtimePermissions.getFingerprint();
if (fingerprint != null) {
serializer.attribute(null, ATTRIBUTE_FINGERPRINT, fingerprint);
}
for (Map.Entry<String, List<RuntimePermissionsState.PermissionState>> entry
: runtimePermissions.getPackagePermissions().entrySet()) {
String packageName = entry.getKey();
List<RuntimePermissionsState.PermissionState> permissions = entry.getValue();
serializer.startTag(null, TAG_PACKAGE);
serializer.attribute(null, ATTRIBUTE_NAME, packageName);
serializePermissions(serializer, permissions);
serializer.endTag(null, TAG_PACKAGE);
}
for (Map.Entry<String, List<RuntimePermissionsState.PermissionState>> entry
: runtimePermissions.getSharedUserPermissions().entrySet()) {
String sharedUserName = entry.getKey();
List<RuntimePermissionsState.PermissionState> permissions = entry.getValue();
serializer.startTag(null, TAG_SHARED_USER);
serializer.attribute(null, ATTRIBUTE_NAME, sharedUserName);
serializePermissions(serializer, permissions);
serializer.endTag(null, TAG_SHARED_USER);
}
serializer.endTag(null, TAG_RUNTIME_PERMISSIONS);
}
private static void serializePermissions(@NonNull XmlSerializer serializer,
@NonNull List<RuntimePermissionsState.PermissionState> permissions) throws IOException {
int permissionsSize = permissions.size();
for (int i = 0; i < permissionsSize; i++) {
RuntimePermissionsState.PermissionState permissionState = permissions.get(i);
serializer.startTag(null, TAG_PERMISSION);
serializer.attribute(null, ATTRIBUTE_NAME, permissionState.getName());
serializer.attribute(null, ATTRIBUTE_GRANTED, Boolean.toString(
permissionState.isGranted() && (permissionState.getFlags()
& PackageManager.FLAG_PERMISSION_ONE_TIME) == 0));
serializer.attribute(null, ATTRIBUTE_FLAGS, Integer.toHexString(
permissionState.getFlags()));
serializer.endTag(null, TAG_PERMISSION);
}
}
@Override
public void deleteForUser(@NonNull UserHandle user) {
getFile(user).delete();
}
@NonNull
private static File getFile(@NonNull UserHandle user) {
ApexEnvironment apexEnvironment = ApexEnvironment.getApexEnvironment(APEX_MODULE_NAME);
File dataDirectory = apexEnvironment.getDeviceProtectedDataDirForUser(user);
return new File(dataDirectory, RUNTIME_PERMISSIONS_FILE_NAME);
}
}

View File

@@ -1,222 +0,0 @@
/*
* Copyright (C) 2020 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.permission.persistence;
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.annotation.SystemApi;
import android.annotation.SystemApi.Client;
import java.util.List;
import java.util.Map;
import java.util.Objects;
/**
* State of all runtime permissions.
*
* TODO(b/147914847): Remove @hide when it becomes the default.
* @hide
*/
@SystemApi(client = Client.SYSTEM_SERVER)
public final class RuntimePermissionsState {
/**
* Special value for {@link #mVersion} to indicate that no version was read.
*/
public static final int NO_VERSION = -1;
/**
* The version of the runtime permissions.
*/
private final int mVersion;
/**
* The fingerprint of the runtime permissions.
*/
@Nullable
private final String mFingerprint;
/**
* The runtime permissions by packages.
*/
@NonNull
private final Map<String, List<PermissionState>> mPackagePermissions;
/**
* The runtime permissions by shared users.
*/
@NonNull
private final Map<String, List<PermissionState>> mSharedUserPermissions;
/**
* Create a new instance of this class.
*
* @param version the version of the runtime permissions
* @param fingerprint the fingerprint of the runtime permissions
* @param packagePermissions the runtime permissions by packages
* @param sharedUserPermissions the runtime permissions by shared users
*/
public RuntimePermissionsState(int version, @Nullable String fingerprint,
@NonNull Map<String, List<PermissionState>> packagePermissions,
@NonNull Map<String, List<PermissionState>> sharedUserPermissions) {
mVersion = version;
mFingerprint = fingerprint;
mPackagePermissions = packagePermissions;
mSharedUserPermissions = sharedUserPermissions;
}
/**
* Get the version of the runtime permissions.
*
* @return the version of the runtime permissions
*/
public int getVersion() {
return mVersion;
}
/**
* Get the fingerprint of the runtime permissions.
*
* @return the fingerprint of the runtime permissions
*/
@Nullable
public String getFingerprint() {
return mFingerprint;
}
/**
* Get the runtime permissions by packages.
*
* @return the runtime permissions by packages
*/
@NonNull
public Map<String, List<PermissionState>> getPackagePermissions() {
return mPackagePermissions;
}
/**
* Get the runtime permissions by shared users.
*
* @return the runtime permissions by shared users
*/
@NonNull
public Map<String, List<PermissionState>> getSharedUserPermissions() {
return mSharedUserPermissions;
}
@Override
public boolean equals(Object object) {
if (this == object) {
return true;
}
if (object == null || getClass() != object.getClass()) {
return false;
}
RuntimePermissionsState that = (RuntimePermissionsState) object;
return mVersion == that.mVersion
&& Objects.equals(mFingerprint, that.mFingerprint)
&& Objects.equals(mPackagePermissions, that.mPackagePermissions)
&& Objects.equals(mSharedUserPermissions, that.mSharedUserPermissions);
}
@Override
public int hashCode() {
return Objects.hash(mVersion, mFingerprint, mPackagePermissions, mSharedUserPermissions);
}
/**
* State of a single permission.
*/
public static final class PermissionState {
/**
* The name of the permission.
*/
@NonNull
private final String mName;
/**
* Whether the permission is granted.
*/
private final boolean mGranted;
/**
* The flags of the permission.
*/
private final int mFlags;
/**
* Create a new instance of this class.
*
* @param name the name of the permission
* @param granted whether the permission is granted
* @param flags the flags of the permission
*/
public PermissionState(@NonNull String name, boolean granted, int flags) {
mName = name;
mGranted = granted;
mFlags = flags;
}
/**
* Get the name of the permission.
*
* @return the name of the permission
*/
@NonNull
public String getName() {
return mName;
}
/**
* Get whether the permission is granted.
*
* @return whether the permission is granted
*/
public boolean isGranted() {
return mGranted;
}
/**
* Get the flags of the permission.
*
* @return the flags of the permission
*/
public int getFlags() {
return mFlags;
}
@Override
public boolean equals(Object object) {
if (this == object) {
return true;
}
if (object == null || getClass() != object.getClass()) {
return false;
}
PermissionState that = (PermissionState) object;
return mGranted == that.mGranted
&& mFlags == that.mFlags
&& Objects.equals(mName, that.mName);
}
@Override
public int hashCode() {
return Objects.hash(mName, mGranted, mFlags);
}
}
}

View File

@@ -1,73 +0,0 @@
/*
* Copyright (C) 2020 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.role.persistence;
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.annotation.SystemApi;
import android.annotation.SystemApi.Client;
import android.os.UserHandle;
/**
* Persistence for roles.
*
* TODO(b/147914847): Remove @hide when it becomes the default.
* @hide
*/
@SystemApi(client = Client.SYSTEM_SERVER)
public interface RolesPersistence {
/**
* Read the roles from persistence.
*
* This will perform I/O operations synchronously.
*
* @param user the user to read for
* @return the roles read
*/
@Nullable
RolesState readForUser(@NonNull UserHandle user);
/**
* Write the roles to persistence.
*
* This will perform I/O operations synchronously.
*
* @param roles the roles to write
* @param user the user to write for
*/
void writeForUser(@NonNull RolesState roles, @NonNull UserHandle user);
/**
* Delete the roles from persistence.
*
* This will perform I/O operations synchronously.
*
* @param user the user to delete for
*/
void deleteForUser(@NonNull UserHandle user);
/**
* Create a new instance of {@link RolesPersistence} implementation.
*
* @return the new instance.
*/
@NonNull
static RolesPersistence createInstance() {
return new RolesPersistenceImpl();
}
}

View File

@@ -1,218 +0,0 @@
/*
* Copyright (C) 2020 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.role.persistence;
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.content.ApexEnvironment;
import android.os.UserHandle;
import android.util.ArrayMap;
import android.util.ArraySet;
import android.util.AtomicFile;
import android.util.Log;
import android.util.Xml;
import com.android.permission.persistence.IoUtils;
import org.xmlpull.v1.XmlPullParser;
import org.xmlpull.v1.XmlPullParserException;
import org.xmlpull.v1.XmlSerializer;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.util.Map;
import java.util.Set;
/**
* Persistence implementation for roles.
*
* TODO(b/147914847): Remove @hide when it becomes the default.
* @hide
*/
public class RolesPersistenceImpl implements RolesPersistence {
private static final String LOG_TAG = RolesPersistenceImpl.class.getSimpleName();
private static final String APEX_MODULE_NAME = "com.android.permission";
private static final String ROLES_FILE_NAME = "roles.xml";
private static final String TAG_ROLES = "roles";
private static final String TAG_ROLE = "role";
private static final String TAG_HOLDER = "holder";
private static final String ATTRIBUTE_VERSION = "version";
private static final String ATTRIBUTE_NAME = "name";
private static final String ATTRIBUTE_PACKAGES_HASH = "packagesHash";
@Nullable
@Override
public RolesState readForUser(@NonNull UserHandle user) {
File file = getFile(user);
try (FileInputStream inputStream = new AtomicFile(file).openRead()) {
XmlPullParser parser = Xml.newPullParser();
parser.setInput(inputStream, null);
return parseXml(parser);
} catch (FileNotFoundException e) {
Log.i(LOG_TAG, "roles.xml not found");
return null;
} catch (XmlPullParserException | IOException e) {
throw new IllegalStateException("Failed to read roles.xml: " + file , e);
}
}
@NonNull
private static RolesState parseXml(@NonNull XmlPullParser parser)
throws IOException, XmlPullParserException {
int type;
int depth;
int innerDepth = parser.getDepth() + 1;
while ((type = parser.next()) != XmlPullParser.END_DOCUMENT
&& ((depth = parser.getDepth()) >= innerDepth || type != XmlPullParser.END_TAG)) {
if (depth > innerDepth || type != XmlPullParser.START_TAG) {
continue;
}
if (parser.getName().equals(TAG_ROLES)) {
return parseRoles(parser);
}
}
throw new IllegalStateException("Missing <" + TAG_ROLES + "> in roles.xml");
}
@NonNull
private static RolesState parseRoles(@NonNull XmlPullParser parser)
throws IOException, XmlPullParserException {
int version = Integer.parseInt(parser.getAttributeValue(null, ATTRIBUTE_VERSION));
String packagesHash = parser.getAttributeValue(null, ATTRIBUTE_PACKAGES_HASH);
Map<String, Set<String>> roles = new ArrayMap<>();
int type;
int depth;
int innerDepth = parser.getDepth() + 1;
while ((type = parser.next()) != XmlPullParser.END_DOCUMENT
&& ((depth = parser.getDepth()) >= innerDepth || type != XmlPullParser.END_TAG)) {
if (depth > innerDepth || type != XmlPullParser.START_TAG) {
continue;
}
if (parser.getName().equals(TAG_ROLE)) {
String roleName = parser.getAttributeValue(null, ATTRIBUTE_NAME);
Set<String> roleHolders = parseRoleHolders(parser);
roles.put(roleName, roleHolders);
}
}
return new RolesState(version, packagesHash, roles);
}
@NonNull
private static Set<String> parseRoleHolders(@NonNull XmlPullParser parser)
throws IOException, XmlPullParserException {
Set<String> roleHolders = new ArraySet<>();
int type;
int depth;
int innerDepth = parser.getDepth() + 1;
while ((type = parser.next()) != XmlPullParser.END_DOCUMENT
&& ((depth = parser.getDepth()) >= innerDepth || type != XmlPullParser.END_TAG)) {
if (depth > innerDepth || type != XmlPullParser.START_TAG) {
continue;
}
if (parser.getName().equals(TAG_HOLDER)) {
String roleHolder = parser.getAttributeValue(null, ATTRIBUTE_NAME);
roleHolders.add(roleHolder);
}
}
return roleHolders;
}
@Override
public void writeForUser(@NonNull RolesState roles, @NonNull UserHandle user) {
File file = getFile(user);
AtomicFile atomicFile = new AtomicFile(file);
FileOutputStream outputStream = null;
try {
outputStream = atomicFile.startWrite();
XmlSerializer serializer = Xml.newSerializer();
serializer.setOutput(outputStream, StandardCharsets.UTF_8.name());
serializer.setFeature("http://xmlpull.org/v1/doc/features.html#indent-output", true);
serializer.startDocument(null, true);
serializeRoles(serializer, roles);
serializer.endDocument();
atomicFile.finishWrite(outputStream);
} catch (Exception e) {
Log.wtf(LOG_TAG, "Failed to write roles.xml, restoring backup: " + file,
e);
atomicFile.failWrite(outputStream);
} finally {
IoUtils.closeQuietly(outputStream);
}
}
private static void serializeRoles(@NonNull XmlSerializer serializer,
@NonNull RolesState roles) throws IOException {
serializer.startTag(null, TAG_ROLES);
int version = roles.getVersion();
serializer.attribute(null, ATTRIBUTE_VERSION, Integer.toString(version));
String packagesHash = roles.getPackagesHash();
if (packagesHash != null) {
serializer.attribute(null, ATTRIBUTE_PACKAGES_HASH, packagesHash);
}
for (Map.Entry<String, Set<String>> entry : roles.getRoles().entrySet()) {
String roleName = entry.getKey();
Set<String> roleHolders = entry.getValue();
serializer.startTag(null, TAG_ROLE);
serializer.attribute(null, ATTRIBUTE_NAME, roleName);
serializeRoleHolders(serializer, roleHolders);
serializer.endTag(null, TAG_ROLE);
}
serializer.endTag(null, TAG_ROLES);
}
private static void serializeRoleHolders(@NonNull XmlSerializer serializer,
@NonNull Set<String> roleHolders) throws IOException {
for (String roleHolder : roleHolders) {
serializer.startTag(null, TAG_HOLDER);
serializer.attribute(null, ATTRIBUTE_NAME, roleHolder);
serializer.endTag(null, TAG_HOLDER);
}
}
@Override
public void deleteForUser(@NonNull UserHandle user) {
getFile(user).delete();
}
@NonNull
private static File getFile(@NonNull UserHandle user) {
ApexEnvironment apexEnvironment = ApexEnvironment.getApexEnvironment(APEX_MODULE_NAME);
File dataDirectory = apexEnvironment.getDeviceProtectedDataDirForUser(user);
return new File(dataDirectory, ROLES_FILE_NAME);
}
}

View File

@@ -1,115 +0,0 @@
/*
* Copyright (C) 2020 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.role.persistence;
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.annotation.SystemApi;
import android.annotation.SystemApi.Client;
import java.util.Map;
import java.util.Objects;
import java.util.Set;
/**
* State of all roles.
*
* TODO(b/147914847): Remove @hide when it becomes the default.
* @hide
*/
@SystemApi(client = Client.SYSTEM_SERVER)
public final class RolesState {
/**
* The version of the roles.
*/
private final int mVersion;
/**
* The hash of all packages in the system.
*/
@Nullable
private final String mPackagesHash;
/**
* The roles.
*/
@NonNull
private final Map<String, Set<String>> mRoles;
/**
* Create a new instance of this class.
*
* @param version the version of the roles
* @param packagesHash the hash of all packages in the system
* @param roles the roles
*/
public RolesState(int version, @Nullable String packagesHash,
@NonNull Map<String, Set<String>> roles) {
mVersion = version;
mPackagesHash = packagesHash;
mRoles = roles;
}
/**
* Get the version of the roles.
*
* @return the version of the roles
*/
public int getVersion() {
return mVersion;
}
/**
* Get the hash of all packages in the system.
*
* @return the hash of all packages in the system
*/
@Nullable
public String getPackagesHash() {
return mPackagesHash;
}
/**
* Get the roles.
*
* @return the roles
*/
@NonNull
public Map<String, Set<String>> getRoles() {
return mRoles;
}
@Override
public boolean equals(Object object) {
if (this == object) {
return true;
}
if (object == null || getClass() != object.getClass()) {
return false;
}
RolesState that = (RolesState) object;
return mVersion == that.mVersion
&& Objects.equals(mPackagesHash, that.mPackagesHash)
&& Objects.equals(mRoles, that.mRoles);
}
@Override
public int hashCode() {
return Objects.hash(mVersion, mPackagesHash, mRoles);
}
}

View File

@@ -1,25 +0,0 @@
// 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.
apex_test {
name: "test_com.android.permission",
visibility: [
"//system/apex/tests",
],
defaults: ["com.android.permission-defaults"],
manifest: "test_manifest.json",
file_contexts: ":com.android.permission-file_contexts",
// Test APEX, should never be installed
installable: false,
}

View File

@@ -1,4 +0,0 @@
{
"name": "com.android.permission",
"version": 2147483647
}

View File

@@ -1,37 +0,0 @@
// Copyright (C) 2020 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.
android_test {
name: "PermissionApexTests",
sdk_version: "test_current",
srcs: [
"java/**/*.kt",
],
static_libs: [
"service-permission.impl",
"androidx.test.rules",
"androidx.test.ext.junit",
"androidx.test.ext.truth",
"mockito-target-extended-minus-junit4",
],
jni_libs: [
"libdexmakerjvmtiagent",
"libstaticjvmtiagent",
],
compile_multilib: "both",
test_suites: [
"general-tests",
"mts",
],
}

View File

@@ -1,32 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
~ Copyright (C) 2020 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.
-->
<manifest
xmlns:android="http://schemas.android.com/apk/res/android"
package="com.android.permission.test">
<!-- The application has to be debuggable for static mocking to work. -->
<application android:debuggable="true">
<uses-library android:name="android.test.runner" />
</application>
<instrumentation
android:name="androidx.test.runner.AndroidJUnitRunner"
android:targetPackage="com.android.permission.test"
android:label="Permission APEX Tests" />
</manifest>

View File

@@ -1,110 +0,0 @@
/*
* Copyright (C) 2020 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.permission.persistence
import android.content.ApexEnvironment
import android.content.Context
import android.os.Process
import android.os.UserHandle
import androidx.test.ext.junit.runners.AndroidJUnit4
import androidx.test.platform.app.InstrumentationRegistry
import com.android.dx.mockito.inline.extended.ExtendedMockito.mockitoSession
import com.google.common.truth.Truth.assertThat
import org.junit.After
import org.junit.Before
import org.junit.Test
import org.junit.runner.RunWith
import org.mockito.ArgumentMatchers.any
import org.mockito.ArgumentMatchers.eq
import org.mockito.Mock
import org.mockito.Mockito.`when`
import org.mockito.MockitoAnnotations.initMocks
import org.mockito.MockitoSession
import org.mockito.quality.Strictness
import java.io.File
@RunWith(AndroidJUnit4::class)
class RuntimePermissionsPersistenceTest {
private val context = InstrumentationRegistry.getInstrumentation().context
private lateinit var mockDataDirectory: File
private lateinit var mockitoSession: MockitoSession
@Mock
lateinit var apexEnvironment: ApexEnvironment
private val persistence = RuntimePermissionsPersistence.createInstance()
private val permissionState = RuntimePermissionsState.PermissionState("permission", true, 3)
private val state = RuntimePermissionsState(
1, "fingerprint", mapOf("package" to listOf(permissionState)),
mapOf("sharedUser" to listOf(permissionState))
)
private val user = Process.myUserHandle()
@Before
fun createMockDataDirectory() {
mockDataDirectory = context.getDir("mock_data", Context.MODE_PRIVATE)
mockDataDirectory.listFiles()!!.forEach { assertThat(it.deleteRecursively()).isTrue() }
}
@Before
fun mockApexEnvironment() {
initMocks(this)
mockitoSession = mockitoSession()
.mockStatic(ApexEnvironment::class.java)
.strictness(Strictness.LENIENT)
.startMocking()
`when`(ApexEnvironment.getApexEnvironment(eq(APEX_MODULE_NAME))).thenReturn(apexEnvironment)
`when`(apexEnvironment.getDeviceProtectedDataDirForUser(any(UserHandle::class.java))).then {
File(mockDataDirectory, it.arguments[0].toString()).also { it.mkdirs() }
}
}
@After
fun finishMockingApexEnvironment() {
mockitoSession.finishMocking()
}
@Test
fun testReadWrite() {
persistence.writeForUser(state, user)
val persistedState = persistence.readForUser(user)
assertThat(persistedState).isEqualTo(state)
assertThat(persistedState!!.version).isEqualTo(state.version)
assertThat(persistedState.fingerprint).isEqualTo(state.fingerprint)
assertThat(persistedState.packagePermissions).isEqualTo(state.packagePermissions)
val persistedPermissionState = persistedState.packagePermissions.values.first().first()
assertThat(persistedPermissionState.name).isEqualTo(permissionState.name)
assertThat(persistedPermissionState.isGranted).isEqualTo(permissionState.isGranted)
assertThat(persistedPermissionState.flags).isEqualTo(permissionState.flags)
assertThat(persistedState.sharedUserPermissions).isEqualTo(state.sharedUserPermissions)
}
@Test
fun testDelete() {
persistence.writeForUser(state, user)
persistence.deleteForUser(user)
val persistedState = persistence.readForUser(user)
assertThat(persistedState).isNull()
}
companion object {
private const val APEX_MODULE_NAME = "com.android.permission"
}
}

View File

@@ -1,101 +0,0 @@
/*
* Copyright (C) 2020 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.role.persistence
import android.content.ApexEnvironment
import android.content.Context
import android.os.Process
import android.os.UserHandle
import androidx.test.ext.junit.runners.AndroidJUnit4
import androidx.test.platform.app.InstrumentationRegistry
import com.android.dx.mockito.inline.extended.ExtendedMockito.mockitoSession
import com.google.common.truth.Truth.assertThat
import org.junit.After
import org.junit.Before
import org.junit.Test
import org.junit.runner.RunWith
import org.mockito.ArgumentMatchers.any
import org.mockito.ArgumentMatchers.eq
import org.mockito.Mock
import org.mockito.Mockito.`when`
import org.mockito.MockitoAnnotations.initMocks
import org.mockito.MockitoSession
import org.mockito.quality.Strictness
import java.io.File
@RunWith(AndroidJUnit4::class)
class RolesPersistenceTest {
private val context = InstrumentationRegistry.getInstrumentation().context
private lateinit var mockDataDirectory: File
private lateinit var mockitoSession: MockitoSession
@Mock
lateinit var apexEnvironment: ApexEnvironment
private val persistence = RolesPersistence.createInstance()
private val state = RolesState(1, "packagesHash", mapOf("role" to setOf("holder1", "holder2")))
private val user = Process.myUserHandle()
@Before
fun createMockDataDirectory() {
mockDataDirectory = context.getDir("mock_data", Context.MODE_PRIVATE)
mockDataDirectory.listFiles()!!.forEach { assertThat(it.deleteRecursively()).isTrue() }
}
@Before
fun mockApexEnvironment() {
initMocks(this)
mockitoSession = mockitoSession()
.mockStatic(ApexEnvironment::class.java)
.strictness(Strictness.LENIENT)
.startMocking()
`when`(ApexEnvironment.getApexEnvironment(eq(APEX_MODULE_NAME))).thenReturn(apexEnvironment)
`when`(apexEnvironment.getDeviceProtectedDataDirForUser(any(UserHandle::class.java))).then {
File(mockDataDirectory, it.arguments[0].toString()).also { it.mkdirs() }
}
}
@After
fun finishMockingApexEnvironment() {
mockitoSession.finishMocking()
}
@Test
fun testReadWrite() {
persistence.writeForUser(state, user)
val persistedState = persistence.readForUser(user)
assertThat(persistedState).isEqualTo(state)
assertThat(persistedState!!.version).isEqualTo(state.version)
assertThat(persistedState.packagesHash).isEqualTo(state.packagesHash)
assertThat(persistedState.roles).isEqualTo(state.roles)
}
@Test
fun testDelete() {
persistence.writeForUser(state, user)
persistence.deleteForUser(user)
val persistedState = persistence.readForUser(user)
assertThat(persistedState).isNull()
}
companion object {
private const val APEX_MODULE_NAME = "com.android.permission"
}
}