Merge "Migrate apex/permission to packages/modules/Permission" am: d985fe7b0e
Original change: https://android-review.googlesource.com/c/platform/frameworks/base/+/1562175 MUST ONLY BE SUBMITTED BY AUTOMERGER Change-Id: Ie20c6dfbbdd3be9b6c5a3c04d937138503aad2c7
This commit is contained in:
@@ -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: "30",
|
|
||||||
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",
|
|
||||||
}
|
|
||||||
@@ -1,6 +0,0 @@
|
|||||||
svetoslavganov@google.com
|
|
||||||
moltmann@google.com
|
|
||||||
eugenesusla@google.com
|
|
||||||
zhanghai@google.com
|
|
||||||
evanseverson@google.com
|
|
||||||
ntmyren@google.com
|
|
||||||
@@ -1,7 +0,0 @@
|
|||||||
{
|
|
||||||
"presubmit" : [
|
|
||||||
{
|
|
||||||
"name" : "PermissionApexTests"
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
|
||||||
@@ -1,4 +0,0 @@
|
|||||||
{
|
|
||||||
"name": "com.android.permission",
|
|
||||||
"version": 300000000
|
|
||||||
}
|
|
||||||
Binary file not shown.
@@ -1,51 +0,0 @@
|
|||||||
-----BEGIN RSA PRIVATE KEY-----
|
|
||||||
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
|
|
||||||
-----END RSA PRIVATE KEY-----
|
|
||||||
Binary file not shown.
@@ -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-----
|
|
||||||
@@ -1,48 +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"],
|
|
||||||
|
|
||||||
// Restrict access to implementation library.
|
|
||||||
impl_library_visibility: [
|
|
||||||
"//frameworks/base/apex/permission:__subpackages__",
|
|
||||||
"//packages/modules/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,
|
|
||||||
}
|
|
||||||
@@ -1 +0,0 @@
|
|||||||
// Signature format: 2.0
|
|
||||||
@@ -1 +0,0 @@
|
|||||||
// Signature format: 2.0
|
|
||||||
@@ -1 +0,0 @@
|
|||||||
// Signature format: 2.0
|
|
||||||
@@ -1 +0,0 @@
|
|||||||
// Signature format: 2.0
|
|
||||||
@@ -1 +0,0 @@
|
|||||||
// Signature format: 2.0
|
|
||||||
@@ -1 +0,0 @@
|
|||||||
// Signature format: 2.0
|
|
||||||
@@ -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 {}
|
|
||||||
@@ -1,45 +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"],
|
|
||||||
impl_library_visibility: [
|
|
||||||
"//frameworks/base/apex/permission/tests",
|
|
||||||
"//frameworks/base/services/tests/mockingservicestests",
|
|
||||||
"//frameworks/base/services/tests/servicestests",
|
|
||||||
"//packages/modules/Permission/tests",
|
|
||||||
],
|
|
||||||
srcs: [
|
|
||||||
":service-permission-sources",
|
|
||||||
],
|
|
||||||
libs: [
|
|
||||||
"framework-permission",
|
|
||||||
],
|
|
||||||
apex_available: [
|
|
||||||
"com.android.permission",
|
|
||||||
"test_com.android.permission",
|
|
||||||
],
|
|
||||||
installable: true,
|
|
||||||
// We don't have last-api tracking files for the public part of this jar's API.
|
|
||||||
unsafe_ignore_missing_latest_api: true,
|
|
||||||
}
|
|
||||||
@@ -1 +0,0 @@
|
|||||||
// Signature format: 2.0
|
|
||||||
@@ -1 +0,0 @@
|
|||||||
// Signature format: 2.0
|
|
||||||
@@ -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();
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
@@ -1 +0,0 @@
|
|||||||
// Signature format: 2.0
|
|
||||||
@@ -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.
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -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();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -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);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -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);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -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();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -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);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -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);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -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,
|
|
||||||
}
|
|
||||||
@@ -1,4 +0,0 @@
|
|||||||
{
|
|
||||||
"name": "com.android.permission",
|
|
||||||
"version": 2147483647
|
|
||||||
}
|
|
||||||
@@ -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",
|
|
||||||
],
|
|
||||||
}
|
|
||||||
@@ -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>
|
|
||||||
@@ -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"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -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"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Reference in New Issue
Block a user