From 21539cd2bee06ab932c1d3d2e3d31d2b2f070a75 Mon Sep 17 00:00:00 2001 From: Yuri Lin Date: Tue, 11 Jun 2024 18:36:50 -0400 Subject: [PATCH] Link to app-provided configuration intent for app-owned rules. If there is no valid intent, the automatic trigger preference is disabled. Flag: android.app.modes_ui Bug: 341961712 Test: manual (for Bedtime & Driving modes), ZenModeSetTriggerLinkPreferenceControllerTest Change-Id: I673792effb3cfdcaaa7cf85adfb55a93b44dcc86 --- res/values/strings.xml | 3 + .../AbstractZenModePreferenceController.java | 11 ++ .../notification/modes/ZenModeFragment.java | 4 +- ...odeSetTriggerLinkPreferenceController.java | 159 +++++++++++++++--- .../modes/ZenModesListFragment.java | 2 +- .../settings/utils/ZenServiceListing.java | 28 ++- .../notification/modes/TestModeBuilder.java | 13 ++ ...etTriggerLinkPreferenceControllerTest.java | 131 ++++++++++++++- 8 files changed, 316 insertions(+), 35 deletions(-) diff --git a/res/values/strings.xml b/res/values/strings.xml index a4908560b45..d60e3573446 100644 --- a/res/values/strings.xml +++ b/res/values/strings.xml @@ -8076,6 +8076,9 @@ %1$d hr, %2$d min + + Turn on automatically + Schedule diff --git a/src/com/android/settings/notification/modes/AbstractZenModePreferenceController.java b/src/com/android/settings/notification/modes/AbstractZenModePreferenceController.java index 9f819d1b6e4..a4bd2aac5f6 100644 --- a/src/com/android/settings/notification/modes/AbstractZenModePreferenceController.java +++ b/src/com/android/settings/notification/modes/AbstractZenModePreferenceController.java @@ -24,6 +24,7 @@ import android.util.Log; import androidx.annotation.NonNull; import androidx.annotation.Nullable; import androidx.preference.Preference; +import androidx.preference.PreferenceScreen; import com.android.settingslib.core.AbstractPreferenceController; import com.android.settingslib.notification.modes.ZenMode; @@ -91,6 +92,16 @@ abstract class AbstractZenModePreferenceController extends AbstractPreferenceCon updateState(preference); } + @Override + public void displayPreference(PreferenceScreen screen) { + super.displayPreference(screen); + if (mZenMode != null) { + displayPreference(screen, mZenMode); + } + } + + public void displayPreference(PreferenceScreen screen, @NonNull ZenMode zenMode) {} + @Override public final void updateState(Preference preference) { super.updateState(preference); diff --git a/src/com/android/settings/notification/modes/ZenModeFragment.java b/src/com/android/settings/notification/modes/ZenModeFragment.java index 67815b10088..3a64fb2f1a0 100644 --- a/src/com/android/settings/notification/modes/ZenModeFragment.java +++ b/src/com/android/settings/notification/modes/ZenModeFragment.java @@ -35,6 +35,7 @@ import java.util.ArrayList; import java.util.List; public class ZenModeFragment extends ZenModeFragmentBase { + // for mode deletion menu private static final int DELETE_MODE = 1; @@ -61,7 +62,8 @@ public class ZenModeFragment extends ZenModeFragmentBase { prefControllers.add(new ZenModeDisplayLinkPreferenceController( context, "mode_display_settings", mBackend, mHelperBackend)); prefControllers.add(new ZenModeSetTriggerLinkPreferenceController(context, - "zen_automatic_trigger_category", this, mBackend)); + "zen_automatic_trigger_category", this, mBackend, + context.getPackageManager())); prefControllers.add(new InterruptionFilterPreferenceController( context, "allow_filtering", mBackend)); prefControllers.add(new ManualDurationPreferenceController( diff --git a/src/com/android/settings/notification/modes/ZenModeSetTriggerLinkPreferenceController.java b/src/com/android/settings/notification/modes/ZenModeSetTriggerLinkPreferenceController.java index 1c96fee7d0b..7328d918941 100644 --- a/src/com/android/settings/notification/modes/ZenModeSetTriggerLinkPreferenceController.java +++ b/src/com/android/settings/notification/modes/ZenModeSetTriggerLinkPreferenceController.java @@ -18,34 +18,62 @@ package com.android.settings.notification.modes; import static android.app.AutomaticZenRule.TYPE_SCHEDULE_CALENDAR; import static android.app.AutomaticZenRule.TYPE_SCHEDULE_TIME; +import static android.app.NotificationManager.EXTRA_AUTOMATIC_RULE_ID; +import android.content.ComponentName; import android.content.Context; +import android.content.Intent; +import android.content.pm.ActivityInfo; +import android.content.pm.ComponentInfo; +import android.content.pm.PackageManager; +import android.content.pm.ResolveInfo; +import android.service.notification.ConditionProviderService; +import android.util.Log; import androidx.annotation.NonNull; +import androidx.annotation.Nullable; import androidx.annotation.VisibleForTesting; import androidx.preference.Preference; import androidx.preference.PreferenceCategory; +import androidx.preference.PreferenceScreen; import com.android.settings.R; import com.android.settings.dashboard.DashboardFragment; +import com.android.settings.utils.ManagedServiceSettings; +import com.android.settings.utils.ZenServiceListing; import com.android.settingslib.PrimarySwitchPreference; import com.android.settingslib.notification.modes.ZenMode; import com.android.settingslib.notification.modes.ZenModesBackend; +import java.util.List; + /** * Preference controller for the link to an individual mode's configuration page. */ class ZenModeSetTriggerLinkPreferenceController extends AbstractZenModePreferenceController { + private static final String TAG = "ZenModeSetTriggerLink"; + @VisibleForTesting protected static final String AUTOMATIC_TRIGGER_PREF_KEY = "zen_automatic_trigger_settings"; + private static final ManagedServiceSettings.Config CONFIG = + ZenModesListFragment.getConditionProviderConfig(); + + private ZenServiceListing mServiceListing; + private final PackageManager mPm; private final DashboardFragment mFragment; ZenModeSetTriggerLinkPreferenceController(Context context, String key, - DashboardFragment fragment, - ZenModesBackend backend) { + DashboardFragment fragment, ZenModesBackend backend, + PackageManager packageManager) { super(context, key, backend); mFragment = fragment; + mPm = packageManager; + } + + @VisibleForTesting + protected void setServiceListing(ZenServiceListing serviceListing) { + mServiceListing = serviceListing; } @Override @@ -53,6 +81,15 @@ class ZenModeSetTriggerLinkPreferenceController extends AbstractZenModePreferenc return !zenMode.isManualDnd(); } + @Override + public void displayPreference(PreferenceScreen screen, @NonNull ZenMode zenMode) { + if (mServiceListing == null) { + mServiceListing = new ZenServiceListing( + mContext, CONFIG, zenMode.getRule().getPackageName()); + } + mServiceListing.reloadApprovedServices(); + } + @Override public void updateState(Preference preference, @NonNull ZenMode zenMode) { // This controller is expected to govern a preference category so that it controls the @@ -70,29 +107,39 @@ class ZenModeSetTriggerLinkPreferenceController extends AbstractZenModePreferenc switchPref.setOnPreferenceClickListener(null); switchPref.setIntent(null); - if (zenMode.isSystemOwned() && zenMode.getType() == TYPE_SCHEDULE_TIME) { - switchPref.setTitle(R.string.zen_mode_set_schedule_link); - // TODO: b/332937635 - set correct metrics category - switchPref.setIntent(ZenSubSettingLauncher.forModeFragment(mContext, - ZenModeSetScheduleFragment.class, zenMode.getId(), 0).toIntent()); - } else if (zenMode.isSystemOwned() && zenMode.getType() == TYPE_SCHEDULE_CALENDAR) { - switchPref.setTitle(R.string.zen_mode_set_calendar_link); - switchPref.setIcon(null); - // TODO: b/332937635 - set correct metrics category - switchPref.setIntent(ZenSubSettingLauncher.forModeFragment(mContext, - ZenModeSetCalendarFragment.class, zenMode.getId(), 0).toIntent()); - } else if (zenMode.isSystemOwned()) { - switchPref.setTitle(R.string.zen_mode_select_schedule); - switchPref.setIcon(R.drawable.ic_add_24dp); - switchPref.setSummary(""); - // TODO: b/342156843 - Hide the switch (needs support in SettingsLib). - switchPref.setOnPreferenceClickListener(clickedPreference -> { - ZenModeScheduleChooserDialog.show(mFragment, mOnScheduleOptionListener); - return true; - }); + if (zenMode.isSystemOwned()) { + if (zenMode.getType() == TYPE_SCHEDULE_TIME) { + switchPref.setTitle(R.string.zen_mode_set_schedule_link); + // TODO: b/332937635 - set correct metrics category + switchPref.setIntent(ZenSubSettingLauncher.forModeFragment(mContext, + ZenModeSetScheduleFragment.class, zenMode.getId(), 0).toIntent()); + } else if (zenMode.getType() == TYPE_SCHEDULE_CALENDAR) { + switchPref.setTitle(R.string.zen_mode_set_calendar_link); + switchPref.setIcon(null); + // TODO: b/332937635 - set correct metrics category + switchPref.setIntent(ZenSubSettingLauncher.forModeFragment(mContext, + ZenModeSetCalendarFragment.class, zenMode.getId(), 0).toIntent()); + } else { + switchPref.setTitle(R.string.zen_mode_select_schedule); + switchPref.setIcon(R.drawable.ic_add_24dp); + switchPref.setSummary(""); + // TODO: b/342156843 - Hide the switch (needs support in SettingsLib). + switchPref.setOnPreferenceClickListener(clickedPreference -> { + ZenModeScheduleChooserDialog.show(mFragment, mOnScheduleOptionListener); + return true; + }); + } } else { - // TODO: b/341961712 - direct preference to app-owned intent if available - switchPref.setTitle("not implemented"); + Intent intent = getAppRuleIntent(zenMode); + if (intent != null && isValidIntent(intent)) { + preference.setVisible(true); + switchPref.setTitle(R.string.zen_mode_configuration_link_title); + switchPref.setSummary(zenMode.getRule().getTriggerDescription()); + switchPref.setIntent(intent); + } else { + Log.i(TAG, "No intent found for " + zenMode.getRule().getName()); + preference.setVisible(false); + } } } @@ -114,4 +161,68 @@ class ZenModeSetTriggerLinkPreferenceController extends AbstractZenModePreferenc }); // TODO: b/342156843 - Do we want to jump to the corresponding schedule editing screen? }; + + @VisibleForTesting + protected @Nullable Intent getAppRuleIntent(ZenMode zenMode) { + Intent intent = new Intent().addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP) + .putExtra(ConditionProviderService.EXTRA_RULE_ID, zenMode.getId()) + .putExtra(EXTRA_AUTOMATIC_RULE_ID, zenMode.getId()); + String owner = zenMode.getRule().getPackageName(); + ComponentName configActivity = null; + if (zenMode.getRule().getConfigurationActivity() != null) { + // If a configuration activity is present, use that directly in the intent + configActivity = zenMode.getRule().getConfigurationActivity(); + } else { + // Otherwise, look for a condition provider service for the rule's package + ComponentInfo ci = mServiceListing.findService(zenMode.getRule().getOwner()); + if (ci == null) { + // do nothing + } else if (ci instanceof ActivityInfo) { + // new activity backed rule + intent.setComponent(new ComponentName(ci.packageName, ci.name)); + return intent; + } else if (ci.metaData != null) { + // old service backed rule + final String configurationActivity = ci.metaData.getString( + ConditionProviderService.META_DATA_CONFIGURATION_ACTIVITY); + if (configurationActivity != null) { + configActivity = ComponentName.unflattenFromString(configurationActivity); + } + } + } + + if (configActivity != null) { + // verify that the owner of the rule owns the configuration activity, but only if + // owner exists + intent.setComponent(configActivity); + if (owner == null) { + return intent; + } + try { + int ownerUid = mPm.getPackageUid(owner, 0); + int configActivityOwnerUid = mPm.getPackageUid(configActivity.getPackageName(), 0); + if (ownerUid == configActivityOwnerUid) { + return intent; + } else { + Log.w(TAG, "Config activity not in owner package for " + + zenMode.getRule().getName()); + return null; + } + } catch (PackageManager.NameNotFoundException e) { + Log.e(TAG, "Failed to find config activity"); + return null; + } + } + return null; + } + + private boolean isValidIntent(Intent intent) { + List results = mPm.queryIntentActivities( + intent, PackageManager.ResolveInfoFlags.of(0)); + if (intent.resolveActivity(mPm) == null || results.size() == 0) { + Log.w(TAG, "intent for zen rule invalid: " + intent); + return false; + } + return true; + } } diff --git a/src/com/android/settings/notification/modes/ZenModesListFragment.java b/src/com/android/settings/notification/modes/ZenModesListFragment.java index 77107f89d02..1883945944d 100644 --- a/src/com/android/settings/notification/modes/ZenModesListFragment.java +++ b/src/com/android/settings/notification/modes/ZenModesListFragment.java @@ -78,7 +78,7 @@ public class ZenModesListFragment extends ZenModesFragmentBase { return SettingsEnums.NOTIFICATION_ZEN_MODE_AUTOMATION; } - private static ManagedServiceSettings.Config getConditionProviderConfig() { + static ManagedServiceSettings.Config getConditionProviderConfig() { return new ManagedServiceSettings.Config.Builder() .setTag(TAG) .setIntentAction(ConditionProviderService.SERVICE_INTERFACE) diff --git a/src/com/android/settings/utils/ZenServiceListing.java b/src/com/android/settings/utils/ZenServiceListing.java index 99f56f621c8..96d700bd1e7 100644 --- a/src/com/android/settings/utils/ZenServiceListing.java +++ b/src/com/android/settings/utils/ZenServiceListing.java @@ -28,11 +28,14 @@ import android.content.pm.ServiceInfo; import android.util.ArraySet; import android.util.Slog; +import androidx.annotation.Nullable; + import java.util.ArrayList; import java.util.List; import java.util.Set; public class ZenServiceListing { + private static final String TAG = "ZenServiceListing"; private final Context mContext; private final ManagedServiceSettings.Config mConfig; @@ -40,9 +43,18 @@ public class ZenServiceListing { private final List mZenCallbacks = new ArrayList<>(); private final NotificationManager mNm; + // only used when android.app.modes_ui flag is true + @Nullable + private String mPkg = null; + public ZenServiceListing(Context context, ManagedServiceSettings.Config config) { + this(context, config, null); + } + + public ZenServiceListing(Context context, ManagedServiceSettings.Config config, @Nullable String pkg) { mContext = context; mConfig = config; + mPkg = pkg; mNm = (NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE); } @@ -89,12 +101,16 @@ public class ZenServiceListing { } } - private static void getServices(ManagedServiceSettings.Config c, List list, + private void getServices(ManagedServiceSettings.Config c, List list, PackageManager pm) { final int user = ActivityManager.getCurrentUser(); + Intent queryIntent = new Intent(c.intentAction); + if (mPkg != null) { + queryIntent.setPackage(mPkg); + } List installedServices = pm.queryIntentServicesAsUser( - new Intent(c.intentAction), + queryIntent, PackageManager.GET_SERVICES | PackageManager.GET_META_DATA, user); @@ -115,12 +131,16 @@ public class ZenServiceListing { } } - private static void getActivities(ManagedServiceSettings.Config c, List list, + private void getActivities(ManagedServiceSettings.Config c, List list, PackageManager pm) { final int user = ActivityManager.getCurrentUser(); + Intent queryIntent = new Intent(c.configIntentAction); + if (mPkg != null) { + queryIntent.setPackage(mPkg); + } List resolveInfos = pm.queryIntentActivitiesAsUser( - new Intent(c.configIntentAction), + queryIntent, PackageManager.GET_ACTIVITIES | PackageManager.GET_META_DATA, user); diff --git a/tests/robotests/src/com/android/settings/notification/modes/TestModeBuilder.java b/tests/robotests/src/com/android/settings/notification/modes/TestModeBuilder.java index 26c7fe170c0..6a1f47409be 100644 --- a/tests/robotests/src/com/android/settings/notification/modes/TestModeBuilder.java +++ b/tests/robotests/src/com/android/settings/notification/modes/TestModeBuilder.java @@ -18,6 +18,7 @@ package com.android.settings.notification.modes; import android.app.AutomaticZenRule; import android.app.NotificationManager; +import android.content.ComponentName; import android.net.Uri; import android.service.notification.Condition; import android.service.notification.ZenDeviceEffects; @@ -149,6 +150,18 @@ class TestModeBuilder { return this; } + TestModeBuilder setConfigurationActivity(ComponentName configActivity) { + mRule.setConfigurationActivity(configActivity); + mConfigZenRule.configurationActivity = configActivity; + return this; + } + + TestModeBuilder setOwner(ComponentName owner) { + mRule.setOwner(owner); + mConfigZenRule.component = owner; + return this; + } + ZenMode build() { return new ZenMode(mId, mRule, mConfigZenRule); } diff --git a/tests/robotests/src/com/android/settings/notification/modes/ZenModeSetTriggerLinkPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/notification/modes/ZenModeSetTriggerLinkPreferenceControllerTest.java index 31959e5d699..4ba21469fad 100644 --- a/tests/robotests/src/com/android/settings/notification/modes/ZenModeSetTriggerLinkPreferenceControllerTest.java +++ b/tests/robotests/src/com/android/settings/notification/modes/ZenModeSetTriggerLinkPreferenceControllerTest.java @@ -19,8 +19,10 @@ package com.android.settings.notification.modes; import static android.app.AutomaticZenRule.TYPE_OTHER; import static android.app.AutomaticZenRule.TYPE_SCHEDULE_CALENDAR; import static android.app.AutomaticZenRule.TYPE_SCHEDULE_TIME; +import static android.app.NotificationManager.EXTRA_AUTOMATIC_RULE_ID; import static android.app.NotificationManager.INTERRUPTION_FILTER_PRIORITY; import static android.platform.test.flag.junit.SetFlagsRule.DefaultInitValueType.DEVICE_DEFAULT; +import static android.service.notification.ConditionProviderService.EXTRA_RULE_ID; import static com.android.settings.notification.modes.ZenModeSetTriggerLinkPreferenceController.AUTOMATIC_TRIGGER_PREF_KEY; @@ -31,10 +33,16 @@ import static org.mockito.Mockito.when; import android.app.AutomaticZenRule; import android.app.Flags; +import android.content.ComponentName; import android.content.Context; +import android.content.Intent; +import android.content.pm.ComponentInfo; +import android.content.pm.PackageManager; import android.net.Uri; +import android.os.Bundle; import android.platform.test.annotations.EnableFlags; import android.platform.test.flag.junit.SetFlagsRule; +import android.service.notification.ConditionProviderService; import android.service.notification.SystemZenRules; import android.service.notification.ZenModeConfig; @@ -44,6 +52,7 @@ import androidx.test.core.app.ApplicationProvider; import com.android.settings.R; import com.android.settings.SettingsActivity; import com.android.settings.dashboard.DashboardFragment; +import com.android.settings.utils.ZenServiceListing; import com.android.settingslib.PrimarySwitchPreference; import com.android.settingslib.notification.modes.ZenMode; import com.android.settingslib.notification.modes.ZenModesBackend; @@ -71,6 +80,11 @@ public class ZenModeSetTriggerLinkPreferenceControllerTest { private PrimarySwitchPreference mPreference; + @Mock + private ZenServiceListing mServiceListing; + @Mock + private PackageManager mPm; + @Mock private PreferenceCategory mPrefCategory; @Mock @@ -84,8 +98,10 @@ public class ZenModeSetTriggerLinkPreferenceControllerTest { mContext = ApplicationProvider.getApplicationContext(); mPrefController = new ZenModeSetTriggerLinkPreferenceController(mContext, - "zen_automatic_trigger_category", mFragment, mBackend); + "zen_automatic_trigger_category", mFragment, mBackend, mPm); + mPrefController.setServiceListing(mServiceListing); mPreference = new PrimarySwitchPreference(mContext); + when(mPrefCategory.findPreference(AUTOMATIC_TRIGGER_PREF_KEY)).thenReturn(mPreference); } @@ -93,9 +109,9 @@ public class ZenModeSetTriggerLinkPreferenceControllerTest { public void testIsAvailable() { // should not be available for manual DND ZenMode manualMode = ZenMode.manualDndMode(new AutomaticZenRule.Builder("Do Not Disturb", - Uri.parse("manual")) - .setInterruptionFilter(INTERRUPTION_FILTER_PRIORITY) - .build(), true); + Uri.parse("manual")) + .setInterruptionFilter(INTERRUPTION_FILTER_PRIORITY) + .build(), true); mPrefController.updateZenMode(mPrefCategory, manualMode); assertThat(mPrefController.isAvailable()).isFalse(); @@ -164,7 +180,7 @@ public class ZenModeSetTriggerLinkPreferenceControllerTest { @Test public void testRuleLink_schedule() { ZenModeConfig.ScheduleInfo scheduleInfo = new ZenModeConfig.ScheduleInfo(); - scheduleInfo.days = new int[] { Calendar.MONDAY, Calendar.TUESDAY, Calendar.THURSDAY }; + scheduleInfo.days = new int[]{Calendar.MONDAY, Calendar.TUESDAY, Calendar.THURSDAY}; scheduleInfo.startHour = 1; scheduleInfo.endHour = 15; ZenMode mode = new TestModeBuilder() @@ -237,4 +253,109 @@ public class ZenModeSetTriggerLinkPreferenceControllerTest { assertThat(updatedMode.getRule().getOwner()).isEqualTo( ZenModeConfig.getScheduleConditionProvider()); } + + @Test + public void testGetAppRuleIntent_configActivity() throws Exception { + ZenMode mode = new TestModeBuilder() + .setId("id") + .setPackage(mContext.getPackageName()) + .setConfigurationActivity(new ComponentName(mContext.getPackageName(), "test")) + .setType(TYPE_OTHER) + .setTriggerDescription("some rule") + .build(); + + when(mPm.getPackageUid(null, 0)).thenReturn(-1); + when(mPm.getPackageUid(mContext.getPackageName(), 0)).thenReturn(1); + + Intent res = mPrefController.getAppRuleIntent(mode); + assertThat(res).isNotNull(); + assertThat(res.getStringExtra(EXTRA_RULE_ID)).isEqualTo("id"); + assertThat(res.getStringExtra(EXTRA_AUTOMATIC_RULE_ID)).isEqualTo("id"); + assertThat(res.getComponent()).isEqualTo( + new ComponentName(mContext.getPackageName(), "test")); + } + + @Test + public void testGetAppRuleIntent_configActivity_wrongPackage() throws Exception { + ZenMode mode = new TestModeBuilder() + .setPackage(mContext.getPackageName()) + .setConfigurationActivity(new ComponentName("another", "test")) + .setType(TYPE_OTHER) + .build(); + + when(mPm.getPackageUid(null, 0)).thenReturn(-1); + when(mPm.getPackageUid(mContext.getPackageName(), 0)).thenReturn(1); + + Intent res = mPrefController.getAppRuleIntent(mode); + assertThat(res).isNull(); + } + + @Test + public void testGetAppRuleIntent_configActivity_unspecifiedOwner() throws Exception { + ZenMode mode = new TestModeBuilder() + .setId("id") + .setPackage(null) + .setConfigurationActivity(new ComponentName("another", "test")) + .setType(TYPE_OTHER) + .build(); + + when(mPm.getPackageUid(null, 0)).thenReturn(-1); + when(mPm.getPackageUid(mContext.getPackageName(), 0)).thenReturn(1); + + Intent res = mPrefController.getAppRuleIntent(mode); + assertThat(res).isNotNull(); + assertThat(res.getStringExtra(EXTRA_RULE_ID)).isEqualTo("id"); + assertThat(res.getStringExtra(EXTRA_AUTOMATIC_RULE_ID)).isEqualTo("id"); + assertThat(res.getComponent()).isEqualTo(new ComponentName("another", "test")); + } + + @Test + public void testGetAppRuleIntent_cps() throws Exception { + ZenMode mode = new TestModeBuilder() + .setId("id") + .setPackage(mContext.getPackageName()) + .setOwner(new ComponentName(mContext.getPackageName(), "service")) + .build(); + + ComponentInfo ci = new ComponentInfo(); + ci.packageName = mContext.getPackageName(); + ci.metaData = new Bundle(); + ci.metaData.putString(ConditionProviderService.META_DATA_CONFIGURATION_ACTIVITY, + ComponentName.flattenToShortString( + new ComponentName(mContext.getPackageName(), "activity"))); + + when(mServiceListing.findService(new ComponentName(mContext.getPackageName(), "service"))) + .thenReturn(ci); + when(mPm.getPackageUid(null, 0)).thenReturn(-1); + when(mPm.getPackageUid(mContext.getPackageName(), 0)).thenReturn(1); + + Intent res = mPrefController.getAppRuleIntent(mode); + assertThat(res).isNotNull(); + assertThat(res.getStringExtra(EXTRA_RULE_ID)).isEqualTo("id"); + assertThat(res.getStringExtra(EXTRA_AUTOMATIC_RULE_ID)).isEqualTo("id"); + assertThat(res.getComponent()).isEqualTo( + new ComponentName(mContext.getPackageName(), "activity")); + } + + @Test + public void testGetAppRuleIntent_cps_wrongPackage() throws Exception { + ZenMode mode = new TestModeBuilder() + .setPackage("other") + .setOwner(new ComponentName(mContext.getPackageName(), "service")) + .setType(TYPE_OTHER) + .build(); + + ComponentInfo ci = new ComponentInfo(); + ci.packageName = mContext.getPackageName(); + ci.metaData = new Bundle(); + ci.metaData.putString(ConditionProviderService.META_DATA_CONFIGURATION_ACTIVITY, + ComponentName.flattenToShortString( + new ComponentName(mContext.getPackageName(), "activity"))); + + when(mPm.getPackageUid(null, 0)).thenReturn(-1); + when(mPm.getPackageUid(mContext.getPackageName(), 0)).thenReturn(1); + + Intent res = mPrefController.getAppRuleIntent(mode); + assertThat(res).isNull(); + } }