Fix DND crash from SpringboardActivity

Special case Uris need to explicitly add their intents.
This unfortunately duplicates a list of special-cased Slices,
but I have attached a bug with a plan to address this duplicity in Q.

Change-Id: I346915c32543713d33716422018d7c950cce323d
Fixes: 80065409
Test: atest SliceDeepLinkSpringBoardTest
This commit is contained in:
Matthew Fritze
2018-05-24 16:09:05 -07:00
parent 2e0709b3b8
commit a559103b1b
6 changed files with 132 additions and 45 deletions

View File

@@ -100,6 +100,17 @@ public class BluetoothSliceBuilder {
.build();
}
public static Intent getIntent(Context context) {
final String screenTitle = context.getText(R.string.bluetooth_settings_title).toString();
final Uri contentUri = new Uri.Builder().appendPath(
SettingsSlicesContract.KEY_BLUETOOTH).build();
return DatabaseIndexingUtils.buildSearchResultPageIntent(context,
BluetoothDashboardFragment.class.getName(), null /* key */, screenTitle,
MetricsProto.MetricsEvent.SETTINGS_CONNECTED_DEVICE_CATEGORY)
.setClassName(context.getPackageName(), SubSettings.class.getName())
.setData(contentUri);
}
/**
* Update the current Bluetooth status to the boolean value keyed by
* {@link android.app.slice.Slice#EXTRA_TOGGLE_STATE} on {@param intent}.
@@ -122,15 +133,7 @@ public class BluetoothSliceBuilder {
}
private static PendingIntent getPrimaryAction(Context context) {
final String screenTitle = context.getText(R.string.bluetooth_settings_title).toString();
final Uri contentUri = new Uri.Builder().appendPath(
SettingsSlicesContract.KEY_BLUETOOTH).build();
final Intent intent = DatabaseIndexingUtils.buildSearchResultPageIntent(context,
BluetoothDashboardFragment.class.getName(), null /* key */, screenTitle,
MetricsProto.MetricsEvent.SETTINGS_CONNECTED_DEVICE_CATEGORY)
.setClassName(context.getPackageName(), SubSettings.class.getName())
.setData(contentUri);
final Intent intent = getIntent(context);
return PendingIntent.getActivity(context, 0 /* requestCode */,
intent, 0 /* flags */);
}

View File

