Resolve intent before launching from DashboardFragment.

Once dashboard tile is displayed, the underlying intent can be disabled.
We will eventually hide the item from UI, but there can be a brief
moment before we are able to hide it. So to prevent user click and
launch a non-exist intent, we will try to resolve it first before
launching anything.

Change-Id: Ic8d790bf3c5d4d269eadb757f789a1641928a7b7
Fix: 36036097
Test: make RunSettingsRoboTests
This commit is contained in:
Fan Zhang
2017-04-21 14:40:11 -07:00
parent 9797a39ad7
commit 3c7ca105df
2 changed files with 44 additions and 12 deletions

View File

@@ -20,9 +20,9 @@ import android.app.Activity;
import android.content.ComponentName; import android.content.ComponentName;
import android.content.Context; import android.content.Context;
import android.content.Intent; import android.content.Intent;
import android.content.pm.PackageManager;
import android.os.Bundle; import android.os.Bundle;
import android.provider.Settings; import android.provider.Settings;
import android.support.annotation.VisibleForTesting;
import android.support.v7.preference.Preference; import android.support.v7.preference.Preference;
import android.text.TextUtils; import android.text.TextUtils;
import android.util.Log; import android.util.Log;
@@ -51,22 +51,17 @@ public class DashboardFeatureProviderImpl implements DashboardFeatureProvider {
private static final String DASHBOARD_TILE_PREF_KEY_PREFIX = "dashboard_tile_pref_"; private static final String DASHBOARD_TILE_PREF_KEY_PREFIX = "dashboard_tile_pref_";
private static final String META_DATA_KEY_INTENT_ACTION = "com.android.settings.intent.action"; private static final String META_DATA_KEY_INTENT_ACTION = "com.android.settings.intent.action";
protected final Context mContext; protected final Context mContext;
private final MetricsFeatureProvider mMetricsFeatureProvider; private final MetricsFeatureProvider mMetricsFeatureProvider;
private final CategoryManager mCategoryManager; private final CategoryManager mCategoryManager;
private final PackageManager mPackageManager;
public DashboardFeatureProviderImpl(Context context) { public DashboardFeatureProviderImpl(Context context) {
mContext = context.getApplicationContext(); mContext = context.getApplicationContext();
mCategoryManager = CategoryManager.get(context, getExtraIntentAction()); mCategoryManager = CategoryManager.get(context, getExtraIntentAction());
mMetricsFeatureProvider = FeatureFactory.getFactory(context).getMetricsFeatureProvider(); mMetricsFeatureProvider = FeatureFactory.getFactory(context).getMetricsFeatureProvider();
} mPackageManager = context.getPackageManager();
@VisibleForTesting
DashboardFeatureProviderImpl(Context context, CategoryManager categoryManager) {
mContext = context.getApplicationContext();
mCategoryManager = categoryManager;
mMetricsFeatureProvider = FeatureFactory.getFactory(context).getMetricsFeatureProvider();
} }
@Override @Override
@@ -208,6 +203,10 @@ public class DashboardFeatureProviderImpl implements DashboardFeatureProvider {
private void launchIntentOrSelectProfile(Activity activity, Tile tile, Intent intent, private void launchIntentOrSelectProfile(Activity activity, Tile tile, Intent intent,
int sourceMetricCategory) { int sourceMetricCategory) {
if (!isIntentResolvable(intent)) {
Log.w(TAG, "Cannot resolve intent, skipping. " + intent);
return;
}
ProfileSelectDialog.updateUserHandlesIfNeeded(mContext, tile); ProfileSelectDialog.updateUserHandlesIfNeeded(mContext, tile);
if (tile.userHandle == null) { if (tile.userHandle == null) {
mMetricsFeatureProvider.logDashboardStartIntent(mContext, intent, sourceMetricCategory); mMetricsFeatureProvider.logDashboardStartIntent(mContext, intent, sourceMetricCategory);
@@ -219,4 +218,8 @@ public class DashboardFeatureProviderImpl implements DashboardFeatureProvider {
ProfileSelectDialog.show(activity.getFragmentManager(), tile); ProfileSelectDialog.show(activity.getFragmentManager(), tile);
} }
} }
private boolean isIntentResolvable(Intent intent) {
return mPackageManager.resolveActivity(intent, 0) != null;
}
} }

View File

@@ -50,6 +50,7 @@ import org.robolectric.RuntimeEnvironment;
import org.robolectric.annotation.Config; import org.robolectric.annotation.Config;
import org.robolectric.shadows.ShadowActivity; import org.robolectric.shadows.ShadowActivity;
import org.robolectric.shadows.ShadowApplication; import org.robolectric.shadows.ShadowApplication;
import org.robolectric.util.ReflectionHelpers;
import java.util.ArrayList; import java.util.ArrayList;
@@ -293,9 +294,35 @@ public class DashboardFeatureProviderImplTest {
.isEqualTo(MetricsProto.MetricsEvent.SETTINGS_GESTURES); .isEqualTo(MetricsProto.MetricsEvent.SETTINGS_GESTURES);
} }
@Test
public void clickPreference_withUnresolvableIntent_shouldNotLaunchAnything() {
ReflectionHelpers.setField(
mImpl, "mPackageManager", RuntimeEnvironment.getPackageManager());
Activity activity = Robolectric.buildActivity(Activity.class).get();
final ShadowApplication application = ShadowApplication.getInstance();
final Preference preference = new Preference(application.getApplicationContext());
final Tile tile = new Tile();
tile.key = "key";
tile.intent = new Intent();
tile.intent.setComponent(new ComponentName("pkg", "class"));
tile.metaData = new Bundle();
tile.metaData.putString("com.android.settings.intent.action", "TestAction");
tile.userHandle = null;
mImpl.bindPreferenceToTile(activity, MetricsProto.MetricsEvent.SETTINGS_GESTURES,
preference, tile, "123", Preference.DEFAULT_ORDER);
preference.performClick();
final ShadowActivity.IntentForResult launchIntent =
shadowOf(activity).getNextStartedActivityForResult();
assertThat(launchIntent).isNull();
}
@Test @Test
public void getPreferences_noCategory_shouldReturnNull() { public void getPreferences_noCategory_shouldReturnNull() {
mImpl = new DashboardFeatureProviderImpl(mActivity, mCategoryManager); mImpl = new DashboardFeatureProviderImpl(mActivity);
ReflectionHelpers.setField(mImpl, "mCategoryManager", mCategoryManager);
when(mCategoryManager.getTilesByCategory(mActivity, CategoryKey.CATEGORY_HOMEPAGE)) when(mCategoryManager.getTilesByCategory(mActivity, CategoryKey.CATEGORY_HOMEPAGE))
.thenReturn(null); .thenReturn(null);
@@ -306,7 +333,8 @@ public class DashboardFeatureProviderImplTest {
@Test @Test
public void getPreferences_noTileForCategory_shouldReturnNull() { public void getPreferences_noTileForCategory_shouldReturnNull() {
mImpl = new DashboardFeatureProviderImpl(mActivity, mCategoryManager); mImpl = new DashboardFeatureProviderImpl(mActivity);
ReflectionHelpers.setField(mImpl, "mCategoryManager", mCategoryManager);
when(mCategoryManager.getTilesByCategory(mActivity, CategoryKey.CATEGORY_HOMEPAGE)) when(mCategoryManager.getTilesByCategory(mActivity, CategoryKey.CATEGORY_HOMEPAGE))
.thenReturn(new DashboardCategory()); .thenReturn(new DashboardCategory());
@@ -317,7 +345,8 @@ public class DashboardFeatureProviderImplTest {
@Test @Test
public void getPreferences_hasTileForCategory_shouldReturnPrefList() { public void getPreferences_hasTileForCategory_shouldReturnPrefList() {
mImpl = new DashboardFeatureProviderImpl(mActivity, mCategoryManager); mImpl = new DashboardFeatureProviderImpl(mActivity);
ReflectionHelpers.setField(mImpl, "mCategoryManager", mCategoryManager);
final DashboardCategory category = new DashboardCategory(); final DashboardCategory category = new DashboardCategory();
category.tiles.add(new Tile()); category.tiles.add(new Tile());
when(mCategoryManager when(mCategoryManager