Don't accept resource references in string fields
Detect it when a developer accidentally uses @string/... in string fields
and log an error rather than publishing shortcuts with wrong values.
Bug 30140672
Change-Id: I98a60afd7f52282019a94a7a8c30a85ea4c7806b
diff --git a/services/core/java/com/android/server/pm/ShortcutParser.java b/services/core/java/com/android/server/pm/ShortcutParser.java
index 0762c0b..3f302d6 100644
--- a/services/core/java/com/android/server/pm/ShortcutParser.java
+++ b/services/core/java/com/android/server/pm/ShortcutParser.java
@@ -29,6 +29,7 @@
import android.util.AttributeSet;
import android.util.Log;
import android.util.Slog;
+import android.util.TypedValue;
import android.util.Xml;
import com.android.internal.R;
@@ -260,7 +261,12 @@
final TypedArray sa = service.mContext.getResources().obtainAttributes(attrs,
R.styleable.ShortcutCategories);
try {
- return sa.getString(R.styleable.ShortcutCategories_name);
+ if (sa.getType(R.styleable.ShortcutCategories_name) == TypedValue.TYPE_STRING) {
+ return sa.getNonResourceString(R.styleable.ShortcutCategories_name);
+ } else {
+ Log.w(TAG, "android:name for shortcut category must be string literal.");
+ return null;
+ }
} finally {
sa.recycle();
}
@@ -272,7 +278,11 @@
final TypedArray sa = service.mContext.getResources().obtainAttributes(attrs,
R.styleable.Shortcut);
try {
- final String id = sa.getString(R.styleable.Shortcut_shortcutId);
+ if (sa.getType(R.styleable.Shortcut_shortcutId) != TypedValue.TYPE_STRING) {
+ Log.w(TAG, "android:shortcutId must be string literal. activity=" + activity);
+ return null;
+ }
+ final String id = sa.getNonResourceString(R.styleable.Shortcut_shortcutId);
final boolean enabled = sa.getBoolean(R.styleable.Shortcut_enabled, true);
final int iconResId = sa.getResourceId(R.styleable.Shortcut_icon, 0);
final int titleResId = sa.getResourceId(R.styleable.Shortcut_shortcutShortLabel, 0);
@@ -281,11 +291,11 @@
R.styleable.Shortcut_shortcutDisabledMessage, 0);
if (TextUtils.isEmpty(id)) {
- Slog.w(TAG, "Shortcut ID must be provided. activity=" + activity);
+ Log.w(TAG, "android:shortcutId must be provided. activity=" + activity);
return null;
}
if (titleResId == 0) {
- Slog.w(TAG, "Shortcut title must be provided. activity=" + activity);
+ Log.w(TAG, "android:shortcutShortLabel must be provided. activity=" + activity);
return null;
}
diff --git a/services/tests/servicestests/res/xml/shortcut_error_3.xml b/services/tests/servicestests/res/xml/shortcut_error_3.xml
index a7b9b84..24ee024 100644
--- a/services/tests/servicestests/res/xml/shortcut_error_3.xml
+++ b/services/tests/servicestests/res/xml/shortcut_error_3.xml
@@ -19,6 +19,10 @@
android:shortcutShortLabel="@string/shortcut_title1"
/>
<shortcut
+ android:shortcutId="@string/shortcut_title1"
+ android:shortcutShortLabel="@string/shortcut_title1"
+ />
+ <shortcut
android:shortcutId="x3"
android:shortcutShortLabel="@string/shortcut_title1"
>
@@ -26,5 +30,7 @@
android:action="android.intent.action.VIEW"
>
</intent>
+ <categories android:name="@string/shortcut_title1" />
+ <categories android:name="cat2" />
</shortcut>
</shortcuts>
diff --git a/services/tests/servicestests/src/com/android/server/pm/ShortcutManagerTest1.java b/services/tests/servicestests/src/com/android/server/pm/ShortcutManagerTest1.java
index bf6c2ff..ae2d632 100644
--- a/services/tests/servicestests/src/com/android/server/pm/ShortcutManagerTest1.java
+++ b/services/tests/servicestests/src/com/android/server/pm/ShortcutManagerTest1.java
@@ -5856,9 +5856,11 @@
// Only the valid one is published.
runWithCaller(CALLING_PACKAGE_1, USER_0, () -> {
- assertShortcutIds(assertAllManifest(assertAllImmutable(assertAllEnabled(
- mManager.getManifestShortcuts()))),
- "x1");
+ assertWith(getCallerShortcuts())
+ .areAllManifest()
+ .areAllImmutable()
+ .areAllEnabled()
+ .haveIds("x1");
});
// Package 1 updated, which has one valid manifest shortcut and one invalid.
@@ -5871,9 +5873,11 @@
// Only the valid one is published.
runWithCaller(CALLING_PACKAGE_1, USER_0, () -> {
- assertShortcutIds(assertAllManifest(assertAllImmutable(assertAllEnabled(
- mManager.getManifestShortcuts()))),
- "x2");
+ assertWith(getCallerShortcuts())
+ .areAllManifest()
+ .areAllImmutable()
+ .areAllEnabled()
+ .haveIds("x2");
});
// Package 1 updated, which has one valid manifest shortcut and one invalid.
@@ -5886,9 +5890,14 @@
// Only the valid one is published.
runWithCaller(CALLING_PACKAGE_1, USER_0, () -> {
- assertShortcutIds(assertAllManifest(assertAllImmutable(assertAllEnabled(
- mManager.getManifestShortcuts()))),
- "x3");
+ assertWith(getCallerShortcuts())
+ .areAllManifest()
+ .areAllImmutable()
+ .areAllEnabled()
+ .haveIds("x3")
+ .forShortcutWithId("x3", si -> {
+ assertEquals(set("cat2"), si.getCategories());
+ });
});
}