@@ -79,15 +79,18 @@ public class LocationSliceBuilder {
.build();
}
private static PendingIntent getPrimaryAction(Context context) {
public static Intent getIntent(Context context) {
final String screenTitle = context.getText(R.string.location_settings_title).toString();
final Uri contentUri = new Uri.Builder().appendPath(KEY_LOCATION).build();
final Intent intent = DatabaseIndexingUtils.buildSearchResultPageIntent(context,
return DatabaseIndexingUtils.buildSearchResultPageIntent(context,
LocationSettings.class.getName(), KEY_LOCATION, screenTitle,
MetricsEvent.LOCATION)
.setClassName(context.getPackageName(), SubSettings.class.getName())
.setData(contentUri);
}
private static PendingIntent getPrimaryAction(Context context) {
final Intent intent = getIntent(context);
return PendingIntent.getActivity(context, 0 /* requestCode */,
intent, 0 /* flags */);
}

View File

@@ -123,6 +123,16 @@ public class ZenModeSliceBuilder {
// handle it.
}
public static Intent getIntent(Context context) {
final Uri contentUri = new Uri.Builder().appendPath(ZEN_MODE_KEY).build();
final String screenTitle = context.getText(R.string.zen_mode_settings_title).toString();
return DatabaseIndexingUtils.buildSearchResultPageIntent(context,
ZenModeSettings.class.getName(), ZEN_MODE_KEY, screenTitle,
MetricsEvent.NOTIFICATION_ZEN_MODE)
.setClassName(context.getPackageName(), SubSettings.class.getName())
.setData(contentUri);
}
private static boolean isZenModeEnabled(Context context) {
final NotificationManager manager = context.getSystemService(NotificationManager.class);
final int zenMode = manager.getZenMode();
@@ -139,16 +149,8 @@ public class ZenModeSliceBuilder {
}
private static PendingIntent getPrimaryAction(Context context) {
final String screenTitle = context.getText(R.string.zen_mode_settings_title).toString();
final Uri contentUri = new Uri.Builder().appendPath(ZEN_MODE_KEY).build();
final Intent intent = DatabaseIndexingUtils.buildSearchResultPageIntent(context,
ZenModeSettings.class.getName(), ZEN_MODE_KEY, screenTitle,
MetricsEvent.NOTIFICATION_ZEN_MODE)
.setClassName(context.getPackageName(), SubSettings.class.getName())
.setData(contentUri);
return PendingIntent.getActivity(context, 0 /* requestCode */,
intent, 0 /* flags */);
final Intent intent = getIntent(context);
return PendingIntent.getActivity(context, 0 /* requestCode */, intent, 0 /* flags */);
}
private static PendingIntent getBroadcastIntent(Context context) {

View File

@@ -18,8 +18,16 @@ import android.app.Activity;
import android.content.Intent;
import android.net.Uri;
import android.os.Bundle;
import android.provider.Settings;
import android.util.Log;
import com.android.settings.bluetooth.BluetoothSliceBuilder;
import com.android.settings.location.LocationSliceBuilder;
import com.android.settings.notification.ZenModeSliceBuilder;
import com.android.settings.overlay.FeatureFactory;
import com.android.settings.wifi.WifiSliceBuilder;
import com.android.settings.wifi.calling.WifiCallingSliceHelper;
import java.net.URISyntaxException;
public class SliceDeepLinkSpringBoard extends Activity {
@@ -44,11 +52,26 @@ public class SliceDeepLinkSpringBoard extends Activity {
if (ACTION_VIEW_SLICE.equals(intent.getAction())) {
// This shouldn't matter since the slice is shown instead of the device
// index caring about the launch uri.
Uri slice = Uri.parse(intent.getStringExtra(EXTRA_SLICE));
SlicesDatabaseAccessor slicesDatabaseAccessor = new SlicesDatabaseAccessor(this);
// Sadly have to block here because we don't know where to go.
final SliceData sliceData = slicesDatabaseAccessor.getSliceDataFromUri(slice);
Intent launchIntent = SliceBuilderUtils.getContentIntent(this, sliceData);
final Uri slice = Uri.parse(intent.getStringExtra(EXTRA_SLICE));
final Intent launchIntent;
// TODO (b/80263568) Avoid duplicating this list of Slice Uris.
if (WifiSliceBuilder.WIFI_URI.equals(slice)) {
launchIntent = WifiSliceBuilder.getIntent(this /* context */);
} else if (ZenModeSliceBuilder.ZEN_MODE_URI.equals(slice)) {
launchIntent = ZenModeSliceBuilder.getIntent(this /* context */);
} else if (BluetoothSliceBuilder.BLUETOOTH_URI.equals(slice)) {
launchIntent = BluetoothSliceBuilder.getIntent(this /* context */);
} else if (LocationSliceBuilder.LOCATION_URI.equals(slice)) {
launchIntent = LocationSliceBuilder.getIntent(this /* context */);
} else {
final SlicesDatabaseAccessor slicesDatabaseAccessor =
new SlicesDatabaseAccessor(this /* context */);
// Sadly have to block here because we don't know where to go.
final SliceData sliceData = slicesDatabaseAccessor.getSliceDataFromUri(slice);
launchIntent = SliceBuilderUtils.getContentIntent(this, sliceData);
}
startActivity(launchIntent);
} else {
startActivity(intent);
@@ -57,6 +80,10 @@ public class SliceDeepLinkSpringBoard extends Activity {
} catch (URISyntaxException e) {
Log.e(TAG, "Error decoding uri", e);
finish();
} catch (IllegalStateException e) {
Log.w(TAG, "Couldn't launch Slice intent", e);
startActivity(new Intent(Settings.ACTION_SETTINGS));
finish();
}
}

View File

@@ -121,6 +121,18 @@ public class WifiSliceBuilder {
// handle it.
}
public static Intent getIntent(Context context) {
final String screenTitle = context.getText(R.string.wifi_settings).toString();
final Uri contentUri = new Uri.Builder().appendPath(KEY_WIFI).build();
final Intent intent = DatabaseIndexingUtils.buildSearchResultPageIntent(context,
WifiSettings.class.getName(), KEY_WIFI, screenTitle,
MetricsEvent.DIALOG_WIFI_AP_EDIT)
.setClassName(context.getPackageName(), SubSettings.class.getName())
.setData(contentUri);
return intent;
}
private static boolean isWifiEnabled(Context context) {
final WifiManager wifiManager = context.getSystemService(WifiManager.class);
@@ -159,14 +171,7 @@ public class WifiSliceBuilder {
}
private static PendingIntent getPrimaryAction(Context context) {
final String screenTitle = context.getText(R.string.wifi_settings).toString();
final Uri contentUri = new Uri.Builder().appendPath(KEY_WIFI).build();
final Intent intent = DatabaseIndexingUtils.buildSearchResultPageIntent(context,
WifiSettings.class.getName(), KEY_WIFI, screenTitle,
MetricsEvent.DIALOG_WIFI_AP_EDIT);
intent.setClassName(context.getPackageName(), SubSettings.class.getName());
intent.setData(contentUri);
final Intent intent = getIntent(context);
return PendingIntent.getActivity(context, 0 /* requestCode */,
intent, 0 /* flags */);
}

View File

@@ -21,14 +21,22 @@ import static com.android.settings.search.DeviceIndexFeatureProvider.createDeepL
import android.content.Context;
import android.content.Intent;
import android.net.Uri;
import android.platform.test.annotations.Presubmit;
import android.support.test.InstrumentationRegistry;
import android.support.test.filters.MediumTest;
import android.support.test.runner.AndroidJUnit4;
import com.android.settings.bluetooth.BluetoothSliceBuilder;
import com.android.settings.location.LocationSliceBuilder;
import com.android.settings.notification.ZenModeSliceBuilder;
import com.android.settings.wifi.WifiSliceBuilder;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
@RunWith(AndroidJUnit4.class)
@MediumTest
public class SliceDeepLinkSpringBoardTest {
private Context mContext;
@@ -38,18 +46,57 @@ public class SliceDeepLinkSpringBoardTest {
}
@Test
public void launcheDeepLinkIntent_shouldNotCrash() {
final Uri springBoardIntentUri = createDeepLink(
new Intent(SliceDeepLinkSpringBoard.ACTION_VIEW_SLICE)
.setPackage(mContext.getPackageName())
.putExtra(SliceDeepLinkSpringBoard.EXTRA_SLICE,
"content://com.android.settings.slices/action/test_slice")
.toUri(Intent.URI_ANDROID_APP_SCHEME));
final Intent deepLinkIntent = new Intent(Intent.ACTION_VIEW)
.setData(springBoardIntentUri)
.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
@Presubmit
public void launchesDeepLinkIntent_shouldNotCrash() {
final Intent deepLinkIntent = getSpringboardIntent(
"content://com.android.settings.slices/action/test_slice");
mContext.startActivity(deepLinkIntent);
}
@Test
@Presubmit
public void launchesDeepLinkIntent_wifiSlice_shouldNotCrash() {
final Intent deepLinkIntent = getSpringboardIntent(WifiSliceBuilder.WIFI_URI.toString());
mContext.startActivity(deepLinkIntent);
}
@Test
@Presubmit
public void launchesDeepLinkIntent_bluetoothSlice_shouldNotCrash() {
final Intent deepLinkIntent = getSpringboardIntent(
BluetoothSliceBuilder.BLUETOOTH_URI.toString());
mContext.startActivity(deepLinkIntent);
}
@Test
@Presubmit
public void launchesDeepLinkIntent_dndSlice_shouldNotCrash() {
final Intent deepLinkIntent = getSpringboardIntent(
ZenModeSliceBuilder.ZEN_MODE_URI.toString());
mContext.startActivity(deepLinkIntent);
}
@Test
@Presubmit
public void launchesDeepLinkIntent_locationSlice_shouldNotCrash() {
final Intent deepLinkIntent = getSpringboardIntent(
LocationSliceBuilder.LOCATION_URI.toString());
mContext.startActivity(deepLinkIntent);
}
private Intent getSpringboardIntent(String uriString) {
final Uri uri = createDeepLink(new Intent(SliceDeepLinkSpringBoard.ACTION_VIEW_SLICE)
.setPackage(mContext.getPackageName())
.putExtra(SliceDeepLinkSpringBoard.EXTRA_SLICE, uriString)
.toUri(Intent.URI_ANDROID_APP_SCHEME));
return new Intent(Intent.ACTION_VIEW)
.setData(uri)
.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
}
}