From 2c4b42c0b7a227ed78a1ac89600deb7d6eadfd3b Mon Sep 17 00:00:00 2001 From: Stephen Chen Date: Thu, 6 Apr 2017 14:59:49 -0700 Subject: [PATCH] Update "Open networks available" toggle to instead open notification channel preferences. Bug: 36526438 Test: make ROBOTEST_FILTER=NotifyOpenNetworkPreferenceControllerTest RunSettingsRoboTests -j40 Change-Id: Idde3949856d050e62abff2c75a7b7db475a94d99 --- res/xml/wifi_configure_settings.xml | 5 +- .../utils/NotificationChannelHelper.java | 64 +++++++ .../settings/wifi/ConfigureWifiSettings.java | 15 +- ...otifyOpenNetworksPreferenceController.java | 164 ++++++++---------- ...fyOpenNetworkPreferenceControllerTest.java | 133 +++++++++----- 5 files changed, 245 insertions(+), 136 deletions(-) create mode 100644 src/com/android/settings/utils/NotificationChannelHelper.java diff --git a/res/xml/wifi_configure_settings.xml b/res/xml/wifi_configure_settings.xml index fa5239d1fcc..b1625cc72e4 100644 --- a/res/xml/wifi_configure_settings.xml +++ b/res/xml/wifi_configure_settings.xml @@ -31,11 +31,10 @@ android:title="@string/use_open_wifi_automatically_title" android:summary="@string/use_open_wifi_automatically_summary" /> - + android:icon="@drawable/ic_settings_notifications"/> getPreferenceControllers(Context context) { final NetworkScoreManagerWrapper networkScoreManagerWrapper = new NetworkScoreManagerWrapper(context.getSystemService(NetworkScoreManager.class)); + final NotificationChannelHelper notificationChannelHelper = + new NotificationChannelHelper(INotificationManager.Stub.asInterface( + ServiceManager.getService(Context.NOTIFICATION_SERVICE))); + final WifiManager wifiManager = context.getSystemService(WifiManager.class); mUseOpenWifiPreferenceController = new UseOpenWifiPreferenceController(context, this, networkScoreManagerWrapper, getLifecycle()); - final WifiManager wifiManager = (WifiManager) getSystemService(WIFI_SERVICE); final List controllers = new ArrayList<>(); controllers.add(new WifiWakeupPreferenceController(context, getLifecycle())); controllers.add(new NetworkScorerPickerPreferenceController(context, networkScoreManagerWrapper)); - controllers.add(new NotifyOpenNetworksPreferenceController(context, getLifecycle())); + controllers.add(new NotifyOpenNetworksPreferenceController(context, + networkScoreManagerWrapper, notificationChannelHelper, getPackageManager())); controllers.add(mUseOpenWifiPreferenceController); controllers.add(new WifiSleepPolicyPreferenceController(context)); controllers.add(new WifiInfoPreferenceController(context, getLifecycle(), wifiManager)); diff --git a/src/com/android/settings/wifi/NotifyOpenNetworksPreferenceController.java b/src/com/android/settings/wifi/NotifyOpenNetworksPreferenceController.java index 8771da48a69..a85a2663799 100644 --- a/src/com/android/settings/wifi/NotifyOpenNetworksPreferenceController.java +++ b/src/com/android/settings/wifi/NotifyOpenNetworksPreferenceController.java @@ -16,75 +16,46 @@ package com.android.settings.wifi; -import android.content.ContentResolver; +import android.app.NotificationChannel; +import android.app.NotificationManager; import android.content.Context; -import android.database.ContentObserver; -import android.net.Uri; -import android.os.Handler; +import android.content.Intent; +import android.content.pm.PackageManager; +import android.net.NetworkScorerAppData; +import android.os.RemoteException; import android.provider.Settings; -import android.support.v14.preference.SwitchPreference; +import android.support.annotation.Nullable; import android.support.v7.preference.Preference; -import android.support.v7.preference.PreferenceScreen; import android.text.TextUtils; - +import android.util.Log; +import com.android.settings.R; import com.android.settings.core.PreferenceController; -import com.android.settings.core.lifecycle.Lifecycle; -import com.android.settings.core.lifecycle.LifecycleObserver; -import com.android.settings.core.lifecycle.events.OnPause; -import com.android.settings.core.lifecycle.events.OnResume; +import com.android.settings.network.NetworkScoreManagerWrapper; +import com.android.settings.utils.NotificationChannelHelper; +import com.android.settings.utils.NotificationChannelHelper.NotificationChannelWrapper; /** - * {@link PreferenceController} that controls whether we should notify user when open network is - * available. + * {@link PreferenceController} that shows whether we should notify user when open network is + * available. The preference links to {@link NotificationChannel} settings. */ -public class NotifyOpenNetworksPreferenceController extends PreferenceController implements - LifecycleObserver, OnResume, OnPause { +public class NotifyOpenNetworksPreferenceController extends PreferenceController { + private static final String TAG = "OpenNetworks"; private static final String KEY_NOTIFY_OPEN_NETWORKS = "notify_open_networks"; - private SettingObserver mSettingObserver; - public NotifyOpenNetworksPreferenceController(Context context, Lifecycle lifecycle) { + private NetworkScoreManagerWrapper mNetworkScoreManager; + private NotificationChannelHelper mNotificationChannelHelper; + private PackageManager mPackageManager; + + public NotifyOpenNetworksPreferenceController( + Context context, + NetworkScoreManagerWrapper networkScoreManager, + NotificationChannelHelper notificationChannelHelper, + PackageManager packageManager) { super(context); - lifecycle.addObserver(this); - } - - @Override - public void displayPreference(PreferenceScreen screen) { - super.displayPreference(screen); - mSettingObserver = new SettingObserver(screen.findPreference(KEY_NOTIFY_OPEN_NETWORKS)); - } - - @Override - public void onResume() { - if (mSettingObserver != null) { - mSettingObserver.register(mContext.getContentResolver(), true /* register */); - } - } - - @Override - public void onPause() { - if (mSettingObserver != null) { - mSettingObserver.register(mContext.getContentResolver(), false /* register */); - } - } - - @Override - public boolean isAvailable() { - return true; - } - - @Override - public boolean handlePreferenceTreeClick(Preference preference) { - if (!TextUtils.equals(preference.getKey(), KEY_NOTIFY_OPEN_NETWORKS)) { - return false; - } - if (!(preference instanceof SwitchPreference)) { - return false; - } - Settings.Global.putInt(mContext.getContentResolver(), - Settings.Global.WIFI_NETWORKS_AVAILABLE_NOTIFICATION_ON, - ((SwitchPreference) preference).isChecked() ? 1 : 0); - return true; + mNetworkScoreManager = networkScoreManager; + mNotificationChannelHelper = notificationChannelHelper; + mPackageManager = packageManager; } @Override @@ -93,42 +64,59 @@ public class NotifyOpenNetworksPreferenceController extends PreferenceController } @Override - public void updateState(Preference preference) { - if (!(preference instanceof SwitchPreference)) { - return; - } - final SwitchPreference notifyOpenNetworks = (SwitchPreference) preference; - notifyOpenNetworks.setChecked(Settings.Global.getInt(mContext.getContentResolver(), - Settings.Global.WIFI_NETWORKS_AVAILABLE_NOTIFICATION_ON, 0) == 1); - notifyOpenNetworks.setEnabled(Settings.Global.getInt(mContext.getContentResolver(), - Settings.Global.NETWORK_RECOMMENDATIONS_ENABLED, 0) == 1); + public boolean isAvailable() { + return getNotificationChannel() != null; } - class SettingObserver extends ContentObserver { - private final Uri NETWORK_RECOMMENDATIONS_ENABLED_URI = - Settings.Global.getUriFor(Settings.Global.NETWORK_RECOMMENDATIONS_ENABLED); - - private final Preference mPreference; - - public SettingObserver(Preference preference) { - super(new Handler()); - mPreference = preference; + @Override + public boolean handlePreferenceTreeClick(Preference preference) { + if (!TextUtils.equals(preference.getKey(), KEY_NOTIFY_OPEN_NETWORKS)) { + return false; + } + NetworkScorerAppData scorer = mNetworkScoreManager.getActiveScorer(); + if (scorer == null) { + return false; } - public void register(ContentResolver cr, boolean register) { - if (register) { - cr.registerContentObserver(NETWORK_RECOMMENDATIONS_ENABLED_URI, false, this); - } else { - cr.unregisterContentObserver(this); - } - } + Intent intent = new Intent(Settings.ACTION_CHANNEL_NOTIFICATION_SETTINGS); + intent.putExtra(Settings.EXTRA_CHANNEL_ID, + scorer.getNetworkAvailableNotificationChannelId()); + intent.putExtra(Settings.EXTRA_APP_PACKAGE, scorer.getRecommendationServicePackageName()); + mContext.startActivity(intent); + return true; + } - @Override - public void onChange(boolean selfChange, Uri uri) { - super.onChange(selfChange, uri); - if (NETWORK_RECOMMENDATIONS_ENABLED_URI.equals(uri)) { - updateState(mPreference); - } + @Override + public void updateState(Preference preference) { + NotificationChannelWrapper channel = getNotificationChannel(); + if (channel == null) { + preference.setSummary(null); + } else { + preference.setSummary(channel.getImportance() != NotificationManager.IMPORTANCE_NONE ? + R.string.notification_toggle_on : R.string.notification_toggle_off); + } + } + + @Nullable + private NotificationChannelWrapper getNotificationChannel() { + NetworkScorerAppData scorer = mNetworkScoreManager.getActiveScorer(); + if (scorer == null) { + return null; + } + String packageName = scorer.getRecommendationServicePackageName(); + String channelId = scorer.getNetworkAvailableNotificationChannelId(); + if (packageName == null || channelId == null) { + return null; + } + try { + return mNotificationChannelHelper.getNotificationChannelForPackage( + packageName, + mPackageManager.getPackageUid(packageName, 0 /* flags */), + channelId, + false /* includeDeleted */ ); + } catch (RemoteException | PackageManager.NameNotFoundException e) { + Log.d(TAG, "Failed to get notification channel.", e); + return null; } } } diff --git a/tests/robotests/src/com/android/settings/wifi/NotifyOpenNetworkPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/wifi/NotifyOpenNetworkPreferenceControllerTest.java index 3afa7fbef67..78dbcbdce03 100644 --- a/tests/robotests/src/com/android/settings/wifi/NotifyOpenNetworkPreferenceControllerTest.java +++ b/tests/robotests/src/com/android/settings/wifi/NotifyOpenNetworkPreferenceControllerTest.java @@ -16,26 +16,29 @@ package com.android.settings.wifi; -import static android.provider.Settings.Global.NETWORK_RECOMMENDATIONS_ENABLED; -import static android.provider.Settings.Global.WIFI_NETWORKS_AVAILABLE_NOTIFICATION_ON; - import static com.google.common.truth.Truth.assertThat; +import static org.mockito.Mockito.anyBoolean; +import static org.mockito.Mockito.anyInt; +import static org.mockito.Mockito.anyString; +import static org.mockito.Mockito.when; -import static org.mockito.Mockito.mock; -import static org.mockito.Mockito.verify; - +import android.app.NotificationManager; +import android.content.ComponentName; import android.content.Context; -import android.provider.Settings; -import android.support.v14.preference.SwitchPreference; +import android.content.pm.PackageManager; +import android.net.NetworkScorerAppData; +import android.os.RemoteException; import android.support.v7.preference.Preference; - +import com.android.settings.R; import com.android.settings.SettingsRobolectricTestRunner; import com.android.settings.TestConfig; -import com.android.settings.core.lifecycle.Lifecycle; - +import com.android.settings.network.NetworkScoreManagerWrapper; +import com.android.settings.utils.NotificationChannelHelper; +import com.android.settings.utils.NotificationChannelHelper.NotificationChannelWrapper; import org.junit.Before; 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; @@ -44,71 +47,123 @@ import org.robolectric.annotation.Config; @Config(manifest = TestConfig.MANIFEST_PATH, sdk = TestConfig.SDK_VERSION) public class NotifyOpenNetworkPreferenceControllerTest { + private static final String TEST_SCORER_PACKAGE = "Test Package"; + private static final String TEST_SCORER_CLASS = "Test Class"; + private static final String TEST_SCORER_LABEL = "Test Label"; + private static final String NOTIFICATION_ID = "Notification Id"; + private static final CharSequence NOTIFICATION_NAME = "Notification Name"; + private Context mContext; private NotifyOpenNetworksPreferenceController mController; + @Mock private NetworkScoreManagerWrapper mNetworkScorer; + @Mock private NotificationChannelHelper mNotificationChannelHelper; + @Mock private PackageManager mPackageManager; + @Mock private NotificationChannelWrapper mChannel; @Before public void setUp() { MockitoAnnotations.initMocks(this); mContext = RuntimeEnvironment.application; - mController = new NotifyOpenNetworksPreferenceController(mContext, mock(Lifecycle.class)); + mController = new NotifyOpenNetworksPreferenceController( + mContext, mNetworkScorer, mNotificationChannelHelper, mPackageManager); + ComponentName scorer = new ComponentName(TEST_SCORER_PACKAGE, TEST_SCORER_CLASS); + + NetworkScorerAppData scorerAppData = new NetworkScorerAppData( + 0, scorer, TEST_SCORER_LABEL, null /* enableUseOpenWifiActivity */, + NOTIFICATION_ID); + when(mNetworkScorer.getActiveScorer()).thenReturn(scorerAppData); } @Test - public void testIsAvailable_shouldAlwaysReturnTrue() { + public void testIsAvailable_shouldReturnFalseWhenScorerDoesNotExist() + throws RemoteException { + when(mNetworkScorer.getActiveScorer()).thenReturn(null); + + assertThat(mController.isAvailable()).isFalse(); + } + + @Test + public void testIsAvailable_shouldReturnFalseWhenNotificationChannelIdDoesNotExist() + throws RemoteException { + ComponentName scorer = new ComponentName(TEST_SCORER_PACKAGE, TEST_SCORER_CLASS); + NetworkScorerAppData scorerAppData = new NetworkScorerAppData( + 0, scorer, TEST_SCORER_LABEL, null /* enableUseOpenWifiActivity */, + null /* networkAvailableNotificationChannelId */); + when(mNetworkScorer.getActiveScorer()).thenReturn(scorerAppData); + + assertThat(mController.isAvailable()).isFalse(); + } + + @Test + public void testIsAvailable_shouldReturnFalseWhenNotificationChannelDoesNotExist() + throws RemoteException { + when(mNotificationChannelHelper.getNotificationChannelForPackage( + anyString(), anyInt(), anyString(), anyBoolean())).thenReturn(null); + + assertThat(mController.isAvailable()).isFalse(); + } + + @Test + public void testIsAvailable_shouldReturnTrueWhenNotificationChannelExists() + throws RemoteException { + when(mNotificationChannelHelper.getNotificationChannelForPackage( + anyString(), anyInt(), anyString(), anyBoolean())).thenReturn(mChannel); + assertThat(mController.isAvailable()).isTrue(); } @Test public void handlePreferenceTreeClick_nonMatchingKey_shouldDoNothing() { - final SwitchPreference pref = new SwitchPreference(mContext); + final Preference pref = new Preference(mContext); assertThat(mController.handlePreferenceTreeClick(pref)).isFalse(); } @Test - public void handlePreferenceTreeClick_nonMatchingType_shouldDoNothing() { + public void handlePreferenceTreeClick_nullScorer_shouldDoNothing() { final Preference pref = new Preference(mContext); pref.setKey(mController.getPreferenceKey()); + when(mNetworkScorer.getActiveScorer()).thenReturn(null); assertThat(mController.handlePreferenceTreeClick(pref)).isFalse(); } @Test - public void handlePreferenceTreeClick_matchingKeyAndType_shouldUpdateSetting() { - final SwitchPreference pref = new SwitchPreference(mContext); - pref.setChecked(true); + public void handlePreferenceTreeClick_matchingKeyAndScorerExists_shouldLaunchActivity() + throws RemoteException { + final Preference pref = new Preference(mContext); pref.setKey(mController.getPreferenceKey()); + when(mNotificationChannelHelper.getNotificationChannelForPackage( + anyString(), anyInt(), anyString(), anyBoolean())).thenReturn(mChannel); assertThat(mController.handlePreferenceTreeClick(pref)).isTrue(); - assertThat(Settings.Global.getInt(mContext.getContentResolver(), - WIFI_NETWORKS_AVAILABLE_NOTIFICATION_ON, 0)) - .isEqualTo(1); } @Test - public void updateState_preferenceSetCheckedAndSetEnabledWhenSettingsAreEnabled() { - final SwitchPreference preference = mock(SwitchPreference.class); - Settings.System.putInt(mContext.getContentResolver(), NETWORK_RECOMMENDATIONS_ENABLED, 1); - Settings.System.putInt(mContext.getContentResolver(), - WIFI_NETWORKS_AVAILABLE_NOTIFICATION_ON, 1); + public void updateState_notificationsEnabled_shouldShowEnabledSummary() throws RemoteException { + final Preference pref = new Preference(mContext); + pref.setKey(mController.getPreferenceKey()); + when(mNotificationChannelHelper.getNotificationChannelForPackage( + anyString(), anyInt(), anyString(), anyBoolean())).thenReturn(mChannel); + when(mChannel.getImportance()).thenReturn(NotificationManager.IMPORTANCE_DEFAULT); + mController.updateState(pref); - mController.updateState(preference); - - verify(preference).setChecked(true); - verify(preference).setEnabled(true); + assertThat(pref.getSummary()).isEqualTo( + mContext.getString(R.string.notification_toggle_on)); } @Test - public void updateState_preferenceSetCheckedAndSetEnabledWhenSettingsAreDisabled() { - final SwitchPreference preference = mock(SwitchPreference.class); - Settings.System.putInt(mContext.getContentResolver(), NETWORK_RECOMMENDATIONS_ENABLED, 0); - Settings.System.putInt(mContext.getContentResolver(), - WIFI_NETWORKS_AVAILABLE_NOTIFICATION_ON, 0); + public void updateState_notificationsEnabled_shouldShowDisabledSummary() + throws RemoteException { + final Preference pref = new Preference(mContext); + pref.setKey(mController.getPreferenceKey()); + when(mNotificationChannelHelper.getNotificationChannelForPackage( + anyString(), anyInt(), anyString(), anyBoolean())).thenReturn(mChannel); + when(mChannel.getImportance()).thenReturn(NotificationManager.IMPORTANCE_NONE); + mController.updateState(pref); - mController.updateState(preference); - - verify(preference).setChecked(false); - verify(preference).setEnabled(false); + assertThat(pref.getSummary()).isEqualTo( + mContext.getString(R.string.notification_toggle_off)); } + }