Merge "Migrate apex/permission to packages/modules/Permission" into rvc-dev
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: "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",
|
||||
}
|
||||
@@ -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-----
|
||||
MIIJKgIBAAKCAgEA6snt4eqoz85xiL9Sf6w1S1b9FgSHK05zYTh2JYPvQKQ3yeZp
|
||||
E6avJ6FN6XcbmkDzSd658BvUGDBSPhOlzuUO4BsoKBuLMxP6TxIQXFKidzDqY0vQ
|
||||
4qkS++bdIhUjwBP3OSZ3Czu0BiihK8GC75Abr//EyCyObGIGGfHEGANiOgrpP4X5
|
||||
+OmLzQLCjk4iE1kg+U6cRSRI/XLaoWC0TvIIuzxznrQ6r5GmzgTOwyBWyIB+bj73
|
||||
bmsweHTU+w9Y7kGOx4hO3XCLIhoBWEw0EbuW9nZmQ4sZls5Jo/CbyJlCclF11yVo
|
||||
SCf2LG/T+9pah5NOmDQ1kPbU+0iKZIV4YFHGTIhyGDE/aPOuUT05ziCGDifgHr0u
|
||||
SG1x/RLqsVh/POvNxnvP9cQFMQ08BvbEJaTTgB785iwKsvdqCfmng/SAyxSetmzP
|
||||
StXVB3fh1OoZ8vunRbQYxnmUxycVqaA96zmBx2wLvbvzKo7pZFDE6nbhnT5+MRAM
|
||||
z/VIK89W26uB4gj8sBFslqZjT0jPqsAZuvDm7swOtMwIcEolyGJuFLqlhN7UwMz2
|
||||
9y8+IpYixR+HvD1TZI9NtmuCmv3kPrWgoMZg6yvaBayTIr8RdYzi6FO/C1lLiraz
|
||||
48dH3sXWRa8cgw6VcSUwYrEBIc3sotdsupO1iOjcFybIwaee0YTZJfjvbqkCAwEA
|
||||
AQKCAgEArRnfdpaJi1xLPGTCMDsIt9kUku0XswgN7PmxsYsKFAB+2S40/jYAIRm9
|
||||
1YjpItsMA8RgFfSOdJ77o6TctCMQyo17F8bm4+uwuic5RLfv7Cx2QmsdQF8jDfFx
|
||||
y7UGPJD7znjbf76uxXOjEB2FqZX3s9TAgkzHXIUQtoQW7RVhkCWHPjxKxgd5+NY2
|
||||
FrDoUpd9xhD9CcTsw1+wbRZdGW88nL6/B50dP2AFORM2VYo8MWr6y9FEn3YLsGOC
|
||||
uu7fxBk1aUrHyl81VRkTMMROB1zkuiUk1FtzrEm+5U15rXXBFYOVe9+qeLhtuOlh
|
||||
wueDoz0pzvF/JLe24uTik6YL0Ae6SD0pFXQ2KDrdH3cUHLok3r76/yGzaDNTFjS2
|
||||
2WbQ8dEJV8veNHk8gjGpFTJIsBUlcZpmUCDHlfvVMb3+2ahQ+28piQUt5t3zqJdZ
|
||||
NDqsOHzY6BRPc+Wm85Xii/lWiQceZSee/b1Enu+nchsyXhSenBfC6bIGZReyMI0K
|
||||
KKKuVhyR6OSOiR5ZdZ/NyXGqsWy05fn/h0X9hnpETsNaNYNKWvpHLfKll+STJpf7
|
||||
AZquJPIclQyiq5NONx6kfPztoCLkKV/zOgIj3Sx5oSZq+5gpO91nXWVwkTbqK1d1
|
||||
004q2Mah6UQyAk1XGQc2pHx7ouVcWawjU30vZ4C015Hv2lm/gVkCggEBAPltATYS
|
||||
OqOSL1YAtIHPiHxMjNAgUdglq8JiJFXVfkocGU9eNub3Ed3sSWu6GB9Myu/sSKje
|
||||
bJ5DZqxJnvB2Fqmu9I9OunLGFSD0aXs4prwsQ1Rm5FcbImtrxcciASdkoo8Pj0z4
|
||||
vk2r2NZD3VtER5Uh+YjSDkxcS9gBStXUpCL6gj69UpOxMmWqZVjyHatVB4lEvYJl
|
||||
N82uT7N7QVNL1DzcZ9z4C4r7ks1Pm7ka12s5m/oaAlAMdVeofiPJe1xA9zRToSr4
|
||||
tIbMkOeXFLVRLuji/7XsOgal5Rl59p+OwLshX5cswPVOMrH6zt+hbsJ5q8M5dqnX
|
||||
VAOBK7KNQ/EKZwcCggEBAPD6KVvyCim46n5EbcEqCkO7gevwZkw/9vLwmM5YsxTh
|
||||
z9FQkPO0iB7mwbX8w04I91Pre4NdfcgMG0pP1b13Sb4KHBchqW1a+TCs3kSGC6gn
|
||||
1SxmXHnA9jRxAkrWlGkoAQEz+aP61cXiiy2tXpQwJ8xQCKprfoqWZwhkCtEVU6CE
|
||||
S7v9cscOHIqgNxx4WoceMmq4EoihHAZzHxTcNVbByckMjb2XQJ0iNw3lDP4ddvc+
|
||||
a4HzHfHkhzeQ5ZNc8SvWU8z80aSCOKRsSD3aUTZzxhZ4O2tZSW7v7p+FpvVee7bC
|
||||
g8YCfszTdpVUMlLRLjScimAcovcFLSvtyupinxWg4M8CggEAN9YGEmOsSte7zwXj
|
||||
YrfhtumwEBtcFwX/2Ej+F1Tuq4p0xAa0RaoDjumJWhtTsRYQy/raHSuFpzwxbNoi
|
||||
QXQ+CIhI6RfXtz/OlQ0B2/rHoJJMFEXgUfuaDfAXW0eqeHYXyezSyIlamKqipPyW
|
||||
Pgsf9yue39keKEv1EorfhNTQVaA8rezV4oglXwrxGyNALw2e3UTNI7ai8mFWKDis
|
||||
XAg6n9E7UwUYGGnO6DUtCBgRJ0jDOQ6/e8n+LrxiWIKPIgzNCiK6jpMUXqTGv4Fb
|
||||
umdNGAdQ9RnHt5tFmRlrczaSwJFtA7uaCpAR2zPpQbiywchZAiAIB2dTwGEXNiZX
|
||||
kksg2wKCAQEA6pNad3qhkgPDoK6T+Jkn7M82paoaqtcJWWwEE7oceZNnbWZz9Agl
|
||||
CY+vuawXonrv5+0vCq2Tp4zBdBFLC2h3jFrjBVFrUFxifpOIukOSTVqZFON/2bWQ
|
||||
9XOcu6UuSz7522Xw+UNPnZXtzcUacD6AP08ZYGvLfrTyDyTzspyED5k48ALEHCkM
|
||||
d5WGkFxII4etpF0TDZVnZo/iDbhe49k4yFFEGO6Ho26PESOLBkNAb2V/2bwDxlij
|
||||
l9+g21Z6HiZA5SamHPH2mXgeyrcen1cL2QupK9J6vVcqfnboE6qp2zp2c+Yx8MlY
|
||||
gfy4EA44YFaSDQVTTgrn8f9Eq+zc130H2QKCAQEAqOKgv68nIPdDSngNyCVyWego
|
||||
boFiDaEJoBBg8FrBjTJ6wFLrNAnXmbvfTtgNmNAzF1cUPJZlIIsHgGrMCfpehbXq
|
||||
WQQIw+E+yFbTGLxseGRfsLrV0CsgnAoOVeod+yIHmqc3livaUbrWhL1V2f6Ue+sE
|
||||
7YLp/iP43NaMfA4kYk2ep7+ZJoEVkCjHJJaHWgAG3RynPJHkTJlSgu7wLYvGc9uE
|
||||
ZsEFUM46lX02t7rrtMfasVGrUy1c2xOxFb4v1vG6iEZ7+YWeq5o3AkxUwEGn+mG4
|
||||
/3p+k4AaTXJDXgyZ0Sv6CkGuPHenAYG4cswcUUEf/G4Ag77x6LBNMgycJBxUJA==
|
||||
-----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,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,
|
||||
}
|
||||
@@ -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,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,
|
||||
}
|
||||
@@ -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