diff --git a/res/raw/gesture_swipe_up.mp4 b/res/raw/gesture_swipe_up.mp4 index f4c8fd16fed..2f652921446 100644 Binary files a/res/raw/gesture_swipe_up.mp4 and b/res/raw/gesture_swipe_up.mp4 differ diff --git a/src/com/android/settings/applications/AppStatePowerBridge.java b/src/com/android/settings/applications/AppStatePowerBridge.java index ce0354412e7..31412a7684b 100644 --- a/src/com/android/settings/applications/AppStatePowerBridge.java +++ b/src/com/android/settings/applications/AppStatePowerBridge.java @@ -15,6 +15,8 @@ */ package com.android.settings.applications; +import android.content.Context; + import com.android.settingslib.applications.ApplicationsState; import com.android.settingslib.applications.ApplicationsState.AppEntry; import com.android.settingslib.applications.ApplicationsState.AppFilter; @@ -28,10 +30,11 @@ import java.util.ArrayList; */ public class AppStatePowerBridge extends AppStateBaseBridge { - private final PowerWhitelistBackend mBackend = PowerWhitelistBackend.getInstance(); + private final PowerWhitelistBackend mBackend; - public AppStatePowerBridge(ApplicationsState appState, Callback callback) { + public AppStatePowerBridge(Context context, ApplicationsState appState, Callback callback) { super(appState, callback); + mBackend = PowerWhitelistBackend.getInstance(context); } @Override @@ -50,11 +53,6 @@ public class AppStatePowerBridge extends AppStateBaseBridge { app.extraInfo = mBackend.isWhitelisted(pkg) ? Boolean.TRUE : Boolean.FALSE; } - public static class HighPowerState { - public boolean isHighPower; - public boolean isSystemHighPower; - } - public static final AppFilter FILTER_POWER_WHITELISTED = new CompoundFilter( ApplicationsState.FILTER_WITHOUT_DISABLED_UNTIL_USED, new AppFilter() { @Override diff --git a/src/com/android/settings/applications/ApplicationFeatureProviderImpl.java b/src/com/android/settings/applications/ApplicationFeatureProviderImpl.java index f59286576e3..3a88337fd2f 100644 --- a/src/com/android/settings/applications/ApplicationFeatureProviderImpl.java +++ b/src/com/android/settings/applications/ApplicationFeatureProviderImpl.java @@ -17,6 +17,7 @@ package com.android.settings.applications; import android.app.admin.DevicePolicyManager; +import android.content.ComponentName; import android.content.Context; import android.content.Intent; import android.content.pm.ComponentInfo; @@ -26,8 +27,11 @@ import android.content.pm.ResolveInfo; import android.content.pm.UserInfo; import android.os.RemoteException; import android.os.UserManager; +import android.telecom.DefaultDialerManager; +import android.text.TextUtils; import android.util.ArraySet; +import com.android.internal.telephony.SmsApplication; import com.android.settingslib.wrapper.PackageManagerWrapper; import java.util.ArrayList; @@ -124,7 +128,18 @@ public class ApplicationFeatureProviderImpl implements ApplicationFeatureProvide @Override public Set getKeepEnabledPackages() { - return new ArraySet<>(); + // Find current default phone/sms app. We should keep them enabled. + final Set keepEnabledPackages = new ArraySet<>(); + final String defaultDialer = DefaultDialerManager.getDefaultDialerApplication(mContext); + if (!TextUtils.isEmpty(defaultDialer)) { + keepEnabledPackages.add(defaultDialer); + } + final ComponentName defaultSms = SmsApplication.getDefaultSmsApplication( + mContext, true /* updateIfNeeded */); + if (defaultSms != null) { + keepEnabledPackages.add(defaultSms.getPackageName()); + } + return keepEnabledPackages; } private static class CurrentUserAndManagedProfilePolicyInstalledAppCounter diff --git a/src/com/android/settings/applications/manageapplications/ManageApplications.java b/src/com/android/settings/applications/manageapplications/ManageApplications.java index a00ea8e2e68..51b24e1913b 100644 --- a/src/com/android/settings/applications/manageapplications/ManageApplications.java +++ b/src/com/android/settings/applications/manageapplications/ManageApplications.java @@ -884,7 +884,7 @@ public class ManageApplications extends InstrumentedFragment } else if (mManageApplications.mListType == LIST_TYPE_USAGE_ACCESS) { mExtraInfoBridge = new AppStateUsageBridge(mContext, mState, this); } else if (mManageApplications.mListType == LIST_TYPE_HIGH_POWER) { - mExtraInfoBridge = new AppStatePowerBridge(mState, this); + mExtraInfoBridge = new AppStatePowerBridge(mContext, mState, this); } else if (mManageApplications.mListType == LIST_TYPE_OVERLAY) { mExtraInfoBridge = new AppStateOverlayBridge(mContext, mState, this); } else if (mManageApplications.mListType == LIST_TYPE_WRITE_SETTINGS) { @@ -1276,7 +1276,8 @@ public class ManageApplications extends InstrumentedFragment return true; } ApplicationsState.AppEntry entry = mEntries.get(position); - return !PowerWhitelistBackend.getInstance().isSysWhitelisted(entry.info.packageName); + return !PowerWhitelistBackend.getInstance(mContext) + .isSysWhitelisted(entry.info.packageName); } @Override diff --git a/src/com/android/settings/bluetooth/BluetoothSliceBuilder.java b/src/com/android/settings/bluetooth/BluetoothSliceBuilder.java index 9a9f45588e7..f01efadb572 100644 --- a/src/com/android/settings/bluetooth/BluetoothSliceBuilder.java +++ b/src/com/android/settings/bluetooth/BluetoothSliceBuilder.java @@ -98,6 +98,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}. @@ -119,15 +130,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 */); } diff --git a/src/com/android/settings/connecteddevice/AdvancedConnectedDeviceDashboardFragment.java b/src/com/android/settings/connecteddevice/AdvancedConnectedDeviceDashboardFragment.java index 9795e9faacb..58369459540 100644 --- a/src/com/android/settings/connecteddevice/AdvancedConnectedDeviceDashboardFragment.java +++ b/src/com/android/settings/connecteddevice/AdvancedConnectedDeviceDashboardFragment.java @@ -40,6 +40,8 @@ public class AdvancedConnectedDeviceDashboardFragment extends DashboardFragment private static final String TAG = "AdvancedConnectedDeviceFrag"; + static final String KEY_BLUETOOTH = "bluetooth_settings"; + @Override public int getMetricsCategory() { return MetricsProto.MetricsEvent.CONNECTION_DEVICE_ADVANCED; @@ -104,6 +106,9 @@ public class AdvancedConnectedDeviceDashboardFragment extends DashboardFragment keys.add(AndroidBeamPreferenceController.KEY_ANDROID_BEAM_SETTINGS); } + // Parent duplicate + keys.add(KEY_BLUETOOTH); + return keys; } diff --git a/src/com/android/settings/connecteddevice/BluetoothDashboardFragment.java b/src/com/android/settings/connecteddevice/BluetoothDashboardFragment.java index 3b24271664c..565bd48c970 100644 --- a/src/com/android/settings/connecteddevice/BluetoothDashboardFragment.java +++ b/src/com/android/settings/connecteddevice/BluetoothDashboardFragment.java @@ -109,17 +109,10 @@ public class BluetoothDashboardFragment extends DashboardFragment { final List result = new ArrayList<>(); // Add the activity title - SearchIndexableRaw data = new SearchIndexableRaw(context); + final SearchIndexableRaw data = new SearchIndexableRaw(context); data.title = context.getString(R.string.bluetooth_settings_title); - data.screenTitle = context.getString(R.string.settings_label); + data.screenTitle = context.getString(R.string.bluetooth_settings_title); data.keywords = context.getString(R.string.keywords_bluetooth_settings); - data.intentTargetPackage = context.getPackageName(); - data.intentTargetClass = BluetoothDashboardFragment.class.getName(); - data.intentAction = new SubSettingLauncher(context) - .setDestination(ScanningSettings.class.getName()) - .setSourceMetricsCategory(MetricsProto.MetricsEvent.BLUETOOTH_FRAGMENT) - .toIntent() - .getAction(); data.key = KEY_BLUETOOTH_SCREEN; result.add(data); diff --git a/src/com/android/settings/fuelgauge/AppButtonsPreferenceController.java b/src/com/android/settings/fuelgauge/AppButtonsPreferenceController.java index 8c4b4d88b2c..5c773736f2f 100644 --- a/src/com/android/settings/fuelgauge/AppButtonsPreferenceController.java +++ b/src/com/android/settings/fuelgauge/AppButtonsPreferenceController.java @@ -48,6 +48,7 @@ import com.android.settings.DeviceAdminAdd; import com.android.settings.R; import com.android.settings.SettingsActivity; import com.android.settings.Utils; +import com.android.settings.applications.ApplicationFeatureProvider; import com.android.settings.core.PreferenceControllerMixin; import com.android.settings.overlay.FeatureFactory; import com.android.settings.widget.ActionButtonPreference; @@ -73,7 +74,7 @@ import java.util.List; * An easy way to handle them is to delegate them to {@link #handleDialogClick(int)} and * {@link #handleActivityResult(int, int, Intent)} in this controller. */ -//TODO(b/35810915): Make AppInfoDashboardFragment use this controller +//TODO(80312809): Merge this class into {@link AppActionButtonPreferenceController} public class AppButtonsPreferenceController extends AbstractPreferenceController implements PreferenceControllerMixin, LifecycleObserver, OnResume, OnDestroy, ApplicationsState.Callbacks { @@ -100,17 +101,18 @@ public class AppButtonsPreferenceController extends AbstractPreferenceController private final int mRequestUninstall; private final int mRequestRemoveDeviceAdmin; + private final DevicePolicyManager mDpm; + private final UserManager mUserManager; + private final PackageManager mPm; + private final SettingsActivity mActivity; + private final Fragment mFragment; + private final MetricsFeatureProvider mMetricsFeatureProvider; + private final ApplicationFeatureProvider mApplicationFeatureProvider; + private final int mUserId; private ApplicationsState.Session mSession; - private DevicePolicyManager mDpm; - private UserManager mUserManager; - private PackageManager mPm; - private SettingsActivity mActivity; - private Fragment mFragment; private RestrictedLockUtils.EnforcedAdmin mAppsControlDisallowedAdmin; - private MetricsFeatureProvider mMetricsFeatureProvider; - private int mUserId; private boolean mUpdatedSysApp = false; private boolean mListeningToPackageRemove = false; private boolean mFinishing = false; @@ -127,8 +129,9 @@ public class AppButtonsPreferenceController extends AbstractPreferenceController "Fragment should implement AppButtonsDialogListener"); } - mMetricsFeatureProvider = FeatureFactory.getFactory(activity).getMetricsFeatureProvider(); - + final FeatureFactory factory = FeatureFactory.getFactory(activity); + mMetricsFeatureProvider = factory.getMetricsFeatureProvider(); + mApplicationFeatureProvider = factory.getApplicationFeatureProvider(activity); mState = state; mDpm = dpm; mUserManager = userManager; @@ -538,11 +541,11 @@ public class AppButtonsPreferenceController extends AbstractPreferenceController // Disable button for core system applications. mButtonsPref.setButton1Text(R.string.disable_text) .setButton1Positive(false); - } else if (mAppEntry.info.enabled && !isDisabledUntilUsed()) { mButtonsPref.setButton1Text(R.string.disable_text) .setButton1Positive(false); - disableable = true; + disableable = !mApplicationFeatureProvider.getKeepEnabledPackages() + .contains(mAppEntry.info.packageName); } else { mButtonsPref.setButton1Text(R.string.enable_text) .setButton1Positive(true); diff --git a/src/com/android/settings/fuelgauge/BackgroundActivityPreferenceController.java b/src/com/android/settings/fuelgauge/BackgroundActivityPreferenceController.java index 69b5e9e3139..092f6270a5d 100644 --- a/src/com/android/settings/fuelgauge/BackgroundActivityPreferenceController.java +++ b/src/com/android/settings/fuelgauge/BackgroundActivityPreferenceController.java @@ -56,7 +56,7 @@ public class BackgroundActivityPreferenceController extends AbstractPreferenceCo public BackgroundActivityPreferenceController(Context context, InstrumentedPreferenceFragment fragment, int uid, String packageName) { - this(context, fragment, uid, packageName, PowerWhitelistBackend.getInstance()); + this(context, fragment, uid, packageName, PowerWhitelistBackend.getInstance(context)); } @VisibleForTesting diff --git a/src/com/android/settings/fuelgauge/BatteryOptimizationPreferenceController.java b/src/com/android/settings/fuelgauge/BatteryOptimizationPreferenceController.java index ab3ce8da0a3..d526f4b5bcf 100644 --- a/src/com/android/settings/fuelgauge/BatteryOptimizationPreferenceController.java +++ b/src/com/android/settings/fuelgauge/BatteryOptimizationPreferenceController.java @@ -48,7 +48,7 @@ public class BatteryOptimizationPreferenceController extends AbstractPreferenceC mFragment = fragment; mSettingsActivity = settingsActivity; mPackageName = packageName; - mBackend = PowerWhitelistBackend.getInstance(); + mBackend = PowerWhitelistBackend.getInstance(mSettingsActivity); } @VisibleForTesting diff --git a/src/com/android/settings/fuelgauge/HighPowerDetail.java b/src/com/android/settings/fuelgauge/HighPowerDetail.java index 4f707008953..7dfa0befa73 100644 --- a/src/com/android/settings/fuelgauge/HighPowerDetail.java +++ b/src/com/android/settings/fuelgauge/HighPowerDetail.java @@ -67,12 +67,13 @@ public class HighPowerDetail extends InstrumentedDialogFragment implements OnCli @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); - mBatteryUtils = BatteryUtils.getInstance(getContext()); - mBackend = PowerWhitelistBackend.getInstance(); + final Context context = getContext(); + mBatteryUtils = BatteryUtils.getInstance(context); + mBackend = PowerWhitelistBackend.getInstance(context); mPackageName = getArguments().getString(AppInfoBase.ARG_PACKAGE_NAME); mPackageUid = getArguments().getInt(AppInfoBase.ARG_PACKAGE_UID); - PackageManager pm = getContext().getPackageManager(); + final PackageManager pm = context.getPackageManager(); try { mLabel = pm.getApplicationInfo(mPackageName, 0).loadLabel(pm); } catch (NameNotFoundException e) { @@ -171,10 +172,10 @@ public class HighPowerDetail extends InstrumentedDialogFragment implements OnCli } public static CharSequence getSummary(Context context, String pkg) { - PowerWhitelistBackend powerWhitelist = PowerWhitelistBackend.getInstance(); + PowerWhitelistBackend powerWhitelist = PowerWhitelistBackend.getInstance(context); return context.getString(powerWhitelist.isSysWhitelisted(pkg) ? R.string.high_power_system : powerWhitelist.isWhitelisted(pkg) ? R.string.high_power_on - : R.string.high_power_off); + : R.string.high_power_off); } public static void show(Fragment caller, int uid, String packageName, int requestCode) { diff --git a/src/com/android/settings/fuelgauge/batterytip/AnomalyDetectionJobService.java b/src/com/android/settings/fuelgauge/batterytip/AnomalyDetectionJobService.java index 84ef8641bdd..55081cd81f9 100644 --- a/src/com/android/settings/fuelgauge/batterytip/AnomalyDetectionJobService.java +++ b/src/com/android/settings/fuelgauge/batterytip/AnomalyDetectionJobService.java @@ -30,12 +30,8 @@ import android.content.ComponentName; import android.content.ContentResolver; import android.content.Context; import android.content.Intent; -import android.content.pm.ApplicationInfo; -import android.content.pm.PackageManager; import android.os.Bundle; -import android.os.Process; import android.os.StatsDimensionsValue; -import android.os.UserHandle; import android.os.UserManager; import android.provider.Settings; import android.support.annotation.GuardedBy; @@ -44,7 +40,6 @@ import android.util.Log; import android.util.Pair; import com.android.internal.logging.nano.MetricsProto; -import com.android.internal.os.BatteryStatsHelper; import com.android.internal.util.ArrayUtils; import com.android.settings.R; import com.android.settings.fuelgauge.BatteryUtils; @@ -101,7 +96,8 @@ public class AnomalyDetectionJobService extends JobService { final BatteryUtils batteryUtils = BatteryUtils.getInstance(this); final ContentResolver contentResolver = getContentResolver(); final UserManager userManager = getSystemService(UserManager.class); - final PowerWhitelistBackend powerWhitelistBackend = PowerWhitelistBackend.getInstance(); + final PowerWhitelistBackend powerWhitelistBackend = + PowerWhitelistBackend.getInstance(context); final PowerUsageFeatureProvider powerUsageFeatureProvider = FeatureFactory .getFactory(this).getPowerUsageFeatureProvider(this); final MetricsFeatureProvider metricsFeatureProvider = FeatureFactory diff --git a/src/com/android/settings/location/LocationSliceBuilder.java b/src/com/android/settings/location/LocationSliceBuilder.java index e69ccfba54c..4cf861f55a7 100644 --- a/src/com/android/settings/location/LocationSliceBuilder.java +++ b/src/com/android/settings/location/LocationSliceBuilder.java @@ -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 */); } diff --git a/src/com/android/settings/notification/ZenModeSliceBuilder.java b/src/com/android/settings/notification/ZenModeSliceBuilder.java index aedd0b3e4c3..16591ce33c7 100644 --- a/src/com/android/settings/notification/ZenModeSliceBuilder.java +++ b/src/com/android/settings/notification/ZenModeSliceBuilder.java @@ -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) { diff --git a/src/com/android/settings/search/DeviceIndexFeatureProvider.java b/src/com/android/settings/search/DeviceIndexFeatureProvider.java index 1c25399c8fa..c4d3abfcaa8 100644 --- a/src/com/android/settings/search/DeviceIndexFeatureProvider.java +++ b/src/com/android/settings/search/DeviceIndexFeatureProvider.java @@ -24,6 +24,7 @@ import android.content.Context; import android.net.Uri; import android.os.Build; import android.provider.Settings; +import android.text.TextUtils; import android.util.Log; import com.android.settings.R; @@ -32,7 +33,6 @@ import com.android.settings.slices.SettingsSliceProvider; import java.util.List; import java.util.Locale; -import java.util.Objects; public interface DeviceIndexFeatureProvider { @@ -96,10 +96,11 @@ public interface DeviceIndexFeatureProvider { } static boolean skipIndex(Context context) { - final boolean isSameVersion = Objects.equals( + final boolean isSameVersion = TextUtils.equals( Settings.Secure.getString(context.getContentResolver(), INDEX_VERSION), VERSION); - final boolean isSameLanguage = Objects.equals( - Settings.Secure.getString(context.getContentResolver(), INDEX_LANGUAGE), LANGUAGE); + final boolean isSameLanguage = TextUtils.equals( + Settings.Secure.getString(context.getContentResolver(), INDEX_LANGUAGE), + LANGUAGE.toString()); return isSameLanguage && isSameVersion; } diff --git a/src/com/android/settings/slices/SliceDeepLinkSpringBoard.java b/src/com/android/settings/slices/SliceDeepLinkSpringBoard.java index 7f1a0f35cae..4f8ed96b9a5 100644 --- a/src/com/android/settings/slices/SliceDeepLinkSpringBoard.java +++ b/src/com/android/settings/slices/SliceDeepLinkSpringBoard.java @@ -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(); } } diff --git a/src/com/android/settings/wifi/WifiSliceBuilder.java b/src/com/android/settings/wifi/WifiSliceBuilder.java index 7df7f19ad78..21a9455ab2c 100644 --- a/src/com/android/settings/wifi/WifiSliceBuilder.java +++ b/src/com/android/settings/wifi/WifiSliceBuilder.java @@ -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 */); } diff --git a/tests/robotests/src/com/android/settings/applications/ApplicationFeatureProviderImplTest.java b/tests/robotests/src/com/android/settings/applications/ApplicationFeatureProviderImplTest.java index a457ba24dab..cd41c8612aa 100644 --- a/tests/robotests/src/com/android/settings/applications/ApplicationFeatureProviderImplTest.java +++ b/tests/robotests/src/com/android/settings/applications/ApplicationFeatureProviderImplTest.java @@ -20,6 +20,7 @@ import static com.google.common.truth.Truth.assertThat; import static org.mockito.Mockito.when; import android.app.admin.DevicePolicyManager; +import android.content.ComponentName; import android.content.Context; import android.content.Intent; import android.content.pm.ActivityInfo; @@ -34,6 +35,8 @@ import android.os.UserManager; import com.android.settings.testutils.ApplicationTestUtils; import com.android.settings.testutils.SettingsRobolectricTestRunner; +import com.android.settings.testutils.shadow.ShadowDefaultDialerManager; +import com.android.settings.testutils.shadow.ShadowSmsApplication; import com.android.settingslib.wrapper.PackageManagerWrapper; import org.junit.Before; @@ -41,11 +44,15 @@ import org.junit.Test; import org.junit.runner.RunWith; import org.mockito.Mock; import org.mockito.MockitoAnnotations; +import org.robolectric.RuntimeEnvironment; +import org.robolectric.annotation.Config; import org.robolectric.shadows.ShadowApplication; +import org.robolectric.util.ReflectionHelpers; import java.util.ArrayList; import java.util.Arrays; import java.util.List; +import java.util.Set; /** * Tests for {@link ApplicationFeatureProviderImpl}. @@ -247,8 +254,18 @@ public final class ApplicationFeatureProviderImplTest { } @Test - public void getKeepEnabledPackages_shouldContainNothing() { - assertThat(mProvider.getKeepEnabledPackages()).isEmpty(); + @Config(shadows = {ShadowSmsApplication.class, ShadowDefaultDialerManager.class}) + public void getKeepEnabledPackages_shouldContainDefaultPhoneAndSms() { + final String testDialer = "com.android.test.defaultdialer"; + final String testSms = "com.android.test.defaultsms"; + ShadowSmsApplication.setDefaultSmsApplication(new ComponentName(testSms, "receiver")); + ShadowDefaultDialerManager.setDefaultDialerApplication(testDialer); + ReflectionHelpers.setField(mProvider, "mContext", RuntimeEnvironment.application); + + final Set keepEnabledPackages = mProvider.getKeepEnabledPackages(); + + final List expectedPackages = Arrays.asList(testDialer, testSms); + assertThat(keepEnabledPackages).containsExactlyElementsIn(expectedPackages); } private void setUpUsersAndInstalledApps() { diff --git a/tests/robotests/src/com/android/settings/connecteddevice/AdvancedConnectedDeviceDashboardFragmentTest.java b/tests/robotests/src/com/android/settings/connecteddevice/AdvancedConnectedDeviceDashboardFragmentTest.java index 2e2dd9d7d3e..1b78f129d42 100644 --- a/tests/robotests/src/com/android/settings/connecteddevice/AdvancedConnectedDeviceDashboardFragmentTest.java +++ b/tests/robotests/src/com/android/settings/connecteddevice/AdvancedConnectedDeviceDashboardFragmentTest.java @@ -67,4 +67,13 @@ public class AdvancedConnectedDeviceDashboardFragmentTest { public void testGetCategoryKey_returnCategoryDevice() { assertThat(mFragment.getCategoryKey()).isEqualTo(CategoryKey.CATEGORY_DEVICE); } + + @Test + public void testSearchIndexProvider_correctNonIndexables() { + final List niks = + AdvancedConnectedDeviceDashboardFragment.SEARCH_INDEX_DATA_PROVIDER + .getNonIndexableKeys(RuntimeEnvironment.application); + + assertThat(niks).contains(AdvancedConnectedDeviceDashboardFragment.KEY_BLUETOOTH); + } } \ No newline at end of file diff --git a/tests/robotests/src/com/android/settings/connecteddevice/BluetoothDashboardFragmentTest.java b/tests/robotests/src/com/android/settings/connecteddevice/BluetoothDashboardFragmentTest.java new file mode 100644 index 00000000000..44b7b8fb79e --- /dev/null +++ b/tests/robotests/src/com/android/settings/connecteddevice/BluetoothDashboardFragmentTest.java @@ -0,0 +1,60 @@ +/* + * Copyright (C) 2018 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License + */ + +package com.android.settings.connecteddevice; + +import static com.google.common.truth.Truth.assertThat; + +import android.content.Context; +import android.text.TextUtils; + +import com.android.settings.R; +import com.android.settings.search.SearchIndexableRaw; +import com.android.settings.testutils.SettingsRobolectricTestRunner; + +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.robolectric.RuntimeEnvironment; + +import java.util.List; +import java.util.stream.Collectors; + +@RunWith(SettingsRobolectricTestRunner.class) +public class BluetoothDashboardFragmentTest { + + private Context mContext; + + @Before + public void setUp() { + mContext = RuntimeEnvironment.application; + } + + @Test + public void rawData_includesFragmentResult() { + final List rawList = + BluetoothDashboardFragment.SEARCH_INDEX_DATA_PROVIDER.getRawDataToIndex(mContext, + true /* enabled */); + + final SearchIndexableRaw fragmentResult = rawList.stream().filter( + raw -> TextUtils.equals(raw.title, + mContext.getString(R.string.bluetooth_settings))).findFirst().get(); + + + assertThat(fragmentResult).isNotNull(); + } + +} diff --git a/tests/robotests/src/com/android/settings/fuelgauge/BatteryOptimizationPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/fuelgauge/BatteryOptimizationPreferenceControllerTest.java index b454416a443..dec9c6a3c96 100644 --- a/tests/robotests/src/com/android/settings/fuelgauge/BatteryOptimizationPreferenceControllerTest.java +++ b/tests/robotests/src/com/android/settings/fuelgauge/BatteryOptimizationPreferenceControllerTest.java @@ -115,6 +115,10 @@ public class BatteryOptimizationPreferenceControllerTest { */ public static class TestPowerWhitelistBackend extends PowerWhitelistBackend { + public TestPowerWhitelistBackend(Context context) { + super(context); + } + @Override public void refreshList() { // Do nothing so we could mock it without error diff --git a/tests/robotests/src/com/android/settings/search/DeviceIndexFeatureProviderTest.java b/tests/robotests/src/com/android/settings/search/DeviceIndexFeatureProviderTest.java index a900db033bc..ebba3f310ce 100644 --- a/tests/robotests/src/com/android/settings/search/DeviceIndexFeatureProviderTest.java +++ b/tests/robotests/src/com/android/settings/search/DeviceIndexFeatureProviderTest.java @@ -23,7 +23,6 @@ import static org.mockito.Mockito.when; import android.app.Activity; import android.app.job.JobScheduler; -import android.os.Build; import android.provider.Settings; import com.android.settings.testutils.FakeFeatureFactory; @@ -113,15 +112,19 @@ public class DeviceIndexFeatureProviderTest { @Test public void updateIndex_enabled_provisioned_sameBuild_sameLang_shouldNotIndex() { + // Enabled + when(mProvider.isIndexingEnabled()).thenReturn(true); + // Provisioned Settings.Global.putInt(mActivity.getContentResolver(), Settings.Global.DEVICE_PROVISIONED, 1); + // Same build and same language DeviceIndexFeatureProvider.setIndexState(mActivity); - JobScheduler jobScheduler = mock(JobScheduler.class); - when(mProvider.isIndexingEnabled()).thenReturn(true); + + final JobScheduler jobScheduler = mock(JobScheduler.class); when(mActivity.getSystemService(JobScheduler.class)).thenReturn(jobScheduler); mProvider.updateIndex(mActivity, false); - verify(mProvider, never()).index(any(), any(), any(), any(), any()); + verify(jobScheduler, never()).schedule(any()); } } diff --git a/tests/robotests/src/com/android/settings/testutils/shadow/ShadowDefaultDialerManager.java b/tests/robotests/src/com/android/settings/testutils/shadow/ShadowDefaultDialerManager.java new file mode 100644 index 00000000000..ec4d788b9c1 --- /dev/null +++ b/tests/robotests/src/com/android/settings/testutils/shadow/ShadowDefaultDialerManager.java @@ -0,0 +1,44 @@ +/* + * Copyright (C) 2018 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.settings.testutils.shadow; + +import android.content.Context; +import android.telecom.DefaultDialerManager; + +import org.robolectric.annotation.Implementation; +import org.robolectric.annotation.Implements; +import org.robolectric.annotation.Resetter; + +@Implements(DefaultDialerManager.class) +public class ShadowDefaultDialerManager { + + private static String sDefaultDailer; + + @Resetter + public void reset() { + sDefaultDailer = null; + } + + @Implementation + public static String getDefaultDialerApplication(Context context) { + return sDefaultDailer; + } + + public static void setDefaultDialerApplication(String dialer) { + sDefaultDailer = dialer; + } +} diff --git a/tests/robotests/src/com/android/settings/testutils/shadow/ShadowSmsApplication.java b/tests/robotests/src/com/android/settings/testutils/shadow/ShadowSmsApplication.java new file mode 100644 index 00000000000..8e0c013f674 --- /dev/null +++ b/tests/robotests/src/com/android/settings/testutils/shadow/ShadowSmsApplication.java @@ -0,0 +1,46 @@ +/* + * Copyright (C) 2018 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.settings.testutils.shadow; + +import android.content.ComponentName; +import android.content.Context; + +import com.android.internal.telephony.SmsApplication; + +import org.robolectric.annotation.Implementation; +import org.robolectric.annotation.Implements; +import org.robolectric.annotation.Resetter; + +@Implements(SmsApplication.class) +public class ShadowSmsApplication { + + private static ComponentName sDefaultSmsApplication; + + @Resetter + public void reset() { + sDefaultSmsApplication = null; + } + + @Implementation + public static ComponentName getDefaultSmsApplication(Context context, boolean updateIfNeeded) { + return sDefaultSmsApplication; + } + + public static void setDefaultSmsApplication(ComponentName cn) { + sDefaultSmsApplication = cn; + } +} diff --git a/tests/unit/src/com/android/settings/slices/SliceDeepLinkSpringBoardTest.java b/tests/unit/src/com/android/settings/slices/SliceDeepLinkSpringBoardTest.java index e7c5d6e30fe..91057b83d4d 100644 --- a/tests/unit/src/com/android/settings/slices/SliceDeepLinkSpringBoardTest.java +++ b/tests/unit/src/com/android/settings/slices/SliceDeepLinkSpringBoardTest.java @@ -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); + } }