From 78c5e5dd00278c4e6ed4ced3ca48b963271b21ff Mon Sep 17 00:00:00 2001 From: Jaewoong Jung Date: Thu, 15 Jun 2017 18:02:44 -0700 Subject: [PATCH] Allows to change summary text in a custom view tile. Now it becomes possible to use META_DATA_PREFERENCE_SUMMARY_URI in in conjunction with META_DATA_PREFERENCE_CUSTOM_VIEW. Bug: 62384773 Test: make RunSettingsLibRoboTests -j40 Change-Id: I91401140b2ed0b12c26b91c8fb3d464179e75844 --- .../android/settingslib/drawer/TileUtils.java | 19 +++- .../settingslib/drawer/TileUtilsTest.java | 101 +++++++++++++++++- 2 files changed, 116 insertions(+), 4 deletions(-) diff --git a/packages/SettingsLib/src/com/android/settingslib/drawer/TileUtils.java b/packages/SettingsLib/src/com/android/settingslib/drawer/TileUtils.java index f52a6b5cac56a..04a3d1f815611 100644 --- a/packages/SettingsLib/src/com/android/settingslib/drawer/TileUtils.java +++ b/packages/SettingsLib/src/com/android/settingslib/drawer/TileUtils.java @@ -165,6 +165,9 @@ public class TileUtils { * Name of the meta-data item that should be set in the AndroidManifest.xml to specify the * custom view which should be displayed for the preference. The custom view will be inflated * as a remote view. + * + * This also can be used with {@link META_DATA_PREFERENCE_SUMMARY_URI} above, by setting the id + * of the summary TextView to '@android:id/summary'. */ public static final String META_DATA_PREFERENCE_CUSTOM_VIEW = "com.android.settings.custom_view"; @@ -315,6 +318,7 @@ public class TileUtils { PackageManager pm = context.getPackageManager(); List results = pm.queryIntentActivitiesAsUser(intent, PackageManager.GET_META_DATA, user.getIdentifier()); + Map providerMap = new HashMap<>(); for (ResolveInfo resolved : results) { if (!resolved.system) { // Do not allow any app to add to settings, only system ones. @@ -346,7 +350,7 @@ public class TileUtils { tile.priority = usePriority ? resolved.priority : 0; tile.metaData = activityInfo.metaData; updateTileData(context, tile, activityInfo, activityInfo.applicationInfo, - pm); + pm, providerMap); if (DEBUG) Log.d(LOG_TAG, "Adding tile " + tile.title); addedCache.put(key, tile); @@ -361,14 +365,14 @@ public class TileUtils { } private static boolean updateTileData(Context context, Tile tile, - ActivityInfo activityInfo, ApplicationInfo applicationInfo, PackageManager pm) { + ActivityInfo activityInfo, ApplicationInfo applicationInfo, PackageManager pm, + Map providerMap) { if (applicationInfo.isSystemApp()) { int icon = 0; Pair iconFromUri = null; CharSequence title = null; String summary = null; String keyHint = null; - Uri uri = null; RemoteViews remoteViews = null; // Get the activity's meta-data @@ -414,6 +418,15 @@ public class TileUtils { if (metaData.containsKey(META_DATA_PREFERENCE_CUSTOM_VIEW)) { int layoutId = metaData.getInt(META_DATA_PREFERENCE_CUSTOM_VIEW); remoteViews = new RemoteViews(applicationInfo.packageName, layoutId); + if (metaData.containsKey(META_DATA_PREFERENCE_SUMMARY_URI)) { + String uriString = metaData.getString( + META_DATA_PREFERENCE_SUMMARY_URI); + String overrideSummary = getTextFromUri(context, uriString, providerMap, + META_DATA_PREFERENCE_SUMMARY); + if (overrideSummary != null) { + remoteViews.setTextViewText(android.R.id.summary, overrideSummary); + } + } } } } catch (PackageManager.NameNotFoundException | Resources.NotFoundException e) { diff --git a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/drawer/TileUtilsTest.java b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/drawer/TileUtilsTest.java index a2e0e2c5b46bf..7cfb32d7bdb03 100644 --- a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/drawer/TileUtilsTest.java +++ b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/drawer/TileUtilsTest.java @@ -36,6 +36,7 @@ import android.provider.Settings.Global; import android.text.TextUtils; import android.util.ArrayMap; import android.util.Pair; +import android.widget.RemoteViews; import com.android.settingslib.R; import com.android.settingslib.TestConfig; @@ -51,6 +52,7 @@ import org.mockito.MockitoAnnotations; import org.robolectric.RobolectricTestRunner; import org.robolectric.RuntimeEnvironment; import org.robolectric.annotation.Config; +import org.robolectric.internal.ShadowExtractor; import java.util.ArrayList; import java.util.Collections; @@ -68,9 +70,13 @@ import static org.mockito.Mockito.spy; import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; +import org.robolectric.annotation.Implementation; +import org.robolectric.annotation.Implements; @RunWith(RobolectricTestRunner.class) -@Config(manifest = TestConfig.MANIFEST_PATH, sdk = TestConfig.SDK_VERSION) +@Config(manifest = TestConfig.MANIFEST_PATH, + sdk = TestConfig.SDK_VERSION, + shadows = {TileUtilsTest.TileUtilsShadowRemoteViews.class}) public class TileUtilsTest { @Mock @@ -364,6 +370,86 @@ public class TileUtilsTest { assertThat(tile.remoteViews.getLayoutId()).isEqualTo(R.layout.user_preference); } + @Test + public void getTilesForIntent_summaryUriSpecified_shouldOverrideRemoteViewSummary() + throws RemoteException { + Intent intent = new Intent(); + Map, Tile> addedCache = new ArrayMap<>(); + List outTiles = new ArrayList<>(); + List info = new ArrayList<>(); + ResolveInfo resolveInfo = newInfo(true, null /* category */, null, + null, URI_GET_SUMMARY); + resolveInfo.activityInfo.metaData.putInt("com.android.settings.custom_view", + R.layout.user_preference); + info.add(resolveInfo); + + when(mPackageManager.queryIntentActivitiesAsUser(eq(intent), anyInt(), anyInt())) + .thenReturn(info); + + // Mock the content provider interaction. + Bundle bundle = new Bundle(); + bundle.putString(TileUtils.META_DATA_PREFERENCE_SUMMARY, "new summary text"); + when(mIContentProvider.call(anyString(), + eq(TileUtils.getMethodFromUri(Uri.parse(URI_GET_SUMMARY))), eq(URI_GET_SUMMARY), + any())).thenReturn(bundle); + when(mContentResolver.acquireUnstableProvider(anyString())) + .thenReturn(mIContentProvider); + when(mContentResolver.acquireUnstableProvider(any(Uri.class))) + .thenReturn(mIContentProvider); + + TileUtils.getTilesForIntent(mContext, UserHandle.CURRENT, intent, addedCache, + null /* defaultCategory */, outTiles, false /* usePriority */, + false /* checkCategory */); + + assertThat(outTiles.size()).isEqualTo(1); + Tile tile = outTiles.get(0); + assertThat(tile.remoteViews).isNotNull(); + assertThat(tile.remoteViews.getLayoutId()).isEqualTo(R.layout.user_preference); + // Make sure the summary TextView got a new text string. + TileUtilsShadowRemoteViews shadowRemoteViews = + (TileUtilsShadowRemoteViews) ShadowExtractor.extract(tile.remoteViews); + assertThat(shadowRemoteViews.overrideViewId).isEqualTo(android.R.id.summary); + assertThat(shadowRemoteViews.overrideText).isEqualTo("new summary text"); + } + + @Test + public void getTilesForIntent_providerUnavailable_shouldNotOverrideRemoteViewSummary() + throws RemoteException { + Intent intent = new Intent(); + Map, Tile> addedCache = new ArrayMap<>(); + List outTiles = new ArrayList<>(); + List info = new ArrayList<>(); + ResolveInfo resolveInfo = newInfo(true, null /* category */, null, + null, URI_GET_SUMMARY); + resolveInfo.activityInfo.metaData.putInt("com.android.settings.custom_view", + R.layout.user_preference); + info.add(resolveInfo); + + when(mPackageManager.queryIntentActivitiesAsUser(eq(intent), anyInt(), anyInt())) + .thenReturn(info); + + // Mock the content provider interaction. + Bundle bundle = new Bundle(); + bundle.putString(TileUtils.META_DATA_PREFERENCE_SUMMARY, "new summary text"); + when(mIContentProvider.call(anyString(), + eq(TileUtils.getMethodFromUri(Uri.parse(URI_GET_SUMMARY))), eq(URI_GET_SUMMARY), + any())).thenReturn(bundle); + + TileUtils.getTilesForIntent(mContext, UserHandle.CURRENT, intent, addedCache, + null /* defaultCategory */, outTiles, false /* usePriority */, + false /* checkCategory */); + + assertThat(outTiles.size()).isEqualTo(1); + Tile tile = outTiles.get(0); + assertThat(tile.remoteViews).isNotNull(); + assertThat(tile.remoteViews.getLayoutId()).isEqualTo(R.layout.user_preference); + // Make sure the summary TextView didn't get any text view updates. + TileUtilsShadowRemoteViews shadowRemoteViews = + (TileUtilsShadowRemoteViews) ShadowExtractor.extract(tile.remoteViews); + assertThat(shadowRemoteViews.overrideViewId).isNull(); + assertThat(shadowRemoteViews.overrideText).isNull(); + } + public static ResolveInfo newInfo(boolean systemApp, String category) { return newInfo(systemApp, category, null); } @@ -423,4 +509,17 @@ public class TileUtilsTest { info.activityInfo.metaData.putString(key, value); } } + + @Implements(RemoteViews.class) + public static class TileUtilsShadowRemoteViews { + + private Integer overrideViewId; + private CharSequence overrideText; + + @Implementation + public void setTextViewText(int viewId, CharSequence text) { + overrideViewId = viewId; + overrideText = text; + } + } }