Merge "Add permissions for using PlatformCompat methods" am: 7202e904c9
Change-Id: Iffdf7ffc1265fce941eb4cd519031da4575ac53a
This commit is contained in:
@@ -4703,6 +4703,19 @@
|
|||||||
<permission android:name="android.permission.ACCESS_SHARED_LIBRARIES"
|
<permission android:name="android.permission.ACCESS_SHARED_LIBRARIES"
|
||||||
android:protectionLevel="signature|installer" />
|
android:protectionLevel="signature|installer" />
|
||||||
|
|
||||||
|
<!-- Allows an app to log compat change usage.
|
||||||
|
@hide <p>Not for use by third-party applications.</p> -->
|
||||||
|
<permission android:name="android.permission.LOG_COMPAT_CHANGE"
|
||||||
|
android:protectionLevel="signature|privileged" />
|
||||||
|
<!-- Allows an app to read compat change config.
|
||||||
|
@hide <p>Not for use by third-party applications.</p> -->
|
||||||
|
<permission android:name="android.permission.READ_COMPAT_CHANGE_CONFIG"
|
||||||
|
android:protectionLevel="signature|privileged" />
|
||||||
|
<!-- Allows an app to override compat change config.
|
||||||
|
@hide <p>Not for use by third-party applications.</p> -->
|
||||||
|
<permission android:name="android.permission.OVERRIDE_COMPAT_CHANGE_CONFIG"
|
||||||
|
android:protectionLevel="signature|privileged" />
|
||||||
|
|
||||||
<!-- Allows input events to be monitored. Very dangerous! @hide -->
|
<!-- Allows input events to be monitored. Very dangerous! @hide -->
|
||||||
<permission android:name="android.permission.MONITOR_INPUT"
|
<permission android:name="android.permission.MONITOR_INPUT"
|
||||||
android:protectionLevel="signature" />
|
android:protectionLevel="signature" />
|
||||||
|
|||||||
@@ -110,6 +110,10 @@
|
|||||||
<uses-permission android:name="android.permission.MOVE_PACKAGE" />
|
<uses-permission android:name="android.permission.MOVE_PACKAGE" />
|
||||||
<uses-permission android:name="android.permission.PACKAGE_VERIFICATION_AGENT" />
|
<uses-permission android:name="android.permission.PACKAGE_VERIFICATION_AGENT" />
|
||||||
|
|
||||||
|
<!-- gating and logging permissions -->
|
||||||
|
<uses-permission android:name="android.permission.LOG_COMPAT_CHANGE" />
|
||||||
|
<uses-permission android:name="android.permission.READ_COMPAT_CHANGE_CONFIG" />
|
||||||
|
|
||||||
<!-- os storage test permissions -->
|
<!-- os storage test permissions -->
|
||||||
<uses-permission android:name="android.permission.MOUNT_UNMOUNT_FILESYSTEMS" />
|
<uses-permission android:name="android.permission.MOUNT_UNMOUNT_FILESYSTEMS" />
|
||||||
<uses-permission android:name="android.permission.ASEC_ACCESS" />
|
<uses-permission android:name="android.permission.ASEC_ACCESS" />
|
||||||
|
|||||||
@@ -26,6 +26,7 @@
|
|||||||
<permission name="android.permission.DELETE_PACKAGES"/>
|
<permission name="android.permission.DELETE_PACKAGES"/>
|
||||||
<permission name="android.permission.FORCE_STOP_PACKAGES"/>
|
<permission name="android.permission.FORCE_STOP_PACKAGES"/>
|
||||||
<permission name="android.permission.LOCAL_MAC_ADDRESS"/>
|
<permission name="android.permission.LOCAL_MAC_ADDRESS"/>
|
||||||
|
<permission name="android.permission.LOG_COMPAT_CHANGE" />
|
||||||
<permission name="android.permission.MANAGE_DEBUGGING"/>
|
<permission name="android.permission.MANAGE_DEBUGGING"/>
|
||||||
<permission name="android.permission.MANAGE_DEVICE_ADMINS"/>
|
<permission name="android.permission.MANAGE_DEVICE_ADMINS"/>
|
||||||
<permission name="android.permission.MANAGE_FINGERPRINT"/>
|
<permission name="android.permission.MANAGE_FINGERPRINT"/>
|
||||||
@@ -37,8 +38,10 @@
|
|||||||
<permission name="android.permission.MODIFY_PHONE_STATE"/>
|
<permission name="android.permission.MODIFY_PHONE_STATE"/>
|
||||||
<permission name="android.permission.MOUNT_UNMOUNT_FILESYSTEMS"/>
|
<permission name="android.permission.MOUNT_UNMOUNT_FILESYSTEMS"/>
|
||||||
<permission name="android.permission.MOVE_PACKAGE"/>
|
<permission name="android.permission.MOVE_PACKAGE"/>
|
||||||
|
<permission name="android.permission.OVERRIDE_COMPAT_CHANGE_CONFIG" />
|
||||||
<permission name="android.permission.OVERRIDE_WIFI_CONFIG"/>
|
<permission name="android.permission.OVERRIDE_WIFI_CONFIG"/>
|
||||||
<permission name="android.permission.PACKAGE_USAGE_STATS"/>
|
<permission name="android.permission.PACKAGE_USAGE_STATS"/>
|
||||||
|
<permission name="android.permission.READ_COMPAT_CHANGE_CONFIG" />
|
||||||
<permission name="android.permission.READ_PRIVILEGED_PHONE_STATE"/>
|
<permission name="android.permission.READ_PRIVILEGED_PHONE_STATE"/>
|
||||||
<permission name="android.permission.READ_SEARCH_INDEXABLES"/>
|
<permission name="android.permission.READ_SEARCH_INDEXABLES"/>
|
||||||
<permission name="android.permission.REBOOT"/>
|
<permission name="android.permission.REBOOT"/>
|
||||||
|
|||||||
@@ -343,6 +343,10 @@ applications that come with the platform
|
|||||||
<permission name="android.permission.CONTROL_INCALL_EXPERIENCE"/>
|
<permission name="android.permission.CONTROL_INCALL_EXPERIENCE"/>
|
||||||
<!-- Permission required for Tethering CTS tests. -->
|
<!-- Permission required for Tethering CTS tests. -->
|
||||||
<permission name="android.permission.TETHER_PRIVILEGED"/>
|
<permission name="android.permission.TETHER_PRIVILEGED"/>
|
||||||
|
<!-- Permissions required for ganting and logging -->
|
||||||
|
<permission name="android.permission.LOG_COMPAT_CHANGE" />
|
||||||
|
<permission name="android.permission.READ_COMPAT_CHANGE_CONFIG" />
|
||||||
|
<permission name="android.permission.OVERRIDE_COMPAT_CHANGE_CONFIG" />
|
||||||
<!-- Permissions required to test ambient display. -->
|
<!-- Permissions required to test ambient display. -->
|
||||||
<permission name="android.permission.READ_DREAM_STATE" />
|
<permission name="android.permission.READ_DREAM_STATE" />
|
||||||
<permission name="android.permission.WRITE_DREAM_STATE" />
|
<permission name="android.permission.WRITE_DREAM_STATE" />
|
||||||
|
|||||||
@@ -215,6 +215,11 @@
|
|||||||
<!-- permissions required for CTS test - PhoneStateListenerTest -->
|
<!-- permissions required for CTS test - PhoneStateListenerTest -->
|
||||||
<uses-permission android:name="android.permission.LISTEN_ALWAYS_REPORTED_SIGNAL_STRENGTH" />
|
<uses-permission android:name="android.permission.LISTEN_ALWAYS_REPORTED_SIGNAL_STRENGTH" />
|
||||||
|
|
||||||
|
<!-- Permissions required for ganting and logging -->
|
||||||
|
<uses-permission android:name="android.permission.LOG_COMPAT_CHANGE"/>
|
||||||
|
<uses-permission android:name="android.permission.READ_COMPAT_CHANGE_CONFIG"/>
|
||||||
|
<uses-permission android:name="android.permission.OVERRIDE_COMPAT_CHANGE_CONFIG"/>
|
||||||
|
|
||||||
<!-- Permission required for CTS test - UiModeManagerTest -->
|
<!-- Permission required for CTS test - UiModeManagerTest -->
|
||||||
<uses-permission android:name="android.permission.ENTER_CAR_MODE_PRIORITIZED"/>
|
<uses-permission android:name="android.permission.ENTER_CAR_MODE_PRIORITIZED"/>
|
||||||
|
|
||||||
|
|||||||
@@ -16,6 +16,11 @@
|
|||||||
|
|
||||||
package com.android.server.compat;
|
package com.android.server.compat;
|
||||||
|
|
||||||
|
import static android.Manifest.permission.LOG_COMPAT_CHANGE;
|
||||||
|
import static android.Manifest.permission.OVERRIDE_COMPAT_CHANGE_CONFIG;
|
||||||
|
import static android.Manifest.permission.READ_COMPAT_CHANGE_CONFIG;
|
||||||
|
import static android.content.pm.PackageManager.PERMISSION_GRANTED;
|
||||||
|
|
||||||
import android.app.ActivityManager;
|
import android.app.ActivityManager;
|
||||||
import android.app.IActivityManager;
|
import android.app.IActivityManager;
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
@@ -66,12 +71,14 @@ public class PlatformCompat extends IPlatformCompat.Stub {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void reportChange(long changeId, ApplicationInfo appInfo) {
|
public void reportChange(long changeId, ApplicationInfo appInfo) {
|
||||||
|
checkCompatChangeLogPermission();
|
||||||
reportChange(changeId, appInfo.uid,
|
reportChange(changeId, appInfo.uid,
|
||||||
ChangeReporter.STATE_LOGGED);
|
ChangeReporter.STATE_LOGGED);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void reportChangeByPackageName(long changeId, String packageName, int userId) {
|
public void reportChangeByPackageName(long changeId, String packageName, int userId) {
|
||||||
|
checkCompatChangeLogPermission();
|
||||||
ApplicationInfo appInfo = getApplicationInfo(packageName, userId);
|
ApplicationInfo appInfo = getApplicationInfo(packageName, userId);
|
||||||
if (appInfo == null) {
|
if (appInfo == null) {
|
||||||
return;
|
return;
|
||||||
@@ -81,11 +88,13 @@ public class PlatformCompat extends IPlatformCompat.Stub {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void reportChangeByUid(long changeId, int uid) {
|
public void reportChangeByUid(long changeId, int uid) {
|
||||||
|
checkCompatChangeLogPermission();
|
||||||
reportChange(changeId, uid, ChangeReporter.STATE_LOGGED);
|
reportChange(changeId, uid, ChangeReporter.STATE_LOGGED);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean isChangeEnabled(long changeId, ApplicationInfo appInfo) {
|
public boolean isChangeEnabled(long changeId, ApplicationInfo appInfo) {
|
||||||
|
checkCompatChangeReadAndLogPermission();
|
||||||
if (mCompatConfig.isChangeEnabled(changeId, appInfo)) {
|
if (mCompatConfig.isChangeEnabled(changeId, appInfo)) {
|
||||||
reportChange(changeId, appInfo.uid,
|
reportChange(changeId, appInfo.uid,
|
||||||
ChangeReporter.STATE_ENABLED);
|
ChangeReporter.STATE_ENABLED);
|
||||||
@@ -98,6 +107,7 @@ public class PlatformCompat extends IPlatformCompat.Stub {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean isChangeEnabledByPackageName(long changeId, String packageName, int userId) {
|
public boolean isChangeEnabledByPackageName(long changeId, String packageName, int userId) {
|
||||||
|
checkCompatChangeReadAndLogPermission();
|
||||||
ApplicationInfo appInfo = getApplicationInfo(packageName, userId);
|
ApplicationInfo appInfo = getApplicationInfo(packageName, userId);
|
||||||
if (appInfo == null) {
|
if (appInfo == null) {
|
||||||
return true;
|
return true;
|
||||||
@@ -107,6 +117,7 @@ public class PlatformCompat extends IPlatformCompat.Stub {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean isChangeEnabledByUid(long changeId, int uid) {
|
public boolean isChangeEnabledByUid(long changeId, int uid) {
|
||||||
|
checkCompatChangeReadAndLogPermission();
|
||||||
String[] packages = mContext.getPackageManager().getPackagesForUid(uid);
|
String[] packages = mContext.getPackageManager().getPackagesForUid(uid);
|
||||||
if (packages == null || packages.length == 0) {
|
if (packages == null || packages.length == 0) {
|
||||||
return true;
|
return true;
|
||||||
@@ -139,6 +150,7 @@ public class PlatformCompat extends IPlatformCompat.Stub {
|
|||||||
@Override
|
@Override
|
||||||
public void setOverrides(CompatibilityChangeConfig overrides, String packageName)
|
public void setOverrides(CompatibilityChangeConfig overrides, String packageName)
|
||||||
throws RemoteException, SecurityException {
|
throws RemoteException, SecurityException {
|
||||||
|
checkCompatChangeOverridePermission();
|
||||||
mCompatConfig.addOverrides(overrides, packageName);
|
mCompatConfig.addOverrides(overrides, packageName);
|
||||||
killPackage(packageName);
|
killPackage(packageName);
|
||||||
}
|
}
|
||||||
@@ -146,11 +158,13 @@ public class PlatformCompat extends IPlatformCompat.Stub {
|
|||||||
@Override
|
@Override
|
||||||
public void setOverridesForTest(CompatibilityChangeConfig overrides, String packageName)
|
public void setOverridesForTest(CompatibilityChangeConfig overrides, String packageName)
|
||||||
throws RemoteException, SecurityException {
|
throws RemoteException, SecurityException {
|
||||||
|
checkCompatChangeOverridePermission();
|
||||||
mCompatConfig.addOverrides(overrides, packageName);
|
mCompatConfig.addOverrides(overrides, packageName);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void clearOverrides(String packageName) throws RemoteException, SecurityException {
|
public void clearOverrides(String packageName) throws RemoteException, SecurityException {
|
||||||
|
checkCompatChangeOverridePermission();
|
||||||
mCompatConfig.removePackageOverrides(packageName);
|
mCompatConfig.removePackageOverrides(packageName);
|
||||||
killPackage(packageName);
|
killPackage(packageName);
|
||||||
}
|
}
|
||||||
@@ -158,12 +172,14 @@ public class PlatformCompat extends IPlatformCompat.Stub {
|
|||||||
@Override
|
@Override
|
||||||
public void clearOverridesForTest(String packageName)
|
public void clearOverridesForTest(String packageName)
|
||||||
throws RemoteException, SecurityException {
|
throws RemoteException, SecurityException {
|
||||||
|
checkCompatChangeOverridePermission();
|
||||||
mCompatConfig.removePackageOverrides(packageName);
|
mCompatConfig.removePackageOverrides(packageName);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean clearOverride(long changeId, String packageName)
|
public boolean clearOverride(long changeId, String packageName)
|
||||||
throws RemoteException, SecurityException {
|
throws RemoteException, SecurityException {
|
||||||
|
checkCompatChangeOverridePermission();
|
||||||
boolean existed = mCompatConfig.removeOverride(changeId, packageName);
|
boolean existed = mCompatConfig.removeOverride(changeId, packageName);
|
||||||
killPackage(packageName);
|
killPackage(packageName);
|
||||||
return existed;
|
return existed;
|
||||||
@@ -171,11 +187,13 @@ public class PlatformCompat extends IPlatformCompat.Stub {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public CompatibilityChangeConfig getAppConfig(ApplicationInfo appInfo) {
|
public CompatibilityChangeConfig getAppConfig(ApplicationInfo appInfo) {
|
||||||
|
checkCompatChangeReadAndLogPermission();
|
||||||
return mCompatConfig.getAppConfig(appInfo);
|
return mCompatConfig.getAppConfig(appInfo);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public CompatibilityChangeInfo[] listAllChanges() {
|
public CompatibilityChangeInfo[] listAllChanges() {
|
||||||
|
checkCompatChangeReadPermission();
|
||||||
return mCompatConfig.dumpChanges();
|
return mCompatConfig.dumpChanges();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -214,6 +232,7 @@ public class PlatformCompat extends IPlatformCompat.Stub {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
|
protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
|
||||||
|
checkCompatChangeReadAndLogPermission();
|
||||||
if (!DumpUtils.checkDumpAndUsageStatsPermission(mContext, "platform_compat", pw)) return;
|
if (!DumpUtils.checkDumpAndUsageStatsPermission(mContext, "platform_compat", pw)) return;
|
||||||
mCompatConfig.dumpConfig(pw);
|
mCompatConfig.dumpConfig(pw);
|
||||||
}
|
}
|
||||||
@@ -275,4 +294,30 @@ public class PlatformCompat extends IPlatformCompat.Stub {
|
|||||||
Binder.restoreCallingIdentity(identity);
|
Binder.restoreCallingIdentity(identity);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void checkCompatChangeLogPermission() throws SecurityException {
|
||||||
|
if (mContext.checkCallingOrSelfPermission(LOG_COMPAT_CHANGE)
|
||||||
|
!= PERMISSION_GRANTED) {
|
||||||
|
throw new SecurityException("Cannot log compat change usage");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void checkCompatChangeReadPermission() throws SecurityException {
|
||||||
|
if (mContext.checkCallingOrSelfPermission(READ_COMPAT_CHANGE_CONFIG)
|
||||||
|
!= PERMISSION_GRANTED) {
|
||||||
|
throw new SecurityException("Cannot read compat change");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void checkCompatChangeOverridePermission() throws SecurityException {
|
||||||
|
if (mContext.checkCallingOrSelfPermission(OVERRIDE_COMPAT_CHANGE_CONFIG)
|
||||||
|
!= PERMISSION_GRANTED) {
|
||||||
|
throw new SecurityException("Cannot override compat change");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void checkCompatChangeReadAndLogPermission() throws SecurityException {
|
||||||
|
checkCompatChangeReadPermission();
|
||||||
|
checkCompatChangeLogPermission();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -17,6 +17,8 @@
|
|||||||
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
|
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
package="com.android.frameworks.mockingservicestests">
|
package="com.android.frameworks.mockingservicestests">
|
||||||
|
|
||||||
|
<uses-permission android:name="android.permission.LOG_COMPAT_CHANGE"/>
|
||||||
|
<uses-permission android:name="android.permission.READ_COMPAT_CHANGE_CONFIG"/>
|
||||||
<uses-permission android:name="android.permission.CHANGE_CONFIGURATION" />
|
<uses-permission android:name="android.permission.CHANGE_CONFIGURATION" />
|
||||||
<uses-permission android:name="android.permission.HARDWARE_TEST"/>
|
<uses-permission android:name="android.permission.HARDWARE_TEST"/>
|
||||||
<uses-permission android:name="android.permission.INTERACT_ACROSS_USERS_FULL" />
|
<uses-permission android:name="android.permission.INTERACT_ACROSS_USERS_FULL" />
|
||||||
|
|||||||
@@ -64,6 +64,8 @@
|
|||||||
<uses-permission android:name="android.permission.WATCH_APPOPS" />
|
<uses-permission android:name="android.permission.WATCH_APPOPS" />
|
||||||
<uses-permission android:name="android.permission.FOREGROUND_SERVICE"/>
|
<uses-permission android:name="android.permission.FOREGROUND_SERVICE"/>
|
||||||
<uses-permission android:name="android.permission.SUSPEND_APPS"/>
|
<uses-permission android:name="android.permission.SUSPEND_APPS"/>
|
||||||
|
<uses-permission android:name="android.permission.LOG_COMPAT_CHANGE" />
|
||||||
|
<uses-permission android:name="android.permission.READ_COMPAT_CHANGE_CONFIG" />
|
||||||
<uses-permission android:name="android.permission.CONTROL_KEYGUARD"/>
|
<uses-permission android:name="android.permission.CONTROL_KEYGUARD"/>
|
||||||
<uses-permission android:name="android.permission.MANAGE_BIND_INSTANT_SERVICE"/>
|
<uses-permission android:name="android.permission.MANAGE_BIND_INSTANT_SERVICE"/>
|
||||||
<uses-permission android:name="android.permission.CONTROL_DISPLAY_COLOR_TRANSFORMS" />
|
<uses-permission android:name="android.permission.CONTROL_DISPLAY_COLOR_TRANSFORMS" />
|
||||||
|
|||||||
@@ -28,6 +28,8 @@
|
|||||||
<uses-permission android:name="android.permission.ACCESS_VOICE_INTERACTION_SERVICE" />
|
<uses-permission android:name="android.permission.ACCESS_VOICE_INTERACTION_SERVICE" />
|
||||||
<uses-permission android:name="android.permission.DEVICE_POWER" />
|
<uses-permission android:name="android.permission.DEVICE_POWER" />
|
||||||
<uses-permission android:name="android.permission.ACCESS_CONTENT_PROVIDERS_EXTERNALLY" />
|
<uses-permission android:name="android.permission.ACCESS_CONTENT_PROVIDERS_EXTERNALLY" />
|
||||||
|
<uses-permission android:name="android.permission.LOG_COMPAT_CHANGE"/>
|
||||||
|
<uses-permission android:name="android.permission.READ_COMPAT_CHANGE_CONFIG"/>
|
||||||
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
|
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
|
||||||
<uses-permission android:name="android.permission.OBSERVE_ROLE_HOLDERS" />
|
<uses-permission android:name="android.permission.OBSERVE_ROLE_HOLDERS" />
|
||||||
<uses-permission android:name="android.permission.GET_INTENT_SENDER_INTENT"/>
|
<uses-permission android:name="android.permission.GET_INTENT_SENDER_INTENT"/>
|
||||||
|
|||||||
@@ -18,14 +18,11 @@ android_test {
|
|||||||
name: "PlatformCompatGating",
|
name: "PlatformCompatGating",
|
||||||
// Only compile source java files in this apk.
|
// Only compile source java files in this apk.
|
||||||
srcs: ["src/**/*.java"],
|
srcs: ["src/**/*.java"],
|
||||||
certificate: "platform",
|
|
||||||
libs: [
|
|
||||||
"android.test.runner",
|
|
||||||
"android.test.base",
|
|
||||||
],
|
|
||||||
static_libs: [
|
static_libs: [
|
||||||
"junit",
|
"junit",
|
||||||
"android-support-test",
|
"androidx.test.runner",
|
||||||
|
"androidx.test.core",
|
||||||
|
"androidx.test.ext.junit",
|
||||||
"mockito-target-minus-junit4",
|
"mockito-target-minus-junit4",
|
||||||
"truth-prebuilt",
|
"truth-prebuilt",
|
||||||
"platform-compat-test-rules"
|
"platform-compat-test-rules"
|
||||||
|
|||||||
@@ -6,6 +6,6 @@
|
|||||||
<uses-library android:name="android.test.runner" />
|
<uses-library android:name="android.test.runner" />
|
||||||
</application>
|
</application>
|
||||||
|
|
||||||
<instrumentation android:name="android.support.test.runner.AndroidJUnitRunner"
|
<instrumentation android:name="androidx.test.runner.AndroidJUnitRunner"
|
||||||
android:targetPackage="com.android.tests.gating"/>
|
android:targetPackage="com.android.tests.gating"/>
|
||||||
</manifest>
|
</manifest>
|
||||||
|
|||||||
@@ -24,7 +24,6 @@
|
|||||||
|
|
||||||
<test class="com.android.tradefed.testtype.AndroidJUnitTest">
|
<test class="com.android.tradefed.testtype.AndroidJUnitTest">
|
||||||
<option name="package" value="com.android.tests.gating"/>
|
<option name="package" value="com.android.tests.gating"/>
|
||||||
<option name="runner" value="android.support.test.runner.AndroidJUnitRunner"/>
|
|
||||||
<option name="hidden-api-checks" value="false"/>
|
<option name="hidden-api-checks" value="false"/>
|
||||||
</test>
|
</test>
|
||||||
</configuration>
|
</configuration>
|
||||||
|
|||||||
@@ -18,8 +18,9 @@ package com.android.tests.gating;
|
|||||||
import static com.google.common.truth.Truth.assertThat;
|
import static com.google.common.truth.Truth.assertThat;
|
||||||
|
|
||||||
import android.compat.testing.PlatformCompatChangeRule;
|
import android.compat.testing.PlatformCompatChangeRule;
|
||||||
import android.support.test.InstrumentationRegistry;
|
|
||||||
import android.support.test.runner.AndroidJUnit4;
|
import androidx.test.ext.junit.runners.AndroidJUnit4;
|
||||||
|
import androidx.test.platform.app.InstrumentationRegistry;
|
||||||
|
|
||||||
import com.android.compat.testing.DummyApi;
|
import com.android.compat.testing.DummyApi;
|
||||||
|
|
||||||
@@ -81,14 +82,14 @@ public class PlatformCompatGatingTest {
|
|||||||
@Test
|
@Test
|
||||||
@EnableCompatChanges({DummyApi.CHANGE_SYSTEM_SERVER})
|
@EnableCompatChanges({DummyApi.CHANGE_SYSTEM_SERVER})
|
||||||
public void testDummyGatingPositiveSystemServer() {
|
public void testDummyGatingPositiveSystemServer() {
|
||||||
assertThat(
|
assertThat(DummyApi.dummySystemServer(
|
||||||
DummyApi.dummySystemServer(InstrumentationRegistry.getTargetContext())).isTrue();
|
InstrumentationRegistry.getInstrumentation().getTargetContext())).isTrue();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@DisableCompatChanges({DummyApi.CHANGE_SYSTEM_SERVER})
|
@DisableCompatChanges({DummyApi.CHANGE_SYSTEM_SERVER})
|
||||||
public void testDummyGatingNegativeSystemServer() {
|
public void testDummyGatingNegativeSystemServer() {
|
||||||
assertThat(
|
assertThat(DummyApi.dummySystemServer(
|
||||||
DummyApi.dummySystemServer(InstrumentationRegistry.getTargetContext())).isFalse();
|
InstrumentationRegistry.getInstrumentation().getTargetContext())).isFalse();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,319 @@
|
|||||||
|
/*
|
||||||
|
* 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.tests.gating;
|
||||||
|
|
||||||
|
import static android.Manifest.permission.LOG_COMPAT_CHANGE;
|
||||||
|
import static android.Manifest.permission.OVERRIDE_COMPAT_CHANGE_CONFIG;
|
||||||
|
import static android.Manifest.permission.READ_COMPAT_CHANGE_CONFIG;
|
||||||
|
|
||||||
|
import android.app.Instrumentation;
|
||||||
|
import android.app.UiAutomation;
|
||||||
|
import android.compat.Compatibility.ChangeConfig;
|
||||||
|
import android.content.Context;
|
||||||
|
import android.content.pm.PackageManager;
|
||||||
|
import android.os.Process;
|
||||||
|
import android.os.ServiceManager;
|
||||||
|
|
||||||
|
import androidx.test.platform.app.InstrumentationRegistry;
|
||||||
|
|
||||||
|
import com.android.internal.compat.CompatibilityChangeConfig;
|
||||||
|
import com.android.internal.compat.IPlatformCompat;
|
||||||
|
|
||||||
|
import org.junit.After;
|
||||||
|
import org.junit.Before;
|
||||||
|
import org.junit.Rule;
|
||||||
|
import org.junit.Test;
|
||||||
|
import org.junit.rules.ExpectedException;
|
||||||
|
import org.junit.runner.RunWith;
|
||||||
|
import org.junit.runners.JUnit4;
|
||||||
|
|
||||||
|
import java.util.HashSet;
|
||||||
|
import java.util.Set;
|
||||||
|
|
||||||
|
@RunWith(JUnit4.class)
|
||||||
|
public final class PlatformCompatPermissionsTest {
|
||||||
|
|
||||||
|
// private Context mContext;
|
||||||
|
private IPlatformCompat mPlatformCompat;
|
||||||
|
|
||||||
|
@Rule
|
||||||
|
public final ExpectedException thrown = ExpectedException.none();
|
||||||
|
private Context mContext;
|
||||||
|
private UiAutomation mUiAutomation;
|
||||||
|
private PackageManager mPackageManager;
|
||||||
|
|
||||||
|
@Before
|
||||||
|
public void setUp() {
|
||||||
|
// mContext;
|
||||||
|
mPlatformCompat = IPlatformCompat.Stub
|
||||||
|
.asInterface(ServiceManager.getService(Context.PLATFORM_COMPAT_SERVICE));
|
||||||
|
Instrumentation instrumentation = InstrumentationRegistry.getInstrumentation();
|
||||||
|
mUiAutomation = instrumentation.getUiAutomation();
|
||||||
|
mContext = instrumentation.getTargetContext();
|
||||||
|
|
||||||
|
mPackageManager = mContext.getPackageManager();
|
||||||
|
}
|
||||||
|
|
||||||
|
@After
|
||||||
|
public void tearDown() {
|
||||||
|
|
||||||
|
mUiAutomation.dropShellPermissionIdentity();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void reportChange_noLogCompatChangePermission_throwsSecurityException()
|
||||||
|
throws Throwable {
|
||||||
|
thrown.expect(SecurityException.class);
|
||||||
|
final String packageName = mContext.getPackageName();
|
||||||
|
|
||||||
|
mPlatformCompat.reportChange(1, mPackageManager.getApplicationInfo(packageName, 0));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void reportChange_logCompatChangePermission_noThrow()
|
||||||
|
throws Throwable {
|
||||||
|
mUiAutomation.adoptShellPermissionIdentity(LOG_COMPAT_CHANGE);
|
||||||
|
final String packageName = mContext.getPackageName();
|
||||||
|
|
||||||
|
mPlatformCompat.reportChange(1, mPackageManager.getApplicationInfo(packageName, 0));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void reportChangeByPackageName_noLogCompatChangePermission_throwsSecurityException()
|
||||||
|
throws Throwable {
|
||||||
|
thrown.expect(SecurityException.class);
|
||||||
|
final String packageName = mContext.getPackageName();
|
||||||
|
|
||||||
|
mPlatformCompat.reportChangeByPackageName(1, packageName, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void reportChangeByPackageName_logCompatChangePermission_noThrow()
|
||||||
|
throws Throwable {
|
||||||
|
mUiAutomation.adoptShellPermissionIdentity(LOG_COMPAT_CHANGE);
|
||||||
|
final String packageName = mContext.getPackageName();
|
||||||
|
|
||||||
|
mPlatformCompat.reportChangeByPackageName(1, packageName, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void reportChangeByUid_noLogCompatChangePermission_throwsSecurityException()
|
||||||
|
throws Throwable {
|
||||||
|
thrown.expect(SecurityException.class);
|
||||||
|
|
||||||
|
mPlatformCompat.reportChangeByUid(1, Process.myUid());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void reportChangeByUid_logCompatChangePermission_noThrow()
|
||||||
|
throws Throwable {
|
||||||
|
mUiAutomation.adoptShellPermissionIdentity(LOG_COMPAT_CHANGE);
|
||||||
|
|
||||||
|
mPlatformCompat.reportChangeByUid(1, Process.myUid());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void isChangeEnabled_noReadCompatConfigPermission_throwsSecurityException()
|
||||||
|
throws Throwable {
|
||||||
|
thrown.expect(SecurityException.class);
|
||||||
|
final String packageName = mContext.getPackageName();
|
||||||
|
|
||||||
|
mPlatformCompat.isChangeEnabled(1, mPackageManager.getApplicationInfo(packageName, 0));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void isChangeEnabled_noLogCompatChangeConfigPermission_throwsSecurityException()
|
||||||
|
throws Throwable {
|
||||||
|
thrown.expect(SecurityException.class);
|
||||||
|
mUiAutomation.adoptShellPermissionIdentity(READ_COMPAT_CHANGE_CONFIG);
|
||||||
|
final String packageName = mContext.getPackageName();
|
||||||
|
|
||||||
|
mPlatformCompat.isChangeEnabled(1, mPackageManager.getApplicationInfo(packageName, 0));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void isChangeEnabled_readAndLogCompatChangeConfigPermission_noThrow()
|
||||||
|
throws Throwable {
|
||||||
|
mUiAutomation.adoptShellPermissionIdentity(READ_COMPAT_CHANGE_CONFIG, LOG_COMPAT_CHANGE);
|
||||||
|
final String packageName = mContext.getPackageName();
|
||||||
|
|
||||||
|
mPlatformCompat.isChangeEnabled(1, mPackageManager.getApplicationInfo(packageName, 0));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void isChangeEnabledByPackageName_noReadCompatConfigPermission_throwsSecurityException()
|
||||||
|
throws Throwable {
|
||||||
|
thrown.expect(SecurityException.class);
|
||||||
|
final String packageName = mContext.getPackageName();
|
||||||
|
|
||||||
|
mPlatformCompat.isChangeEnabledByPackageName(1, packageName, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void isChangeEnabledByPackageName_noLogompatConfigPermission_throwsSecurityException()
|
||||||
|
throws Throwable {
|
||||||
|
thrown.expect(SecurityException.class);
|
||||||
|
mUiAutomation.adoptShellPermissionIdentity(READ_COMPAT_CHANGE_CONFIG);
|
||||||
|
final String packageName = mContext.getPackageName();
|
||||||
|
|
||||||
|
mPlatformCompat.isChangeEnabledByPackageName(1, packageName, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void isChangeEnabledByPackageName_readAndLogCompatChangeConfigPermission_noThrow()
|
||||||
|
throws Throwable {
|
||||||
|
mUiAutomation.adoptShellPermissionIdentity(READ_COMPAT_CHANGE_CONFIG, LOG_COMPAT_CHANGE);
|
||||||
|
final String packageName = mContext.getPackageName();
|
||||||
|
|
||||||
|
mPlatformCompat.isChangeEnabledByPackageName(1, packageName, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void isChangeEnabledByUid_noReadCompatConfigPermission_throwsSecurityException()
|
||||||
|
throws Throwable {
|
||||||
|
thrown.expect(SecurityException.class);
|
||||||
|
|
||||||
|
mPlatformCompat.isChangeEnabledByUid(1, Process.myUid());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void isChangeEnabledByUid_noLogCompatChangePermission_throwsSecurityException()
|
||||||
|
throws Throwable {
|
||||||
|
thrown.expect(SecurityException.class);
|
||||||
|
mUiAutomation.adoptShellPermissionIdentity(READ_COMPAT_CHANGE_CONFIG);
|
||||||
|
|
||||||
|
mPlatformCompat.isChangeEnabledByUid(1, Process.myUid());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void isChangeEnabledByUid_readAndLogCompatChangeConfigPermission_noThrow()
|
||||||
|
throws Throwable {
|
||||||
|
mUiAutomation.adoptShellPermissionIdentity(READ_COMPAT_CHANGE_CONFIG, LOG_COMPAT_CHANGE);
|
||||||
|
|
||||||
|
mPlatformCompat.isChangeEnabledByUid(1, Process.myUid());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void setOverrides_noOverridesPermission_throwsSecurityException()
|
||||||
|
throws Throwable {
|
||||||
|
thrown.expect(SecurityException.class);
|
||||||
|
Set<Long> enabled = new HashSet<>();
|
||||||
|
Set<Long> disabled = new HashSet<>();
|
||||||
|
ChangeConfig changeConfig = new ChangeConfig(enabled, disabled);
|
||||||
|
CompatibilityChangeConfig compatibilityChangeConfig =
|
||||||
|
new CompatibilityChangeConfig(changeConfig);
|
||||||
|
|
||||||
|
mPlatformCompat.setOverrides(compatibilityChangeConfig, "foo.bar");
|
||||||
|
}
|
||||||
|
@Test
|
||||||
|
public void setOverrides_overridesPermission_noThrow()
|
||||||
|
throws Throwable {
|
||||||
|
mUiAutomation.adoptShellPermissionIdentity(OVERRIDE_COMPAT_CHANGE_CONFIG);
|
||||||
|
Set<Long> enabled = new HashSet<>();
|
||||||
|
Set<Long> disabled = new HashSet<>();
|
||||||
|
ChangeConfig changeConfig = new ChangeConfig(enabled, disabled);
|
||||||
|
CompatibilityChangeConfig compatibilityChangeConfig =
|
||||||
|
new CompatibilityChangeConfig(changeConfig);
|
||||||
|
|
||||||
|
mPlatformCompat.setOverrides(compatibilityChangeConfig, "foo.bar");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void setOverridesForTest_noOverridesPermission_throwsSecurityException()
|
||||||
|
throws Throwable {
|
||||||
|
thrown.expect(SecurityException.class);
|
||||||
|
Set<Long> enabled = new HashSet<>();
|
||||||
|
Set<Long> disabled = new HashSet<>();
|
||||||
|
ChangeConfig changeConfig = new ChangeConfig(enabled, disabled);
|
||||||
|
CompatibilityChangeConfig compatibilityChangeConfig =
|
||||||
|
new CompatibilityChangeConfig(changeConfig);
|
||||||
|
|
||||||
|
mPlatformCompat.setOverridesForTest(compatibilityChangeConfig, "foo.bar");
|
||||||
|
}
|
||||||
|
@Test
|
||||||
|
public void setOverridesForTest_overridesPermission_noThrow()
|
||||||
|
throws Throwable {
|
||||||
|
mUiAutomation.adoptShellPermissionIdentity(OVERRIDE_COMPAT_CHANGE_CONFIG);
|
||||||
|
Set<Long> enabled = new HashSet<>();
|
||||||
|
Set<Long> disabled = new HashSet<>();
|
||||||
|
ChangeConfig changeConfig = new ChangeConfig(enabled, disabled);
|
||||||
|
CompatibilityChangeConfig compatibilityChangeConfig =
|
||||||
|
new CompatibilityChangeConfig(changeConfig);
|
||||||
|
|
||||||
|
mPlatformCompat.setOverridesForTest(compatibilityChangeConfig, "foo.bar");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void clearOverrides_noOverridesPermission_throwsSecurityException()
|
||||||
|
throws Throwable {
|
||||||
|
thrown.expect(SecurityException.class);
|
||||||
|
|
||||||
|
mPlatformCompat.clearOverrides("foo.bar");
|
||||||
|
}
|
||||||
|
@Test
|
||||||
|
public void clearOverrides_overridesPermission_noThrow()
|
||||||
|
throws Throwable {
|
||||||
|
mUiAutomation.adoptShellPermissionIdentity(OVERRIDE_COMPAT_CHANGE_CONFIG);
|
||||||
|
|
||||||
|
mPlatformCompat.clearOverrides("foo.bar");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void clearOverridesForTest_noOverridesPermission_throwsSecurityException()
|
||||||
|
throws Throwable {
|
||||||
|
thrown.expect(SecurityException.class);
|
||||||
|
|
||||||
|
mPlatformCompat.clearOverridesForTest("foo.bar");
|
||||||
|
}
|
||||||
|
@Test
|
||||||
|
public void clearOverridesForTest_overridesPermission_noThrow()
|
||||||
|
throws Throwable {
|
||||||
|
mUiAutomation.adoptShellPermissionIdentity(OVERRIDE_COMPAT_CHANGE_CONFIG);
|
||||||
|
|
||||||
|
mPlatformCompat.clearOverridesForTest("foo.bar");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void clearOverride_noOverridesPermission_throwsSecurityException()
|
||||||
|
throws Throwable {
|
||||||
|
thrown.expect(SecurityException.class);
|
||||||
|
|
||||||
|
mPlatformCompat.clearOverride(1, "foo.bar");
|
||||||
|
}
|
||||||
|
@Test
|
||||||
|
public void clearOverride_overridesPermission_noThrow()
|
||||||
|
throws Throwable {
|
||||||
|
mUiAutomation.adoptShellPermissionIdentity(OVERRIDE_COMPAT_CHANGE_CONFIG);
|
||||||
|
|
||||||
|
mPlatformCompat.clearOverride(1, "foo.bar");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void listAllChanges_noReadCompatConfigPermission_throwsSecurityException()
|
||||||
|
throws Throwable {
|
||||||
|
thrown.expect(SecurityException.class);
|
||||||
|
|
||||||
|
mPlatformCompat.listAllChanges();
|
||||||
|
}
|
||||||
|
@Test
|
||||||
|
public void listAllChanges_readCompatConfigPermission_noThrow()
|
||||||
|
throws Throwable {
|
||||||
|
mUiAutomation.adoptShellPermissionIdentity(READ_COMPAT_CHANGE_CONFIG);
|
||||||
|
|
||||||
|
mPlatformCompat.listAllChanges();
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -19,7 +19,7 @@ java_library {
|
|||||||
srcs: ["src/**/*.java"],
|
srcs: ["src/**/*.java"],
|
||||||
static_libs: [
|
static_libs: [
|
||||||
"junit",
|
"junit",
|
||||||
"android-support-test",
|
"androidx.test.core",
|
||||||
"truth-prebuilt",
|
"truth-prebuilt",
|
||||||
"core-compat-test-rules"
|
"core-compat-test-rules"
|
||||||
],
|
],
|
||||||
|
|||||||
@@ -16,13 +16,17 @@
|
|||||||
|
|
||||||
package android.compat.testing;
|
package android.compat.testing;
|
||||||
|
|
||||||
|
import android.Manifest;
|
||||||
import android.app.Instrumentation;
|
import android.app.Instrumentation;
|
||||||
|
import android.app.UiAutomation;
|
||||||
import android.compat.Compatibility;
|
import android.compat.Compatibility;
|
||||||
import android.compat.Compatibility.ChangeConfig;
|
import android.compat.Compatibility.ChangeConfig;
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
import android.os.RemoteException;
|
import android.os.RemoteException;
|
||||||
import android.os.ServiceManager;
|
import android.os.ServiceManager;
|
||||||
import android.support.test.InstrumentationRegistry;
|
|
||||||
|
import androidx.test.platform.app.InstrumentationRegistry;
|
||||||
|
|
||||||
|
|
||||||
import com.android.internal.compat.CompatibilityChangeConfig;
|
import com.android.internal.compat.CompatibilityChangeConfig;
|
||||||
import com.android.internal.compat.IPlatformCompat;
|
import com.android.internal.compat.IPlatformCompat;
|
||||||
@@ -83,12 +87,17 @@ public class PlatformCompatChangeRule extends CoreCompatChangeRule {
|
|||||||
@Override
|
@Override
|
||||||
public void evaluate() throws Throwable {
|
public void evaluate() throws Throwable {
|
||||||
Instrumentation instrumentation = InstrumentationRegistry.getInstrumentation();
|
Instrumentation instrumentation = InstrumentationRegistry.getInstrumentation();
|
||||||
|
UiAutomation uiAutomation = instrumentation.getUiAutomation();
|
||||||
String packageName = instrumentation.getTargetContext().getPackageName();
|
String packageName = instrumentation.getTargetContext().getPackageName();
|
||||||
IPlatformCompat platformCompat = IPlatformCompat.Stub
|
IPlatformCompat platformCompat = IPlatformCompat.Stub
|
||||||
.asInterface(ServiceManager.getService(Context.PLATFORM_COMPAT_SERVICE));
|
.asInterface(ServiceManager.getService(Context.PLATFORM_COMPAT_SERVICE));
|
||||||
if (platformCompat == null) {
|
if (platformCompat == null) {
|
||||||
throw new IllegalStateException("Could not get IPlatformCompat service!");
|
throw new IllegalStateException("Could not get IPlatformCompat service!");
|
||||||
}
|
}
|
||||||
|
uiAutomation.adoptShellPermissionIdentity(
|
||||||
|
Manifest.permission.LOG_COMPAT_CHANGE,
|
||||||
|
Manifest.permission.OVERRIDE_COMPAT_CHANGE_CONFIG,
|
||||||
|
Manifest.permission.READ_COMPAT_CHANGE_CONFIG);
|
||||||
Compatibility.setOverrides(mConfig);
|
Compatibility.setOverrides(mConfig);
|
||||||
try {
|
try {
|
||||||
platformCompat.setOverridesForTest(new CompatibilityChangeConfig(mConfig),
|
platformCompat.setOverridesForTest(new CompatibilityChangeConfig(mConfig),
|
||||||
@@ -101,6 +110,7 @@ public class PlatformCompatChangeRule extends CoreCompatChangeRule {
|
|||||||
} catch (RemoteException e) {
|
} catch (RemoteException e) {
|
||||||
throw new RuntimeException("Could not call IPlatformCompat binder method!", e);
|
throw new RuntimeException("Could not call IPlatformCompat binder method!", e);
|
||||||
} finally {
|
} finally {
|
||||||
|
uiAutomation.dropShellPermissionIdentity();
|
||||||
Compatibility.clearOverrides();
|
Compatibility.clearOverrides();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user