Split query permission from update permission
Split time zone rules query permission from update permission.
This would allow an app like Settings to determine the current rules
update state, which would enable it to show the version of rules
the device came with, if there have been any updates and whether
a reboot is needed for changes to take effect.
Test: PTS: run -m PtsTimeZoneTestCases
Test: atest FrameworksServicesTests:RulesManagerServiceTest
Bug: 69443060
Change-Id: Ia5d31814d7caee842f5e28870fab61f7c7129386
diff --git a/api/system-current.txt b/api/system-current.txt
index 3dbb333..5ec8ad3 100644
--- a/api/system-current.txt
+++ b/api/system-current.txt
@@ -123,6 +123,7 @@
field public static final java.lang.String PERFORM_SIM_ACTIVATION = "android.permission.PERFORM_SIM_ACTIVATION";
field public static final java.lang.String PROVIDE_RESOLVER_RANKER_SERVICE = "android.permission.PROVIDE_RESOLVER_RANKER_SERVICE";
field public static final java.lang.String PROVIDE_TRUST_AGENT = "android.permission.PROVIDE_TRUST_AGENT";
+ field public static final java.lang.String QUERY_TIME_ZONE_RULES = "android.permission.QUERY_TIME_ZONE_RULES";
field public static final java.lang.String READ_CONTENT_RATING_SYSTEMS = "android.permission.READ_CONTENT_RATING_SYSTEMS";
field public static final java.lang.String READ_DREAM_STATE = "android.permission.READ_DREAM_STATE";
field public static final java.lang.String READ_FRAME_BUFFER = "android.permission.READ_FRAME_BUFFER";
diff --git a/core/java/android/app/timezone/RulesManager.java b/core/java/android/app/timezone/RulesManager.java
index dc79256..fe83113 100644
--- a/core/java/android/app/timezone/RulesManager.java
+++ b/core/java/android/app/timezone/RulesManager.java
@@ -36,7 +36,7 @@
* <p>This interface is intended for use with the default APK-based time zone rules update
* application but it can also be used by OEMs if that mechanism is turned off using configuration.
* All callers must possess the {@link android.Manifest.permission#UPDATE_TIME_ZONE_RULES} system
- * permission.
+ * permission unless otherwise stated.
*
* <p>When using the default mechanism, when properly configured the Android system will send a
* {@link RulesUpdaterContract#ACTION_TRIGGER_RULES_UPDATE_CHECK} intent with a
@@ -120,9 +120,12 @@
/**
* Returns information about the current time zone rules state such as the IANA version of
- * the system and any currently installed distro. This method is intended to allow clients to
- * determine if the current state can be improved; for example by passing the information to a
- * server that may provide a new distro for download.
+ * the system and any currently installed distro. This method allows clients to determine the
+ * current device state, perhaps to see if it can be improved; for example by passing the
+ * information to a server that may provide a new distro for download.
+ *
+ * <p>Callers must possess the {@link android.Manifest.permission#QUERY_TIME_ZONE_RULES} system
+ * permission.
*/
public RulesState getRulesState() {
try {
diff --git a/core/res/AndroidManifest.xml b/core/res/AndroidManifest.xml
index 022cf22..9dc6d71 100644
--- a/core/res/AndroidManifest.xml
+++ b/core/res/AndroidManifest.xml
@@ -2397,6 +2397,12 @@
<permission android:name="android.permission.UPDATE_CONFIG"
android:protectionLevel="signature|privileged" />
+ <!-- Allows an application to query the current time zone rules state
+ on device.
+ @SystemApi @hide -->
+ <permission android:name="android.permission.QUERY_TIME_ZONE_RULES"
+ android:protectionLevel="signature|privileged" />
+
<!-- Allows a time zone rule updater application to request
the system installs / uninstalls timezone rules.
<p>An application requesting this permission is responsible for
diff --git a/services/core/java/com/android/server/timezone/RulesManagerService.java b/services/core/java/com/android/server/timezone/RulesManagerService.java
index 872d723..23c4a337 100644
--- a/services/core/java/com/android/server/timezone/RulesManagerService.java
+++ b/services/core/java/com/android/server/timezone/RulesManagerService.java
@@ -92,6 +92,9 @@
@VisibleForTesting(visibility = VisibleForTesting.Visibility.PRIVATE)
static final String REQUIRED_UPDATER_PERMISSION =
android.Manifest.permission.UPDATE_TIME_ZONE_RULES;
+ @VisibleForTesting(visibility = VisibleForTesting.Visibility.PRIVATE)
+ static final String REQUIRED_QUERY_PERMISSION =
+ android.Manifest.permission.QUERY_TIME_ZONE_RULES;
private static final File SYSTEM_TZ_DATA_FILE = new File("/system/usr/share/zoneinfo/tzdata");
private static final File TZ_DATA_DIR = new File("/data/misc/zoneinfo");
@@ -131,7 +134,7 @@
@Override // Binder call
public RulesState getRulesState() {
- mPermissionHelper.enforceCallerHasPermission(REQUIRED_UPDATER_PERMISSION);
+ mPermissionHelper.enforceCallerHasPermission(REQUIRED_QUERY_PERMISSION);
return getRulesStateInternal();
}
diff --git a/services/tests/servicestests/src/com/android/server/timezone/RulesManagerServiceTest.java b/services/tests/servicestests/src/com/android/server/timezone/RulesManagerServiceTest.java
index f5969f3..c252609 100644
--- a/services/tests/servicestests/src/com/android/server/timezone/RulesManagerServiceTest.java
+++ b/services/tests/servicestests/src/com/android/server/timezone/RulesManagerServiceTest.java
@@ -41,6 +41,7 @@
import libcore.io.IoUtils;
+import static com.android.server.timezone.RulesManagerService.REQUIRED_QUERY_PERMISSION;
import static com.android.server.timezone.RulesManagerService.REQUIRED_UPDATER_PERMISSION;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
@@ -91,25 +92,25 @@
@Test(expected = SecurityException.class)
public void getRulesState_noCallerPermission() throws Exception {
- configureCallerDoesNotHavePermission();
+ configureCallerDoesNotHaveQueryPermission();
mRulesManagerService.getRulesState();
}
@Test(expected = SecurityException.class)
public void requestInstall_noCallerPermission() throws Exception {
- configureCallerDoesNotHavePermission();
+ configureCallerDoesNotHaveUpdatePermission();
mRulesManagerService.requestInstall(null, null, null);
}
@Test(expected = SecurityException.class)
public void requestUninstall_noCallerPermission() throws Exception {
- configureCallerDoesNotHavePermission();
+ configureCallerDoesNotHaveUpdatePermission();
mRulesManagerService.requestUninstall(null, null);
}
@Test(expected = SecurityException.class)
public void requestNothing_noCallerPermission() throws Exception {
- configureCallerDoesNotHavePermission();
+ configureCallerDoesNotHaveUpdatePermission();
mRulesManagerService.requestNothing(null, true);
}
@@ -916,12 +917,18 @@
.enforceCallerHasPermission(REQUIRED_UPDATER_PERMISSION);
}
- private void configureCallerDoesNotHavePermission() {
+ private void configureCallerDoesNotHaveUpdatePermission() {
doThrow(new SecurityException("Simulated permission failure"))
.when(mMockPermissionHelper)
.enforceCallerHasPermission(REQUIRED_UPDATER_PERMISSION);
}
+ private void configureCallerDoesNotHaveQueryPermission() {
+ doThrow(new SecurityException("Simulated permission failure"))
+ .when(mMockPermissionHelper)
+ .enforceCallerHasPermission(REQUIRED_QUERY_PERMISSION);
+ }
+
private void configureStageInstallExpectation(int resultCode)
throws Exception {
when(mMockTimeZoneDistroInstaller.stageInstallWithErrorCode(any(TimeZoneDistro.class)))