From ec0a30a8b9f2f62d99b26dcf0e61234bb0d5b427 Mon Sep 17 00:00:00 2001 From: pastychang Date: Mon, 22 Apr 2019 16:17:46 +0800 Subject: [PATCH 01/10] Set QR scan activity to light theme in setup flow Test: atest Bug: 131029518 Change-Id: Ibec28e78fcf17390cd3844ead4a88a4e6bff6094 --- res/values/themes.xml | 21 +++++++++++++++++++ .../settings/wifi/WifiDialogActivity.java | 16 ++++++++------ .../wifi/dpp/WifiDppEnrolleeActivity.java | 7 ++++++- .../settings/wifi/WifiDialogActivityTest.java | 21 +++++++++++++++++++ 4 files changed, 58 insertions(+), 7 deletions(-) diff --git a/res/values/themes.xml b/res/values/themes.xml index 5db5f2fba03..1541b6d07d9 100644 --- a/res/values/themes.xml +++ b/res/values/themes.xml @@ -210,4 +210,25 @@ @*android:string/config_headlineFontFamilyMedium + + + diff --git a/src/com/android/settings/wifi/WifiDialogActivity.java b/src/com/android/settings/wifi/WifiDialogActivity.java index 8268eccac6b..77827867630 100644 --- a/src/com/android/settings/wifi/WifiDialogActivity.java +++ b/src/com/android/settings/wifi/WifiDialogActivity.java @@ -60,16 +60,18 @@ public class WifiDialogActivity extends Activity implements WifiDialog.WifiDialo private WifiDialog mDialog; + private Intent mIntent; + @Override protected void onCreate(Bundle savedInstanceState) { - final Intent intent = getIntent(); - if (WizardManagerHelper.isSetupWizardIntent(intent)) { - setTheme(SetupWizardUtils.getTransparentTheme(intent)); + mIntent = getIntent(); + if (WizardManagerHelper.isSetupWizardIntent(mIntent)) { + setTheme(SetupWizardUtils.getTransparentTheme(mIntent)); } super.onCreate(savedInstanceState); - final Bundle accessPointState = intent.getBundleExtra(KEY_ACCESS_POINT_STATE); + final Bundle accessPointState = mIntent.getBundleExtra(KEY_ACCESS_POINT_STATE); AccessPoint accessPoint = null; if (accessPointState != null) { accessPoint = new AccessPoint(this, accessPointState); @@ -175,9 +177,11 @@ public class WifiDialogActivity extends Activity implements WifiDialog.WifiDialo @Override public void onScan(WifiDialog dialog, String ssid) { + Intent intent = WifiDppUtils.getEnrolleeQrCodeScannerIntent(ssid); + WizardManagerHelper.copyWizardManagerExtras(mIntent, intent); + // Launch QR code scanner to join a network. - startActivityForResult(WifiDppUtils.getEnrolleeQrCodeScannerIntent(ssid), - REQUEST_CODE_WIFI_DPP_ENROLLEE_QR_CODE_SCANNER); + startActivityForResult(intent, REQUEST_CODE_WIFI_DPP_ENROLLEE_QR_CODE_SCANNER); } @Override diff --git a/src/com/android/settings/wifi/dpp/WifiDppEnrolleeActivity.java b/src/com/android/settings/wifi/dpp/WifiDppEnrolleeActivity.java index 392b27dc46d..2229895c6cd 100644 --- a/src/com/android/settings/wifi/dpp/WifiDppEnrolleeActivity.java +++ b/src/com/android/settings/wifi/dpp/WifiDppEnrolleeActivity.java @@ -18,7 +18,6 @@ package com.android.settings.wifi.dpp; import android.app.ActionBar; import android.app.settings.SettingsEnums; -import android.content.Context; import android.content.Intent; import android.os.Bundle; import android.util.Log; @@ -30,6 +29,8 @@ import androidx.fragment.app.FragmentTransaction; import com.android.settings.R; import com.android.settings.core.InstrumentedActivity; +import com.google.android.setupcompat.util.WizardManagerHelper; + /** * To provision "this" device with specified Wi-Fi network. * @@ -54,6 +55,10 @@ public class WifiDppEnrolleeActivity extends InstrumentedActivity implements protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); + if (WizardManagerHelper.isAnySetupWizard(getIntent())) { + setTheme(R.style.LightTheme_SettingsBase_SetupWizard); + } + setContentView(R.layout.wifi_dpp_activity); mFragmentManager = getSupportFragmentManager(); diff --git a/tests/robotests/src/com/android/settings/wifi/WifiDialogActivityTest.java b/tests/robotests/src/com/android/settings/wifi/WifiDialogActivityTest.java index 41d1bbe4f38..15a07802be2 100644 --- a/tests/robotests/src/com/android/settings/wifi/WifiDialogActivityTest.java +++ b/tests/robotests/src/com/android/settings/wifi/WifiDialogActivityTest.java @@ -27,6 +27,7 @@ import com.android.settings.R; import com.android.settings.testutils.shadow.ShadowAlertDialogCompat; import com.android.settings.testutils.shadow.ShadowConnectivityManager; import com.android.settings.testutils.shadow.ShadowWifiManager; +import com.android.settings.wifi.dpp.WifiDppEnrolleeActivity; import com.google.android.setupcompat.util.WizardManagerHelper; @@ -37,6 +38,7 @@ import org.mockito.Mock; import org.mockito.MockitoAnnotations; import org.robolectric.Robolectric; import org.robolectric.RobolectricTestRunner; +import org.robolectric.android.controller.ActivityController; import org.robolectric.annotation.Config; import org.robolectric.util.ReflectionHelpers; @@ -111,4 +113,23 @@ public class WifiDialogActivityTest { assertThat(dialog.getContext().getThemeResId()) .isEqualTo(R.style.SuwAlertDialogThemeCompat_Light); } + + @Test + public void onScan_whenLaunchFromDeferredSetup_shouldApplyLightTheme() { + ActivityController controller = Robolectric.buildActivity( + WifiDppEnrolleeActivity.class, + new Intent() + .setAction(WifiDppEnrolleeActivity.ACTION_ENROLLEE_QR_CODE_SCANNER) + .putExtra(WizardManagerHelper.EXTRA_IS_FIRST_RUN, true) + .putExtra(WizardManagerHelper.EXTRA_IS_SETUP_FLOW, true) + ); + controller.create(); + + Intent intent = controller.getIntent(); + assertThat(intent.getBooleanExtra(WizardManagerHelper.EXTRA_IS_FIRST_RUN, false)).isTrue(); + assertThat(intent.getBooleanExtra(WizardManagerHelper.EXTRA_IS_SETUP_FLOW, false)).isTrue(); + + assertThat(controller.get().getThemeResId()). + isEqualTo(R.style.LightTheme_SettingsBase_SetupWizard); + } } From 078134cb16400824d1d6edd5e8dcbfe0f7516f50 Mon Sep 17 00:00:00 2001 From: Leon Liao Date: Tue, 23 Apr 2019 13:25:52 +0800 Subject: [PATCH 02/10] Replace the placeholder animation. Update the placeholder animation in Accessibility Settings 'Time to read' and 'Time to take action'. Bug: 119283926 Bug: 129090045 Test: Screenshot | RunSettingsRoboTests Change-Id: I215facd35cb3b9d0fc90a5e267368de2edddf0dc --- res/drawable-nodpi/accessibility_timeout | 0 res/raw/accessibility_timeout.mp4 | 0 res/xml/accessibility_content_timeout_settings.xml | 4 ++-- res/xml/accessibility_control_timeout_settings.xml | 4 ++-- 4 files changed, 4 insertions(+), 4 deletions(-) create mode 100644 res/drawable-nodpi/accessibility_timeout create mode 100644 res/raw/accessibility_timeout.mp4 diff --git a/res/drawable-nodpi/accessibility_timeout b/res/drawable-nodpi/accessibility_timeout new file mode 100644 index 00000000000..e69de29bb2d diff --git a/res/raw/accessibility_timeout.mp4 b/res/raw/accessibility_timeout.mp4 new file mode 100644 index 00000000000..e69de29bb2d diff --git a/res/xml/accessibility_content_timeout_settings.xml b/res/xml/accessibility_content_timeout_settings.xml index 2d9072b222d..ea8d88ae68c 100644 --- a/res/xml/accessibility_content_timeout_settings.xml +++ b/res/xml/accessibility_content_timeout_settings.xml @@ -25,8 +25,8 @@ diff --git a/res/xml/accessibility_control_timeout_settings.xml b/res/xml/accessibility_control_timeout_settings.xml index ea8d8c64580..e5a6e5b0b26 100644 --- a/res/xml/accessibility_control_timeout_settings.xml +++ b/res/xml/accessibility_control_timeout_settings.xml @@ -25,8 +25,8 @@ From ca46ea69147ef4f6dd5d550669656874b3d8f4bd Mon Sep 17 00:00:00 2001 From: tmfang Date: Wed, 24 Apr 2019 16:52:00 +0800 Subject: [PATCH 03/10] Tweak paddings for apps filter in app info screen Since we enlarge touch target size for settings spinner widget, we need to tweak paddings of apps filters here. Test: visual Bug: 131060416 Change-Id: Ic6cc4f5d480f1fc34fdbecd86f82b324f9e75964 --- res/layout/apps_filter_spinner.xml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/res/layout/apps_filter_spinner.xml b/res/layout/apps_filter_spinner.xml index 50f0fde26c7..23465b910d9 100644 --- a/res/layout/apps_filter_spinner.xml +++ b/res/layout/apps_filter_spinner.xml @@ -26,8 +26,8 @@ android:layout_height="wrap_content" android:layout_width="wrap_content" android:layout_centerHorizontal="true" - android:layout_marginTop="24dp" - android:layout_marginBottom="16dp"/> + android:layout_marginTop="16dp" + android:layout_marginBottom="8dp"/> Date: Sun, 28 Apr 2019 00:29:32 -0700 Subject: [PATCH 04/10] Run postEnroll() after enrolling from SUW Bug: 131231334 Test: tested on blueline Change-Id: I225725edb1c3379f2f3f5bc8b5cbe9adddb49f59 --- .../fingerprint/FingerprintEnrollFinish.java | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/src/com/android/settings/biometrics/fingerprint/FingerprintEnrollFinish.java b/src/com/android/settings/biometrics/fingerprint/FingerprintEnrollFinish.java index b8ec103b015..5984d624203 100644 --- a/src/com/android/settings/biometrics/fingerprint/FingerprintEnrollFinish.java +++ b/src/com/android/settings/biometrics/fingerprint/FingerprintEnrollFinish.java @@ -33,6 +33,7 @@ import com.android.settings.biometrics.BiometricEnrollBase; import com.google.android.setupcompat.template.FooterBarMixin; import com.google.android.setupcompat.template.FooterButton; +import com.google.android.setupcompat.util.WizardManagerHelper; /** * Activity which concludes fingerprint enrollment. @@ -104,6 +105,9 @@ public class FingerprintEnrollFinish extends BiometricEnrollBase { protected void onNextButtonClick(View view) { updateFingerprintSuggestionEnableState(); setResult(RESULT_FINISHED); + if (WizardManagerHelper.isAnySetupWizard(getIntent())) { + postEnroll(); + } finish(); } @@ -127,6 +131,16 @@ public class FingerprintEnrollFinish extends BiometricEnrollBase { } } + private void postEnroll() { + final FingerprintManager fpm = Utils.getFingerprintManagerOrNull(this); + if (fpm != null) { + int result = fpm.postEnroll(); + if (result < 0) { + Log.w(TAG, "postEnroll failed: result = " + result); + } + } + } + private void onAddAnotherButtonClick(View view) { startActivityForResult(getFingerprintEnrollingIntent(), REQUEST_ADD_ANOTHER); } From 8979f8486581bf54b73f8037bc19d8ecaa1afa80 Mon Sep 17 00:00:00 2001 From: Ilya Matyukhin Date: Sun, 28 Apr 2019 15:10:02 -0700 Subject: [PATCH 05/10] Show fingerprint preferences after enrolling from settings Bug: 131231334 Test: tested on blueline Change-Id: Ifd43f28001fcb42ec61a62ad6656d2da2a0629eb --- AndroidManifest.xml | 11 +++++++++++ src/com/android/settings/Settings.java | 1 + .../fingerprint/FingerprintEnrollFinish.java | 13 +++++++++++++ .../biometrics/fingerprint/FingerprintSettings.java | 3 +++ .../settings/core/gateway/SettingsGateway.java | 2 ++ 5 files changed, 30 insertions(+) diff --git a/AndroidManifest.xml b/AndroidManifest.xml index 603900c1aed..764e1d2e4d7 100644 --- a/AndroidManifest.xml +++ b/AndroidManifest.xml @@ -436,6 +436,17 @@ android:value="com.android.settings.biometrics.face.FaceSettings" /> + + + + + + + + Date: Fri, 26 Apr 2019 12:56:50 -0400 Subject: [PATCH 06/10] Fix visibility and editability of importance fields - Block field should always be visible - Locked by OEM: cannot block or change importance - Locked by default app: cannot block, can change importance - Locked by system app: cannot block, can change importance - system app but blockable: can block, can change importance Test: robotests Fixes: 131248127 Change-Id: Ifa718c84573dd5125aefa4f672a79dc4f267d515 --- .../slices/NotificationChannelSlice.java | 2 +- .../NotificationMultiChannelAppRow.java | 3 +- .../BlockPreferenceController.java | 21 ++-- .../HighImportancePreferenceController.java | 2 +- .../ImportancePreferenceController.java | 4 +- .../MinImportancePreferenceController.java | 2 +- .../notification/NotificationBackend.java | 25 +++-- .../NotificationPreferenceController.java | 18 +-- .../NotificationSettingsBase.java | 16 ++- .../slices/NotificationChannelSliceTest.java | 3 +- .../NotificationMultiChannelAppRowTest.java | 5 +- .../AllowSoundPreferenceControllerTest.java | 7 +- .../BadgePreferenceControllerTest.java | 6 +- .../BlockPreferenceControllerTest.java | 104 ++++++++++++++++-- .../BubblePreferenceControllerTest.java | 5 +- .../DndPreferenceControllerTest.java | 4 +- ...ighImportancePreferenceControllerTest.java | 34 +++++- .../ImportancePreferenceControllerTest.java | 34 +++++- .../LightsPreferenceControllerTest.java | 4 +- ...MinImportancePreferenceControllerTest.java | 34 +++++- .../notification/NotificationBackendTest.java | 101 ++++++----------- .../NotificationPreferenceControllerTest.java | 45 +------- .../SoundPreferenceControllerTest.java | 4 +- .../VibrationPreferenceControllerTest.java | 4 +- 24 files changed, 293 insertions(+), 194 deletions(-) diff --git a/src/com/android/settings/homepage/contextualcards/slices/NotificationChannelSlice.java b/src/com/android/settings/homepage/contextualcards/slices/NotificationChannelSlice.java index a262191d395..ee9d089a342 100644 --- a/src/com/android/settings/homepage/contextualcards/slices/NotificationChannelSlice.java +++ b/src/com/android/settings/homepage/contextualcards/slices/NotificationChannelSlice.java @@ -459,7 +459,7 @@ public class NotificationChannelSlice implements CustomSliceable { private boolean isChannelConfigurable(NotificationChannel channel, NotificationBackend.AppRow appRow) { if (channel != null && appRow != null) { - return !TextUtils.equals(channel.getId(), appRow.lockedChannelId); + return !channel.isImportanceLockedByOEM(); } return false; diff --git a/src/com/android/settings/homepage/contextualcards/slices/NotificationMultiChannelAppRow.java b/src/com/android/settings/homepage/contextualcards/slices/NotificationMultiChannelAppRow.java index 4edce14dda3..bf91f53f3aa 100644 --- a/src/com/android/settings/homepage/contextualcards/slices/NotificationMultiChannelAppRow.java +++ b/src/com/android/settings/homepage/contextualcards/slices/NotificationMultiChannelAppRow.java @@ -16,6 +16,7 @@ package com.android.settings.homepage.contextualcards.slices; +import android.app.role.RoleManager; import android.content.Context; import android.content.pm.PackageInfo; @@ -46,7 +47,7 @@ class NotificationMultiChannelAppRow implements Callable 1) { return mNotificationBackend.loadAppRow(mContext, mContext.getPackageManager(), - mPackageInfo); + mContext.getSystemService(RoleManager.class), mPackageInfo); } return null; } diff --git a/src/com/android/settings/notification/BlockPreferenceController.java b/src/com/android/settings/notification/BlockPreferenceController.java index 960526cb05b..37589d9ea8e 100644 --- a/src/com/android/settings/notification/BlockPreferenceController.java +++ b/src/com/android/settings/notification/BlockPreferenceController.java @@ -54,13 +54,7 @@ public class BlockPreferenceController extends NotificationPreferenceController if (mAppRow == null) { return false; } - if (mChannel != null) { - return isChannelBlockable(); - } else if (mChannelGroup != null) { - return isChannelGroupBlockable(); - } else { - return !mAppRow.systemApp || (mAppRow.systemApp && mAppRow.banned); - } + return true; } public void updateState(Preference preference) { @@ -78,6 +72,19 @@ public class BlockPreferenceController extends NotificationPreferenceController } bar.setDisabledByAdmin(mAdmin); + if (mChannel != null && !isChannelBlockable()) { + bar.setEnabled(false); + } + + if (mChannelGroup != null && !isChannelGroupBlockable()) { + bar.setEnabled(false); + } + + if (mChannel == null && mAppRow.systemApp + && (!mAppRow.banned || mAppRow.lockedImportance)) { + bar.setEnabled(false); + } + if (mChannel != null) { bar.setChecked(!mAppRow.banned && mChannel.getImportance() != NotificationManager.IMPORTANCE_NONE); diff --git a/src/com/android/settings/notification/HighImportancePreferenceController.java b/src/com/android/settings/notification/HighImportancePreferenceController.java index b82cb1facc2..da9b3b46537 100644 --- a/src/com/android/settings/notification/HighImportancePreferenceController.java +++ b/src/com/android/settings/notification/HighImportancePreferenceController.java @@ -62,7 +62,7 @@ public class HighImportancePreferenceController extends NotificationPreferenceCo @Override public void updateState(Preference preference) { if (mAppRow != null && mChannel != null) { - preference.setEnabled(mAdmin == null && isChannelBlockable()); + preference.setEnabled(mAdmin == null && !mChannel.isImportanceLockedByOEM()); RestrictedSwitchPreference pref = (RestrictedSwitchPreference) preference; pref.setChecked(mChannel.getImportance() >= IMPORTANCE_HIGH); diff --git a/src/com/android/settings/notification/ImportancePreferenceController.java b/src/com/android/settings/notification/ImportancePreferenceController.java index 708fc15bf38..46b2ec6ca78 100644 --- a/src/com/android/settings/notification/ImportancePreferenceController.java +++ b/src/com/android/settings/notification/ImportancePreferenceController.java @@ -59,9 +59,9 @@ public class ImportancePreferenceController extends NotificationPreferenceContro @Override public void updateState(Preference preference) { if (mAppRow!= null && mChannel != null) { - preference.setEnabled(mAdmin == null && isChannelBlockable()); + preference.setEnabled(mAdmin == null && !mChannel.isImportanceLockedByOEM()); ImportancePreference pref = (ImportancePreference) preference; - pref.setConfigurable(isChannelBlockable()); + pref.setConfigurable(!mChannel.isImportanceLockedByOEM()); pref.setImportance(mChannel.getImportance()); pref.setDisplayInStatusBar(mBackend.showSilentInStatusBar(mContext.getPackageName())); // TODO: b/128445911 pass along lock screen setting diff --git a/src/com/android/settings/notification/MinImportancePreferenceController.java b/src/com/android/settings/notification/MinImportancePreferenceController.java index 84cead13f1d..0af0c8dd331 100644 --- a/src/com/android/settings/notification/MinImportancePreferenceController.java +++ b/src/com/android/settings/notification/MinImportancePreferenceController.java @@ -62,7 +62,7 @@ public class MinImportancePreferenceController extends NotificationPreferenceCon @Override public void updateState(Preference preference) { if (mAppRow != null && mChannel != null) { - preference.setEnabled(mAdmin == null && isChannelBlockable()); + preference.setEnabled(mAdmin == null && !mChannel.isImportanceLockedByOEM()); RestrictedSwitchPreference pref = (RestrictedSwitchPreference) preference; pref.setChecked(mChannel.getImportance() == IMPORTANCE_MIN); diff --git a/src/com/android/settings/notification/NotificationBackend.java b/src/com/android/settings/notification/NotificationBackend.java index def820c990c..747c541e4b6 100644 --- a/src/com/android/settings/notification/NotificationBackend.java +++ b/src/com/android/settings/notification/NotificationBackend.java @@ -21,6 +21,7 @@ import static android.app.NotificationManager.IMPORTANCE_UNSPECIFIED; import android.app.INotificationManager; import android.app.NotificationChannel; import android.app.NotificationChannelGroup; +import android.app.role.RoleManager; import android.app.usage.IUsageStatsManager; import android.app.usage.UsageEvents; import android.content.ComponentName; @@ -86,14 +87,22 @@ public class NotificationBackend { return !systemApp || (systemApp && blocked); } - public AppRow loadAppRow(Context context, PackageManager pm, PackageInfo app) { + public AppRow loadAppRow(Context context, PackageManager pm, + RoleManager roleManager, PackageInfo app) { final AppRow row = loadAppRow(context, pm, app.applicationInfo); - recordCanBeBlocked(context, pm, app, row); + recordCanBeBlocked(context, pm, roleManager, app, row); return row; } - void recordCanBeBlocked(Context context, PackageManager pm, PackageInfo app, AppRow row) { + void recordCanBeBlocked(Context context, PackageManager pm, RoleManager rm, PackageInfo app, + AppRow row) { row.systemApp = Utils.isSystemPackage(context.getResources(), pm, app); + List roles = rm.getHeldRolesFromController(app.packageName); + if (roles.contains(RoleManager.ROLE_SMS) + || roles.contains(RoleManager.ROLE_DIALER) + || roles.contains(RoleManager.ROLE_EMERGENCY)) { + row.systemApp = true; + } final String[] nonBlockablePkgs = context.getResources().getStringArray( com.android.internal.R.array.config_nonBlockableNotificationPackages); markAppRowWithBlockables(nonBlockablePkgs, row, app.packageName); @@ -108,10 +117,8 @@ public class NotificationBackend { if (pkg == null) { continue; } else if (pkg.contains(":")) { - // Interpret as channel; lock only this channel for this app. - if (packageName.equals(pkg.split(":", 2)[0])) { - row.lockedChannelId = pkg.split(":", 2 )[1]; - } + // handled by NotificationChannel.isImportanceLockedByOEM() + continue; } else if (packageName.equals(nonBlockablePkgs[i])) { row.systemApp = row.lockedImportance = true; } @@ -123,8 +130,9 @@ public class NotificationBackend { try { PackageInfo info = context.getPackageManager().getPackageInfo( app.packageName, PackageManager.GET_SIGNATURES); + RoleManager rm = context.getSystemService(RoleManager.class); final AppRow row = new AppRow(); - recordCanBeBlocked(context, context.getPackageManager(), info, row); + recordCanBeBlocked(context, context.getPackageManager(), rm, info, row); return row.systemApp; } catch (PackageManager.NameNotFoundException e) { e.printStackTrace(); @@ -491,7 +499,6 @@ public class NotificationBackend { public boolean first; // first app in section public boolean systemApp; public boolean lockedImportance; - public String lockedChannelId; public boolean showBadge; public boolean allowBubbles; public int userId; diff --git a/src/com/android/settings/notification/NotificationPreferenceController.java b/src/com/android/settings/notification/NotificationPreferenceController.java index 1bfe47ecf96..d09ea4dc3dc 100644 --- a/src/com/android/settings/notification/NotificationPreferenceController.java +++ b/src/com/android/settings/notification/NotificationPreferenceController.java @@ -110,27 +110,13 @@ public abstract class NotificationPreferenceController extends AbstractPreferenc } } - private boolean isChannelConfigurable() { - if (mAppRow != null && mAppRow.lockedImportance) { - return false; - } - if (mChannel != null && mAppRow != null) { - return !Objects.equals(mChannel.getId(), mAppRow.lockedChannelId); - } - return false; - } - protected boolean isChannelBlockable() { if (mChannel != null && mAppRow != null) { - if (!isChannelConfigurable()) { + if (mChannel.isImportanceLockedByCriticalDeviceFunction() + || mChannel.isImportanceLockedByOEM()) { return mChannel.getImportance() == IMPORTANCE_NONE; } - if (mChannel.isImportanceLockedByOEM() - || mChannel.isImportanceLockedByCriticalDeviceFunction()) { - return false; - } - return mChannel.isBlockableSystem() || !mAppRow.systemApp || mChannel.getImportance() == IMPORTANCE_NONE; } diff --git a/src/com/android/settings/notification/NotificationSettingsBase.java b/src/com/android/settings/notification/NotificationSettingsBase.java index 163671a979b..32d8e913f78 100644 --- a/src/com/android/settings/notification/NotificationSettingsBase.java +++ b/src/com/android/settings/notification/NotificationSettingsBase.java @@ -25,6 +25,7 @@ import android.app.Notification; import android.app.NotificationChannel; import android.app.NotificationChannelGroup; import android.app.NotificationManager; +import android.app.role.RoleManager; import android.content.BroadcastReceiver; import android.content.Context; import android.content.Intent; @@ -36,7 +37,6 @@ import android.content.pm.PackageManager.NameNotFoundException; import android.content.pm.ResolveInfo; import android.graphics.BlendMode; import android.graphics.BlendModeColorFilter; -import android.graphics.ColorFilter; import android.graphics.drawable.Drawable; import android.graphics.drawable.GradientDrawable; import android.graphics.drawable.LayerDrawable; @@ -71,6 +71,7 @@ abstract public class NotificationSettingsBase extends DashboardFragment { protected PackageManager mPm; protected NotificationBackend mBackend = new NotificationBackend(); protected NotificationManager mNm; + protected RoleManager mRm; protected Context mContext; protected int mUid; @@ -101,6 +102,7 @@ abstract public class NotificationSettingsBase extends DashboardFragment { mPm = getPackageManager(); mNm = NotificationManager.from(mContext); + mRm = mContext.getSystemService(RoleManager.class); mPkg = mArgs != null && mArgs.containsKey(AppInfoBase.ARG_PACKAGE_NAME) ? mArgs.getString(AppInfoBase.ARG_PACKAGE_NAME) @@ -195,7 +197,7 @@ abstract public class NotificationSettingsBase extends DashboardFragment { } private void loadAppRow() { - mAppRow = mBackend.loadAppRow(mContext, mPm, mPkgInfo); + mAppRow = mBackend.loadAppRow(mContext, mPm, mRm, mPkgInfo); } private void loadChannelGroup() { @@ -342,7 +344,7 @@ abstract public class NotificationSettingsBase extends DashboardFragment { protected boolean isChannelConfigurable(NotificationChannel channel) { if (channel != null && mAppRow != null) { - return !channel.getId().equals(mAppRow.lockedChannelId); + return !channel.isImportanceLockedByOEM(); } return false; } @@ -353,6 +355,14 @@ abstract public class NotificationSettingsBase extends DashboardFragment { return true; } + if (channel.isImportanceLockedByCriticalDeviceFunction()) { + return false; + } + + if (channel.isImportanceLockedByOEM()) { + return false; + } + return channel.isBlockableSystem() || channel.getImportance() == NotificationManager.IMPORTANCE_NONE; } diff --git a/tests/robotests/src/com/android/settings/homepage/contextualcards/slices/NotificationChannelSliceTest.java b/tests/robotests/src/com/android/settings/homepage/contextualcards/slices/NotificationChannelSliceTest.java index 60a6b42d427..335e99f0742 100644 --- a/tests/robotests/src/com/android/settings/homepage/contextualcards/slices/NotificationChannelSliceTest.java +++ b/tests/robotests/src/com/android/settings/homepage/contextualcards/slices/NotificationChannelSliceTest.java @@ -30,6 +30,7 @@ import static org.robolectric.Shadows.shadowOf; import android.app.NotificationChannel; import android.app.NotificationChannelGroup; +import android.app.role.RoleManager; import android.content.Context; import android.content.pm.ApplicationInfo; import android.content.pm.PackageInfo; @@ -345,7 +346,7 @@ public class NotificationChannelSliceTest { doReturn(buildNotificationChannelGroups(channels)).when(mNotificationBackend).getGroups( any(String.class), any(int.class)); doReturn(appRow).when(mNotificationBackend).loadAppRow(any(Context.class), - any(PackageManager.class), any(PackageInfo.class)); + any(PackageManager.class), any(RoleManager.class), any(PackageInfo.class)); doReturn(channelCount).when(mNotificationBackend).getChannelCount( any(String.class), any(int.class)); } diff --git a/tests/robotests/src/com/android/settings/homepage/contextualcards/slices/NotificationMultiChannelAppRowTest.java b/tests/robotests/src/com/android/settings/homepage/contextualcards/slices/NotificationMultiChannelAppRowTest.java index d722af67a1d..c6222f1d23a 100644 --- a/tests/robotests/src/com/android/settings/homepage/contextualcards/slices/NotificationMultiChannelAppRowTest.java +++ b/tests/robotests/src/com/android/settings/homepage/contextualcards/slices/NotificationMultiChannelAppRowTest.java @@ -21,6 +21,7 @@ import static org.mockito.Mockito.doReturn; import static org.mockito.Mockito.never; import static org.mockito.Mockito.verify; +import android.app.role.RoleManager; import android.content.Context; import android.content.pm.ApplicationInfo; import android.content.pm.PackageInfo; @@ -65,7 +66,7 @@ public class NotificationMultiChannelAppRowTest { mNotificationMultiChannelAppRow.call(); verify(mNotificationBackend).loadAppRow(any(Context.class), any(PackageManager.class), - any(PackageInfo.class)); + any(RoleManager.class), any(PackageInfo.class)); } @Test @@ -76,6 +77,6 @@ public class NotificationMultiChannelAppRowTest { mNotificationMultiChannelAppRow.call(); verify(mNotificationBackend, never()).loadAppRow(any(Context.class), - any(PackageManager.class), any(PackageInfo.class)); + any(PackageManager.class), any(RoleManager.class), any(PackageInfo.class)); } } diff --git a/tests/robotests/src/com/android/settings/notification/AllowSoundPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/notification/AllowSoundPreferenceControllerTest.java index 9d2754139fe..f747842d91d 100644 --- a/tests/robotests/src/com/android/settings/notification/AllowSoundPreferenceControllerTest.java +++ b/tests/robotests/src/com/android/settings/notification/AllowSoundPreferenceControllerTest.java @@ -139,12 +139,11 @@ public class AllowSoundPreferenceControllerTest { } @Test - public void testUpdateState_notBlockable() { - String lockedId = "locked"; + public void testUpdateState_notBlockable_oem() { NotificationBackend.AppRow appRow = new NotificationBackend.AppRow(); - appRow.lockedChannelId = lockedId; NotificationChannel channel = mock(NotificationChannel.class); - when(channel.getId()).thenReturn(lockedId); + when(channel.getId()).thenReturn(""); + when(channel.isImportanceLockedByOEM()).thenReturn(true); mController.onResume(appRow, channel, null, null); Preference pref = new RestrictedSwitchPreference(mContext); diff --git a/tests/robotests/src/com/android/settings/notification/BadgePreferenceControllerTest.java b/tests/robotests/src/com/android/settings/notification/BadgePreferenceControllerTest.java index 9ea201a531f..6de55652c77 100644 --- a/tests/robotests/src/com/android/settings/notification/BadgePreferenceControllerTest.java +++ b/tests/robotests/src/com/android/settings/notification/BadgePreferenceControllerTest.java @@ -188,11 +188,10 @@ public class BadgePreferenceControllerTest { @Test public void testUpdateState_channelNotBlockable() { - String lockedId = "locked"; NotificationBackend.AppRow appRow = new NotificationBackend.AppRow(); - appRow.lockedChannelId = lockedId; NotificationChannel channel = mock(NotificationChannel.class); - when(channel.getId()).thenReturn(lockedId); + when(channel.getId()).thenReturn(""); + when(channel.isImportanceLockedByOEM()).thenReturn(true); mController.onResume(appRow, channel, null, null); Preference pref = new RestrictedSwitchPreference(mContext); @@ -204,7 +203,6 @@ public class BadgePreferenceControllerTest { @Test public void testUpdateState_channel() { NotificationBackend.AppRow appRow = new NotificationBackend.AppRow(); - appRow.lockedChannelId = "a"; NotificationChannel channel = mock(NotificationChannel.class); when(channel.canShowBadge()).thenReturn(true); mController.onResume(appRow, channel, null, null); diff --git a/tests/robotests/src/com/android/settings/notification/BlockPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/notification/BlockPreferenceControllerTest.java index bdbf40a35ac..41655fab9cf 100644 --- a/tests/robotests/src/com/android/settings/notification/BlockPreferenceControllerTest.java +++ b/tests/robotests/src/com/android/settings/notification/BlockPreferenceControllerTest.java @@ -101,23 +101,23 @@ public class BlockPreferenceControllerTest { } @Test - public void testIsAvailable_notIfChannelNotBlockable() { + public void testIsAvailable_channelNotBlockable() { NotificationBackend.AppRow appRow = new NotificationBackend.AppRow(); appRow.systemApp = true; NotificationChannel channel = mock(NotificationChannel.class); when(channel.getImportance()).thenReturn(IMPORTANCE_HIGH); mController.onResume(appRow, channel, null, null); - assertFalse(mController.isAvailable()); + assertTrue(mController.isAvailable()); } @Test - public void testIsAvailable_notIfChannelNonDefault() { + public void testIsAvailable_channelNonDefault() { NotificationBackend.AppRow appRow = new NotificationBackend.AppRow(); appRow.systemApp = true; NotificationChannel channel = mock(NotificationChannel.class); when(channel.getImportance()).thenReturn(IMPORTANCE_HIGH); mController.onResume(appRow, channel, null, null); - assertFalse(mController.isAvailable()); + assertTrue(mController.isAvailable()); } @Test @@ -131,19 +131,19 @@ public class BlockPreferenceControllerTest { } @Test - public void testIsAvailable_notIfGroupNotBlockable() { + public void testIsAvailable_GroupNotBlockable() { NotificationBackend.AppRow appRow = new NotificationBackend.AppRow(); appRow.systemApp = true; mController.onResume(appRow, null, mock(NotificationChannelGroup.class), null); - assertFalse(mController.isAvailable()); + assertTrue(mController.isAvailable()); } @Test - public void testIsAvailable_notIfAppNotBlockable() { + public void testIsAvailable_AppNotBlockable() { NotificationBackend.AppRow appRow = new NotificationBackend.AppRow(); appRow.systemApp = true; mController.onResume(appRow, null, null, null); - assertFalse(mController.isAvailable()); + assertTrue(mController.isAvailable()); } @Test @@ -160,13 +160,99 @@ public class BlockPreferenceControllerTest { public void testIsAvailable_nonSystemApp() { NotificationBackend.AppRow appRow = new NotificationBackend.AppRow(); appRow.systemApp = false; - appRow.lockedChannelId = "not this"; NotificationChannel channel = mock(NotificationChannel.class); when(channel.getImportance()).thenReturn(IMPORTANCE_HIGH); mController.onResume(appRow, channel, null, null); assertTrue(mController.isAvailable()); } + @Test + public void testIsEnabled_lockedApp() { + NotificationBackend.AppRow appRow = new NotificationBackend.AppRow(); + appRow.lockedImportance = true; + appRow.systemApp = true; + mController.onResume(appRow, null, null, null); + mController.updateState(mPreference); + assertFalse(mSwitch.isEnabled()); + } + + @Test + public void testIsEnabled_GroupNotBlockable() { + NotificationBackend.AppRow appRow = new NotificationBackend.AppRow(); + appRow.systemApp = true; + mController.onResume(appRow, null, mock(NotificationChannelGroup.class), null); + mController.updateState(mPreference); + assertFalse(mSwitch.isEnabled()); + } + + @Test + public void testIsEnabled_systemAppNotBlockable() { + NotificationBackend.AppRow appRow = new NotificationBackend.AppRow(); + appRow.systemApp = true; + mController.onResume(appRow, null, null, null); + mController.updateState(mPreference); + assertFalse(mSwitch.isEnabled()); + } + + @Test + public void testIsEnabled_systemAppBlockable() { + NotificationBackend.AppRow appRow = new NotificationBackend.AppRow(); + appRow.systemApp = true; + NotificationChannel channel = new NotificationChannel("", "", IMPORTANCE_DEFAULT); + channel.setBlockableSystem(true); + mController.onResume(appRow, channel, null, null); + mController.updateState(mPreference); + assertTrue(mSwitch.isEnabled()); + } + + @Test + public void testIsEnabled_lockedChannel() { + NotificationBackend.AppRow appRow = new NotificationBackend.AppRow(); + NotificationChannel channel = mock(NotificationChannel.class); + when(channel.isImportanceLockedByOEM()).thenReturn(true); + when(channel.getImportance()).thenReturn(IMPORTANCE_HIGH); + mController.onResume(appRow, channel, null, null); + + mController.updateState(mPreference); + + assertFalse(mSwitch.isEnabled()); + } + + @Test + public void testIsEnabled_defaultAppChannel() { + NotificationBackend.AppRow appRow = new NotificationBackend.AppRow(); + NotificationChannel channel = mock(NotificationChannel.class); + when(channel.isImportanceLockedByCriticalDeviceFunction()).thenReturn(true); + when(channel.getImportance()).thenReturn(IMPORTANCE_HIGH); + mController.onResume(appRow, channel, null, null); + + mController.updateState(mPreference); + + assertFalse(mSwitch.isEnabled()); + } + + @Test + public void testIsEnabled_channel() { + NotificationBackend.AppRow appRow = new NotificationBackend.AppRow(); + NotificationChannel channel = mock(NotificationChannel.class); + when(channel.getImportance()).thenReturn(IMPORTANCE_HIGH); + mController.onResume(appRow, channel, null, null); + + mController.updateState(mPreference); + + assertTrue(mSwitch.isEnabled()); + } + + @Test + public void testIsEnabled_app() { + NotificationBackend.AppRow appRow = new NotificationBackend.AppRow(); + mController.onResume(appRow, null, null, null); + + mController.updateState(mPreference); + + assertTrue(mSwitch.isEnabled()); + } + @Test public void testUpdateState_app() { NotificationBackend.AppRow appRow = new NotificationBackend.AppRow(); diff --git a/tests/robotests/src/com/android/settings/notification/BubblePreferenceControllerTest.java b/tests/robotests/src/com/android/settings/notification/BubblePreferenceControllerTest.java index 0d0b4852b58..ea66964b6f5 100644 --- a/tests/robotests/src/com/android/settings/notification/BubblePreferenceControllerTest.java +++ b/tests/robotests/src/com/android/settings/notification/BubblePreferenceControllerTest.java @@ -203,11 +203,9 @@ public class BubblePreferenceControllerTest { @Test public void testUpdateState_channelNotBlockable() { - String lockedId = "locked"; NotificationBackend.AppRow appRow = new NotificationBackend.AppRow(); - appRow.lockedChannelId = lockedId; NotificationChannel channel = mock(NotificationChannel.class); - when(channel.getId()).thenReturn(lockedId); + when(channel.isImportanceLockedByCriticalDeviceFunction()).thenReturn(true); mController.onResume(appRow, channel, null, null); Preference pref = new RestrictedSwitchPreference(mContext); @@ -219,7 +217,6 @@ public class BubblePreferenceControllerTest { @Test public void testUpdateState_channel() { NotificationBackend.AppRow appRow = new NotificationBackend.AppRow(); - appRow.lockedChannelId = "a"; NotificationChannel channel = mock(NotificationChannel.class); when(channel.canBubble()).thenReturn(true); mController.onResume(appRow, channel, null, null); diff --git a/tests/robotests/src/com/android/settings/notification/DndPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/notification/DndPreferenceControllerTest.java index 929c14d7db3..f6636301ece 100644 --- a/tests/robotests/src/com/android/settings/notification/DndPreferenceControllerTest.java +++ b/tests/robotests/src/com/android/settings/notification/DndPreferenceControllerTest.java @@ -111,11 +111,9 @@ public class DndPreferenceControllerTest { @Test public void testUpdateState_notBlockable() { - String lockedId = "locked"; NotificationBackend.AppRow appRow = new NotificationBackend.AppRow(); - appRow.lockedChannelId = lockedId; NotificationChannel channel = mock(NotificationChannel.class); - when(channel.getId()).thenReturn(lockedId); + when(channel.isImportanceLockedByOEM()).thenReturn(true); mController.onResume(appRow, channel, null, null); Preference pref = new RestrictedSwitchPreference(RuntimeEnvironment.application); diff --git a/tests/robotests/src/com/android/settings/notification/HighImportancePreferenceControllerTest.java b/tests/robotests/src/com/android/settings/notification/HighImportancePreferenceControllerTest.java index 6e6dad4c839..a89a826199c 100644 --- a/tests/robotests/src/com/android/settings/notification/HighImportancePreferenceControllerTest.java +++ b/tests/robotests/src/com/android/settings/notification/HighImportancePreferenceControllerTest.java @@ -142,11 +142,9 @@ public class HighImportancePreferenceControllerTest { @Test public void testUpdateState_notConfigurable() { - String lockedId = "locked"; NotificationBackend.AppRow appRow = new NotificationBackend.AppRow(); - appRow.lockedChannelId = lockedId; NotificationChannel channel = mock(NotificationChannel.class); - when(channel.getId()).thenReturn(lockedId); + when(channel.isImportanceLockedByOEM()).thenReturn(true); when(channel.getImportance()).thenReturn(IMPORTANCE_HIGH); mController.onResume(appRow, channel, null, null); @@ -156,6 +154,36 @@ public class HighImportancePreferenceControllerTest { assertFalse(pref.isEnabled()); } + @Test + public void testUpdateState_systemButConfigurable() { + NotificationBackend.AppRow appRow = new NotificationBackend.AppRow(); + appRow.systemApp = true; + NotificationChannel channel = mock(NotificationChannel.class); + when(channel.isImportanceLockedByOEM()).thenReturn(false); + when(channel.getImportance()).thenReturn(IMPORTANCE_HIGH); + mController.onResume(appRow, channel, null, null); + + Preference pref = new RestrictedSwitchPreference(mContext, null); + mController.updateState(pref); + + assertTrue(pref.isEnabled()); + } + + @Test + public void testUpdateState_defaultApp() { + NotificationBackend.AppRow appRow = new NotificationBackend.AppRow(); + appRow.systemApp = true; + NotificationChannel channel = mock(NotificationChannel.class); + when(channel.isImportanceLockedByCriticalDeviceFunction()).thenReturn(true); + when(channel.getImportance()).thenReturn(IMPORTANCE_HIGH); + mController.onResume(appRow, channel, null, null); + + Preference pref = new RestrictedSwitchPreference(mContext, null); + mController.updateState(pref); + + assertTrue(pref.isEnabled()); + } + @Test public void testUpdateState_high() { NotificationBackend.AppRow appRow = new NotificationBackend.AppRow(); diff --git a/tests/robotests/src/com/android/settings/notification/ImportancePreferenceControllerTest.java b/tests/robotests/src/com/android/settings/notification/ImportancePreferenceControllerTest.java index c9f62e98c3b..999631e6629 100644 --- a/tests/robotests/src/com/android/settings/notification/ImportancePreferenceControllerTest.java +++ b/tests/robotests/src/com/android/settings/notification/ImportancePreferenceControllerTest.java @@ -159,11 +159,9 @@ public class ImportancePreferenceControllerTest { @Test public void testUpdateState_notConfigurable() { - String lockedId = "locked"; NotificationBackend.AppRow appRow = new NotificationBackend.AppRow(); - appRow.lockedChannelId = lockedId; NotificationChannel channel = mock(NotificationChannel.class); - when(channel.getId()).thenReturn(lockedId); + when(channel.isImportanceLockedByOEM()).thenReturn(true); when(channel.getImportance()).thenReturn(IMPORTANCE_HIGH); mController.onResume(appRow, channel, null, null); @@ -173,6 +171,36 @@ public class ImportancePreferenceControllerTest { assertFalse(pref.isEnabled()); } + @Test + public void testUpdateState_systemButConfigurable() { + NotificationBackend.AppRow appRow = new NotificationBackend.AppRow(); + appRow.systemApp = true; + NotificationChannel channel = mock(NotificationChannel.class); + when(channel.isImportanceLockedByOEM()).thenReturn(false); + when(channel.getImportance()).thenReturn(IMPORTANCE_HIGH); + mController.onResume(appRow, channel, null, null); + + Preference pref = new ImportancePreference(mContext, null); + mController.updateState(pref); + + assertTrue(pref.isEnabled()); + } + + @Test + public void testUpdateState_defaultApp() { + NotificationBackend.AppRow appRow = new NotificationBackend.AppRow(); + appRow.systemApp = true; + NotificationChannel channel = mock(NotificationChannel.class); + when(channel.isImportanceLockedByCriticalDeviceFunction()).thenReturn(true); + when(channel.getImportance()).thenReturn(IMPORTANCE_HIGH); + mController.onResume(appRow, channel, null, null); + + Preference pref = new ImportancePreference(mContext, null); + mController.updateState(pref); + + assertTrue(pref.isEnabled()); + } + @Test public void testUpdateState() { NotificationBackend.AppRow appRow = new NotificationBackend.AppRow(); diff --git a/tests/robotests/src/com/android/settings/notification/LightsPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/notification/LightsPreferenceControllerTest.java index 3724ddb9c43..ac9cdf1644d 100644 --- a/tests/robotests/src/com/android/settings/notification/LightsPreferenceControllerTest.java +++ b/tests/robotests/src/com/android/settings/notification/LightsPreferenceControllerTest.java @@ -159,11 +159,9 @@ public class LightsPreferenceControllerTest { @Test public void testUpdateState_notBlockable() { - String lockedId = "locked"; NotificationBackend.AppRow appRow = new NotificationBackend.AppRow(); - appRow.lockedChannelId = lockedId; NotificationChannel channel = mock(NotificationChannel.class); - when(channel.getId()).thenReturn(lockedId); + when(channel.isImportanceLockedByOEM()).thenReturn(true); mController.onResume(appRow, channel, null, null); Preference pref = new RestrictedSwitchPreference(mContext); diff --git a/tests/robotests/src/com/android/settings/notification/MinImportancePreferenceControllerTest.java b/tests/robotests/src/com/android/settings/notification/MinImportancePreferenceControllerTest.java index 28058a409ef..b8ef7d12d95 100644 --- a/tests/robotests/src/com/android/settings/notification/MinImportancePreferenceControllerTest.java +++ b/tests/robotests/src/com/android/settings/notification/MinImportancePreferenceControllerTest.java @@ -142,11 +142,9 @@ public class MinImportancePreferenceControllerTest { @Test public void testUpdateState_notConfigurable() { - String lockedId = "locked"; NotificationBackend.AppRow appRow = new NotificationBackend.AppRow(); - appRow.lockedChannelId = lockedId; NotificationChannel channel = mock(NotificationChannel.class); - when(channel.getId()).thenReturn(lockedId); + when(channel.isImportanceLockedByOEM()).thenReturn(true); when(channel.getImportance()).thenReturn(IMPORTANCE_LOW); mController.onResume(appRow, channel, null, null); @@ -156,6 +154,36 @@ public class MinImportancePreferenceControllerTest { assertFalse(pref.isEnabled()); } + @Test + public void testUpdateState_systemButConfigurable() { + NotificationBackend.AppRow appRow = new NotificationBackend.AppRow(); + appRow.systemApp = true; + NotificationChannel channel = mock(NotificationChannel.class); + when(channel.isImportanceLockedByOEM()).thenReturn(false); + when(channel.getImportance()).thenReturn(IMPORTANCE_LOW); + mController.onResume(appRow, channel, null, null); + + Preference pref = new RestrictedSwitchPreference(mContext, null); + mController.updateState(pref); + + assertTrue(pref.isEnabled()); + } + + @Test + public void testUpdateState_defaultApp() { + NotificationBackend.AppRow appRow = new NotificationBackend.AppRow(); + appRow.systemApp = true; + NotificationChannel channel = mock(NotificationChannel.class); + when(channel.isImportanceLockedByCriticalDeviceFunction()).thenReturn(true); + when(channel.getImportance()).thenReturn(IMPORTANCE_LOW); + mController.onResume(appRow, channel, null, null); + + Preference pref = new RestrictedSwitchPreference(mContext, null); + mController.updateState(pref); + + assertTrue(pref.isEnabled()); + } + @Test public void testUpdateState_min() { NotificationBackend.AppRow appRow = new NotificationBackend.AppRow(); diff --git a/tests/robotests/src/com/android/settings/notification/NotificationBackendTest.java b/tests/robotests/src/com/android/settings/notification/NotificationBackendTest.java index 2c2e3791ab8..cb5060914b8 100644 --- a/tests/robotests/src/com/android/settings/notification/NotificationBackendTest.java +++ b/tests/robotests/src/com/android/settings/notification/NotificationBackendTest.java @@ -18,22 +18,28 @@ package com.android.settings.notification; import static com.google.common.truth.Truth.assertThat; -import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertFalse; -import static org.junit.Assert.assertNull; import static org.junit.Assert.assertTrue; +import static org.mockito.ArgumentMatchers.anyString; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.when; +import android.app.role.RoleManager; import android.app.usage.UsageEvents; +import android.content.pm.ApplicationInfo; +import android.content.pm.PackageInfo; +import android.content.pm.PackageManager; import android.os.Parcel; import com.android.settings.notification.NotificationBackend.AppRow; import org.junit.Test; import org.junit.runner.RunWith; +import org.robolectric.RobolectricTestRunner; +import org.robolectric.RuntimeEnvironment; import java.util.ArrayList; import java.util.List; -import org.robolectric.RobolectricTestRunner; @RunWith(RobolectricTestRunner.class) public class NotificationBackendTest { @@ -50,81 +56,40 @@ public class NotificationBackendTest { // This package has a package lock but no locked channels assertTrue(appRow.lockedImportance); - assertNull(appRow.lockedChannelId); } @Test - public void testMarkAppRow_unblockableChannelOrPkg() { - String channelBlockName = "foo.bar.pkgWithChannel"; - String pkgBlockName = "foo.bar.pkgBlock"; - String[] nonBlockablePkgs = new String[2]; - nonBlockablePkgs[0] = pkgBlockName; - nonBlockablePkgs[1] = channelBlockName + ":SpecificChannel"; + public void testMarkAppRow_defaultPackage() { + PackageInfo pi = new PackageInfo(); + pi.packageName = "test"; + pi.applicationInfo = new ApplicationInfo(); + pi.applicationInfo.packageName = "test"; + List roles = new ArrayList<>(); + roles.add(RoleManager.ROLE_DIALER); + RoleManager rm = mock(RoleManager.class); + when(rm.getHeldRolesFromController(anyString())).thenReturn(roles); - // This package has a channel level lock but no full package lock - AppRow channelBlockApp = new AppRow(); - channelBlockApp.pkg = channelBlockName; - NotificationBackend.markAppRowWithBlockables(nonBlockablePkgs, channelBlockApp, - channelBlockName); - assertFalse(channelBlockApp.lockedImportance); - assertEquals("SpecificChannel", channelBlockApp.lockedChannelId); + AppRow appRow = new NotificationBackend().loadAppRow(RuntimeEnvironment.application, + mock(PackageManager.class), rm, pi); - // This other package has the reverse - AppRow pkgBlock = new AppRow(); - pkgBlock.pkg = pkgBlockName; - NotificationBackend.markAppRowWithBlockables(nonBlockablePkgs, pkgBlock, pkgBlockName); - assertTrue(pkgBlock.lockedImportance); - assertNull(pkgBlock.lockedChannelId); - - // This third package has no locks at all - AppRow otherAppRow = new AppRow(); - otherAppRow.pkg ="foo.bar.nothingBlocked"; - NotificationBackend.markAppRowWithBlockables(nonBlockablePkgs, otherAppRow, - "foo.bar.nothingBlocked"); - assertFalse(otherAppRow.lockedImportance); - assertNull(otherAppRow.lockedChannelId); + assertTrue(appRow.systemApp); } @Test - public void testMarkAppRow_unblockableChannelAndPkg() { - AppRow appRow = new AppRow(); - String packageName = "foo.bar.unblockable"; - appRow.pkg = packageName; - String[] nonBlockablePkgs = new String[2]; - nonBlockablePkgs[0] = "foo.bar.unblockable"; - nonBlockablePkgs[1] = "foo.bar.unblockable:SpecificChannel"; - NotificationBackend.markAppRowWithBlockables(nonBlockablePkgs, appRow, packageName); + public void testMarkAppRow_notDefaultPackage() { + PackageInfo pi = new PackageInfo(); + pi.packageName = "test"; + pi.applicationInfo = new ApplicationInfo(); + pi.applicationInfo.packageName = "test"; + List roles = new ArrayList<>(); + roles.add(RoleManager.ROLE_HOME); + RoleManager rm = mock(RoleManager.class); + when(rm.getHeldRolesFromController(anyString())).thenReturn(roles); - // This package has both a channel lock and a package lock - assertTrue(appRow.lockedImportance); - assertEquals("SpecificChannel", appRow.lockedChannelId); - } + AppRow appRow = new NotificationBackend().loadAppRow(RuntimeEnvironment.application, + mock(PackageManager.class), rm, pi); - @Test - public void testMarkAppRow_channelNameWithColons() { - AppRow appRow = new AppRow(); - String packageName = "foo.bar.unblockable"; - String channelName = "SpecificChannel:1234:abc:defg"; - appRow.pkg = packageName; - String[] nonBlockablePkgs = new String[1]; - nonBlockablePkgs[0] = packageName + ":" + channelName; - NotificationBackend.markAppRowWithBlockables(nonBlockablePkgs, appRow, packageName); - - assertEquals(channelName, appRow.lockedChannelId); - } - - @Test - public void testMarkAppRow_blocklistWithNullEntries() { - AppRow appRow = new AppRow(); - String packageName = "foo.bar.unblockable"; - appRow.pkg = packageName; - String[] nonBlockablePkgs = new String[6]; // extra long list with some entries left null - nonBlockablePkgs[2] = "foo.bar.unblockable"; - nonBlockablePkgs[4] = "foo.bar.unblockable:SpecificChannel"; - NotificationBackend.markAppRowWithBlockables(nonBlockablePkgs, appRow, packageName); - - assertTrue(appRow.lockedImportance); - assertEquals("SpecificChannel", appRow.lockedChannelId); + assertFalse(appRow.systemApp); } @Test diff --git a/tests/robotests/src/com/android/settings/notification/NotificationPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/notification/NotificationPreferenceControllerTest.java index a72597b4ba7..cde5b900cf1 100644 --- a/tests/robotests/src/com/android/settings/notification/NotificationPreferenceControllerTest.java +++ b/tests/robotests/src/com/android/settings/notification/NotificationPreferenceControllerTest.java @@ -203,36 +203,29 @@ public class NotificationPreferenceControllerTest { } @Test - public void testIsBlockable_channelLevelWhitelist() { - String sameId = "bananas"; + public void testIsBlockable_oemWhitelist() { NotificationBackend.AppRow appRow = new NotificationBackend.AppRow(); - appRow.lockedChannelId = sameId; NotificationChannel channel = mock(NotificationChannel.class); - when(channel.getId()).thenReturn(sameId); + when(channel.isImportanceLockedByOEM()).thenReturn(true); when(channel.getImportance()).thenReturn(IMPORTANCE_LOW); mController.onResume(appRow, channel, null, null); assertFalse(mController.isChannelBlockable()); - when(channel.getId()).thenReturn("something new"); + when(channel.isImportanceLockedByOEM()).thenReturn(false); mController.onResume(appRow, channel, null, null); assertTrue(mController.isChannelBlockable()); } @Test - public void testIsBlockable_appLevelWhitelist() { + public void testIsBlockable_defaultApp() { NotificationBackend.AppRow appRow = new NotificationBackend.AppRow(); - appRow.lockedChannelId = "something"; - appRow.lockedImportance = true; NotificationChannel channel = mock(NotificationChannel.class); when(channel.getImportance()).thenReturn(IMPORTANCE_LOW); + when(channel.isImportanceLockedByCriticalDeviceFunction()).thenReturn(true); mController.onResume(appRow, channel, null, null); assertFalse(mController.isChannelBlockable()); - - appRow.lockedImportance = false; - mController.onResume(appRow, mock(NotificationChannel.class), null, null); - assertTrue(mController.isChannelBlockable()); } @Test @@ -281,34 +274,6 @@ public class NotificationPreferenceControllerTest { assertTrue(mController.isChannelBlockable()); } - @Test - public void testIsChannelBlockable_notConfigurable() { - String sameId = "apples"; - NotificationBackend.AppRow appRow = new NotificationBackend.AppRow(); - appRow.systemApp = false; - appRow.lockedChannelId = sameId; - NotificationChannel channel = mock(NotificationChannel.class); - when(channel.getId()).thenReturn(sameId); - when(channel.getImportance()).thenReturn(IMPORTANCE_DEFAULT); - - mController.onResume(appRow, channel, null, null); - assertFalse(mController.isChannelBlockable()); - } - - @Test - public void testIsChannelBlockable_notConfigurableButBlocked() { - String sameId = "apples"; - NotificationBackend.AppRow appRow = new NotificationBackend.AppRow(); - appRow.systemApp = false; - appRow.lockedChannelId = sameId; - NotificationChannel channel = mock(NotificationChannel.class); - when(channel.getId()).thenReturn(sameId); - when(channel.getImportance()).thenReturn(IMPORTANCE_NONE); - - mController.onResume(appRow, channel, null, null); - assertTrue(mController.isChannelBlockable()); - } - @Test public void testIsChannelGroupBlockable_nonSystemBlockable() { NotificationBackend.AppRow appRow = new NotificationBackend.AppRow(); diff --git a/tests/robotests/src/com/android/settings/notification/SoundPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/notification/SoundPreferenceControllerTest.java index 1d9836e2af1..f09f63b415a 100644 --- a/tests/robotests/src/com/android/settings/notification/SoundPreferenceControllerTest.java +++ b/tests/robotests/src/com/android/settings/notification/SoundPreferenceControllerTest.java @@ -162,11 +162,9 @@ public class SoundPreferenceControllerTest { @Test public void testUpdateState_notBlockable() { - String lockedId = "locked"; NotificationBackend.AppRow appRow = new NotificationBackend.AppRow(); - appRow.lockedChannelId = lockedId; NotificationChannel channel = mock(NotificationChannel.class); - when(channel.getId()).thenReturn(lockedId); + when(channel.isImportanceLockedByOEM()).thenReturn(true); mController.onResume(appRow, channel, null, null); AttributeSet attributeSet = Robolectric.buildAttributeSet().build(); diff --git a/tests/robotests/src/com/android/settings/notification/VibrationPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/notification/VibrationPreferenceControllerTest.java index adc10f46180..786b713b272 100644 --- a/tests/robotests/src/com/android/settings/notification/VibrationPreferenceControllerTest.java +++ b/tests/robotests/src/com/android/settings/notification/VibrationPreferenceControllerTest.java @@ -141,11 +141,9 @@ public class VibrationPreferenceControllerTest { @Test public void testUpdateState_notBlockable() { - String lockedId = "locked"; NotificationBackend.AppRow appRow = new NotificationBackend.AppRow(); - appRow.lockedChannelId = lockedId; NotificationChannel channel = mock(NotificationChannel.class); - when(channel.getId()).thenReturn(lockedId); + when(channel.isImportanceLockedByOEM()).thenReturn(true); mController.onResume(appRow, channel, null, null); Preference pref = new RestrictedSwitchPreference(RuntimeEnvironment.application); From ec01bff5c4e58788d07d5eadfc97f1d39cc62723 Mon Sep 17 00:00:00 2001 From: Yi-Ling Chuang Date: Mon, 29 Apr 2019 18:16:30 +0800 Subject: [PATCH 07/10] Only shows two suggestion cards at once. Displaying too many cards may overwhelm users, so limit the number of suggestion cards that should be displayed to two. Fixes: 126213965 Test: robotests Change-Id: I17c43746f475b31121c5809e0e8c6cf932efb99d --- .../contextualcards/ContextualCardLoader.java | 51 +++--------- .../ContextualCardLoaderTest.java | 83 +++---------------- 2 files changed, 24 insertions(+), 110 deletions(-) diff --git a/src/com/android/settings/homepage/contextualcards/ContextualCardLoader.java b/src/com/android/settings/homepage/contextualcards/ContextualCardLoader.java index 74ff6134dcf..a50cf41a385 100644 --- a/src/com/android/settings/homepage/contextualcards/ContextualCardLoader.java +++ b/src/com/android/settings/homepage/contextualcards/ContextualCardLoader.java @@ -50,7 +50,7 @@ import java.util.concurrent.TimeoutException; public class ContextualCardLoader extends AsyncLoaderCompat> { @VisibleForTesting - static final int DEFAULT_CARD_COUNT = 4; + static final int DEFAULT_CARD_COUNT = 2; static final int CARD_CONTENT_LOADER_ID = 1; private static final String TAG = "ContextualCardLoader"; @@ -141,42 +141,19 @@ public class ContextualCardLoader extends AsyncLoaderCompat } } - try { - // The maximum cards are four small cards OR - // one large card with two small cards OR - // two large cards - if (visibleCards.size() <= 2 || getNumberOfLargeCard(visibleCards) == 0) { - // four small cards - return visibleCards; - } + if (!CardContentProvider.DELETE_CARD_URI.equals(mNotifyUri)) { + final MetricsFeatureProvider metricsFeatureProvider = + FeatureFactory.getFactory(mContext).getMetricsFeatureProvider(); - if (visibleCards.size() == DEFAULT_CARD_COUNT) { - hiddenCards.add(visibleCards.remove(visibleCards.size() - 1)); - } + metricsFeatureProvider.action(mContext, + SettingsEnums.ACTION_CONTEXTUAL_CARD_SHOW, + ContextualCardLogUtils.buildCardListLog(visibleCards)); - if (getNumberOfLargeCard(visibleCards) == 1) { - // One large card with two small cards - return visibleCards; - } - - hiddenCards.add(visibleCards.remove(visibleCards.size() - 1)); - - // Two large cards - return visibleCards; - } finally { - if (!CardContentProvider.DELETE_CARD_URI.equals(mNotifyUri)) { - final MetricsFeatureProvider metricsFeatureProvider = - FeatureFactory.getFactory(mContext).getMetricsFeatureProvider(); - - metricsFeatureProvider.action(mContext, - SettingsEnums.ACTION_CONTEXTUAL_CARD_SHOW, - ContextualCardLogUtils.buildCardListLog(visibleCards)); - - metricsFeatureProvider.action(mContext, - SettingsEnums.ACTION_CONTEXTUAL_CARD_NOT_SHOW, - ContextualCardLogUtils.buildCardListLog(hiddenCards)); - } + metricsFeatureProvider.action(mContext, + SettingsEnums.ACTION_CONTEXTUAL_CARD_NOT_SHOW, + ContextualCardLogUtils.buildCardListLog(hiddenCards)); } + return visibleCards; } @VisibleForTesting @@ -208,12 +185,6 @@ public class ContextualCardLoader extends AsyncLoaderCompat return cards; } - private int getNumberOfLargeCard(List cards) { - return (int) cards.stream() - .filter(card -> isLargeCard(card)) - .count(); - } - private boolean isLargeCard(ContextualCard card) { return card.getSliceUri().equals(CONTEXTUAL_WIFI_SLICE_URI) || card.getSliceUri().equals(BLUETOOTH_DEVICES_SLICE_URI) diff --git a/tests/robotests/src/com/android/settings/homepage/contextualcards/ContextualCardLoaderTest.java b/tests/robotests/src/com/android/settings/homepage/contextualcards/ContextualCardLoaderTest.java index c2a3aa9cc9e..b7c21b8ae88 100644 --- a/tests/robotests/src/com/android/settings/homepage/contextualcards/ContextualCardLoaderTest.java +++ b/tests/robotests/src/com/android/settings/homepage/contextualcards/ContextualCardLoaderTest.java @@ -60,6 +60,14 @@ public class ContextualCardLoaderTest { mFakeFeatureFactory = FakeFeatureFactory.setupForTest(); } + @Test + public void loadInBackground_legacyMode_shouldReturnNothing() { + assertThat(mContext.getResources().getBoolean(R.bool.config_use_legacy_suggestion)) + .isTrue(); + + assertThat(mContextualCardLoader.loadInBackground()).isEmpty(); + } + @Test public void getDisplayableCards_twoEligibleCards_shouldShowAll() { final List cards = getContextualCardList().stream().limit(2) @@ -72,53 +80,16 @@ public class ContextualCardLoaderTest { } @Test - public void getDisplayableCards_fiveEligibleCardsNoLarge_shouldShowDefaultCardCount() { - final List fiveCards = getContextualCardListWithNoLargeCard(); - doReturn(fiveCards).when(mContextualCardLoader).filterEligibleCards(anyList()); + public void getDisplayableCards_fourEligibleCards_shouldShowDefaultCardCount() { + final List fourCards = getContextualCardList(); + doReturn(fourCards).when(mContextualCardLoader).filterEligibleCards(anyList()); - final List result = mContextualCardLoader.getDisplayableCards( - fiveCards); + final List result = mContextualCardLoader + .getDisplayableCards(fourCards); assertThat(result).hasSize(DEFAULT_CARD_COUNT); } - @Test - public void getDisplayableCards_threeEligibleCardsOneLarge_shouldShowThreeCards() { - final List cards = getContextualCardList().stream().limit(2) - .collect(Collectors.toList()); - cards.add(new ContextualCard.Builder() - .setName("test_gesture") - .setCardType(ContextualCard.CardType.SLICE) - .setSliceUri(Uri.parse( - "content://com.android.settings.test.slices/action/gesture_pick_up")) - .build()); - doReturn(cards).when(mContextualCardLoader).filterEligibleCards(anyList()); - - final List result = mContextualCardLoader.getDisplayableCards(cards); - - assertThat(result).hasSize(3); - } - - @Test - public void getDisplayableCards_threeEligibleCardsTwoLarge_shouldShowTwoCards() { - final List threeCards = getContextualCardList().stream().limit(3) - .collect(Collectors.toList()); - doReturn(threeCards).when(mContextualCardLoader).filterEligibleCards(anyList()); - - final List result = mContextualCardLoader.getDisplayableCards( - threeCards); - - assertThat(result).hasSize(2); - } - - @Test - public void loadInBackground_legacyMode_shouldReturnNothing() { - assertThat(mContext.getResources().getBoolean(R.bool.config_use_legacy_suggestion)) - .isTrue(); - - assertThat(mContextualCardLoader.loadInBackground()).isEmpty(); - } - @Test public void getDisplayableCards_refreshCardUri_shouldLogContextualCardDisplay() { mContextualCardLoader.mNotifyUri = CardContentProvider.REFRESH_CARD_URI; @@ -167,32 +138,4 @@ public class ContextualCardLoaderTest { .build()); return cards; } - - private List getContextualCardListWithNoLargeCard() { - final List cards = new ArrayList<>(); - cards.add(new ContextualCard.Builder() - .setName("test_rotate") - .setCardType(ContextualCard.CardType.SLICE) - .setSliceUri( - Uri.parse("content://com.android.settings.test.slices/action/auto_rotate")) - .build()); - cards.add(new ContextualCard.Builder() - .setName("test_flashlight") - .setCardType(ContextualCard.CardType.SLICE) - .setSliceUri( - Uri.parse("content://com.android.settings.test.slices/action/flashlight")) - .build()); - cards.add(new ContextualCard.Builder() - .setName("test_bt") - .setCardType(ContextualCard.CardType.SLICE) - .setSliceUri(Uri.parse("content://android.settings.test.slices/action/bluetooth")) - .build()); - cards.add(new ContextualCard.Builder() - .setName("test_gesture") - .setCardType(ContextualCard.CardType.SLICE) - .setSliceUri(Uri.parse( - "content://com.android.settings.test.slices/action/gesture_pick_up")) - .build()); - return cards; - } } From 811998f4b9f915689f19197d7b3a946867af13e6 Mon Sep 17 00:00:00 2001 From: Beverly Date: Mon, 29 Apr 2019 08:52:21 -0400 Subject: [PATCH 08/10] Update DND strings - use pull-down shade - "Notification list" updated to "pull-down shade" - DND text messages should be messages Test: manual Fixes: 131434487 Change-Id: I2740a462042867e58f190f4b49e1aa7a8f1cf126 --- res/values/strings.xml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/res/values/strings.xml b/res/values/strings.xml index 2a29f44f38d..ebb2d2c2b24 100644 --- a/res/values/strings.xml +++ b/res/values/strings.xml @@ -7585,7 +7585,7 @@ Don\'t wake for notifications - Hide from notification list + Hide from pull-down shade Never @@ -8380,13 +8380,13 @@ - Allow text messages + Allow messages To be sure allowed messages make sound, check whether your device is set to ring, vibrate, or silent. - For \u2018%1$s\u2019 incoming text messages are blocked. You can adjust settings to allow your friends, family, or other contacts to reach you. + For \u2018%1$s\u2019 incoming messages are blocked. You can adjust settings to allow your friends, family, or other contacts to reach you. SMS, MMS, and messaging apps From 23c07c8727890670394f055f55bade1452038a99 Mon Sep 17 00:00:00 2001 From: Beverly Date: Mon, 29 Apr 2019 09:52:37 -0400 Subject: [PATCH 09/10] Add null check to avoid settings crash Test: manual Fixes: 131580180 Change-Id: I128d1b23ca33c06f049d8fe4ca3e56c5abefae5f --- ...tractZenModeAutomaticRulePreferenceController.java | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/src/com/android/settings/notification/AbstractZenModeAutomaticRulePreferenceController.java b/src/com/android/settings/notification/AbstractZenModeAutomaticRulePreferenceController.java index 58e19165104..f7b32221ea2 100644 --- a/src/com/android/settings/notification/AbstractZenModeAutomaticRulePreferenceController.java +++ b/src/com/android/settings/notification/AbstractZenModeAutomaticRulePreferenceController.java @@ -123,11 +123,14 @@ abstract public class AbstractZenModeAutomaticRulePreferenceController extends return new ComponentName(ci.packageName, ci.name); } // old service backed rule - final String configurationActivity = - ci.metaData.getString(ConditionProviderService.META_DATA_CONFIGURATION_ACTIVITY); - if (configurationActivity != null) { - return ComponentName.unflattenFromString(configurationActivity); + if (ci.metaData != null) { + final String configurationActivity = ci.metaData.getString( + ConditionProviderService.META_DATA_CONFIGURATION_ACTIVITY); + if (configurationActivity != null) { + return ComponentName.unflattenFromString(configurationActivity); + } } + return null; } From aa625bd06ea21399caf68c3d6cbd1d51466c6969 Mon Sep 17 00:00:00 2001 From: Lei Yu Date: Mon, 29 Apr 2019 13:25:24 -0700 Subject: [PATCH 10/10] Fix a crash in battery settings page Regression from ag/7161923, in this case we should use onResume/onPause pair. Also sort the method to fit android lifecycle. Bug: 131615524 Test: RunSettingsRoboTests Change-Id: I299032bfeb119dac293039917c6673dd4c0ef4e0 --- .../settings/fuelgauge/PowerUsageSummary.java | 34 +++++------ .../fuelgauge/PowerUsageSummaryTest.java | 57 ++++++++++++++++--- 2 files changed, 68 insertions(+), 23 deletions(-) diff --git a/src/com/android/settings/fuelgauge/PowerUsageSummary.java b/src/com/android/settings/fuelgauge/PowerUsageSummary.java index 78391f271b1..85a08793b42 100644 --- a/src/com/android/settings/fuelgauge/PowerUsageSummary.java +++ b/src/com/android/settings/fuelgauge/PowerUsageSummary.java @@ -19,6 +19,7 @@ package com.android.settings.fuelgauge; import static com.android.settings.fuelgauge.BatteryBroadcastReceiver.BatteryUpdateType; import android.app.settings.SettingsEnums; +import android.content.ContentResolver; import android.content.Context; import android.database.ContentObserver; import android.net.Uri; @@ -107,7 +108,8 @@ public class PowerUsageSummary extends PowerUsageBase implements OnLongClickList BatteryTipPreferenceController mBatteryTipPreferenceController; private int mStatsType = BatteryStats.STATS_SINCE_CHARGED; - private final ContentObserver mSettingsObserver = new ContentObserver(new Handler()) { + @VisibleForTesting + final ContentObserver mSettingsObserver = new ContentObserver(new Handler()) { @Override public void onChange(boolean selfChange, Uri uri) { restartBatteryInfoLoader(); @@ -201,21 +203,6 @@ public class PowerUsageSummary extends PowerUsageBase implements OnLongClickList } }; - @Override - public void onStop() { - getContentResolver().unregisterContentObserver(mSettingsObserver); - super.onStop(); - } - - @Override - public void onResume() { - super.onResume(); - getContentResolver().registerContentObserver( - Global.getUriFor(Global.BATTERY_ESTIMATES_LAST_UPDATE_TIME), - false, - mSettingsObserver); - } - @Override public void onAttach(Context context) { super.onAttach(context); @@ -251,6 +238,21 @@ public class PowerUsageSummary extends PowerUsageBase implements OnLongClickList updateBatteryTipFlag(icicle); } + @Override + public void onResume() { + super.onResume(); + getContentResolver().registerContentObserver( + Global.getUriFor(Global.BATTERY_ESTIMATES_LAST_UPDATE_TIME), + false, + mSettingsObserver); + } + + @Override + public void onPause() { + getContentResolver().unregisterContentObserver(mSettingsObserver); + super.onPause(); + } + @Override public int getMetricsCategory() { return SettingsEnums.FUELGAUGE_POWER_USAGE_SUMMARY_V2; diff --git a/tests/robotests/src/com/android/settings/fuelgauge/PowerUsageSummaryTest.java b/tests/robotests/src/com/android/settings/fuelgauge/PowerUsageSummaryTest.java index 2ee6d0c9588..2dd0d9be71e 100644 --- a/tests/robotests/src/com/android/settings/fuelgauge/PowerUsageSummaryTest.java +++ b/tests/robotests/src/com/android/settings/fuelgauge/PowerUsageSummaryTest.java @@ -33,16 +33,20 @@ import static org.mockito.Mockito.times; import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; +import android.content.ContentResolver; import android.content.Context; import android.content.Intent; import android.os.Bundle; +import android.provider.Settings; import android.view.Menu; import android.view.MenuInflater; import android.view.MenuItem; import android.view.View; import android.widget.TextView; +import androidx.annotation.VisibleForTesting; import androidx.loader.app.LoaderManager; +import androidx.preference.PreferenceScreen; import com.android.internal.os.BatterySipper; import com.android.internal.os.BatteryStatsHelper; @@ -51,6 +55,7 @@ import com.android.settings.SettingsActivity; import com.android.settings.fuelgauge.batterytip.BatteryTipPreferenceController; import com.android.settings.testutils.FakeFeatureFactory; import com.android.settings.testutils.XmlTestUtils; +import com.android.settingslib.core.instrumentation.VisibilityLoggerMixin; import com.android.settingslib.widget.LayoutPreference; import org.junit.Before; @@ -66,6 +71,7 @@ import org.mockito.stubbing.Answer; import org.robolectric.Robolectric; import org.robolectric.RobolectricTestRunner; import org.robolectric.RuntimeEnvironment; +import org.robolectric.util.ReflectionHelpers; import java.util.ArrayList; import java.util.List; @@ -117,6 +123,14 @@ public class PowerUsageSummaryTest { private MenuItem mAdvancedPageMenu; @Mock private BatteryInfo mBatteryInfo; + @Mock + private ContentResolver mContentResolver; + @Mock + private BatteryBroadcastReceiver mBatteryBroadcastReceiver; + @Mock + private VisibilityLoggerMixin mVisibilityLoggerMixin; + @Mock + private PreferenceScreen mPreferenceScreen; private List mUsageList; private Context mRealContext; @@ -148,7 +162,7 @@ public class PowerUsageSummaryTest { .thenReturn(sAdditionalBatteryInfoIntent); when(mBatteryHelper.getTotalPower()).thenReturn(TOTAL_POWER); when(mBatteryHelper.getStats().computeBatteryRealtime(anyLong(), anyInt())) - .thenReturn(TIME_SINCE_LAST_FULL_CHARGE_US); + .thenReturn(TIME_SINCE_LAST_FULL_CHARGE_US); when(mNormalBatterySipper.getUid()).thenReturn(UID); mNormalBatterySipper.totalPowerMah = POWER_MAH; @@ -176,6 +190,11 @@ public class PowerUsageSummaryTest { mFragment.mScreenUsagePref = mScreenUsagePref; mFragment.mLastFullChargePref = mLastFullChargePref; mFragment.mBatteryUtils = spy(new BatteryUtils(mRealContext)); + ReflectionHelpers.setField(mFragment, "mVisibilityLoggerMixin", mVisibilityLoggerMixin); + ReflectionHelpers.setField(mFragment, "mBatteryBroadcastReceiver", + mBatteryBroadcastReceiver); + doReturn(mPreferenceScreen).when(mFragment).getPreferenceScreen(); + when(mFragment.getContentResolver()).thenReturn(mContentResolver); } @Test @@ -207,10 +226,10 @@ public class PowerUsageSummaryTest { public void nonIndexableKeys_MatchPreferenceKeys() { final Context context = RuntimeEnvironment.application; final List niks = - PowerUsageSummary.SEARCH_INDEX_DATA_PROVIDER.getNonIndexableKeys(context); + PowerUsageSummary.SEARCH_INDEX_DATA_PROVIDER.getNonIndexableKeys(context); final List keys = - XmlTestUtils.getKeysFromPreferenceXml(context, R.xml.power_usage_summary); + XmlTestUtils.getKeysFromPreferenceXml(context, R.xml.power_usage_summary); assertThat(keys).containsAllIn(niks); } @@ -223,25 +242,25 @@ public class PowerUsageSummaryTest { mFragment.restartBatteryTipLoader(); verify(mLoaderManager) - .restartLoader(eq(PowerUsageSummary.BATTERY_TIP_LOADER), eq(Bundle.EMPTY), any()); + .restartLoader(eq(PowerUsageSummary.BATTERY_TIP_LOADER), eq(Bundle.EMPTY), any()); } @Test public void showBothEstimates_summariesAreBothModified() { when(mFeatureFactory.powerUsageFeatureProvider.isEnhancedBatteryPredictionEnabled(any())) - .thenReturn(true); + .thenReturn(true); doAnswer(new Answer() { @Override public Object answer(InvocationOnMock invocation) { return mRealContext.getString( - R.string.power_usage_old_debug, invocation.getArguments()[0]); + R.string.power_usage_old_debug, invocation.getArguments()[0]); } }).when(mFeatureFactory.powerUsageFeatureProvider).getOldEstimateDebugString(any()); doAnswer(new Answer() { @Override public Object answer(InvocationOnMock invocation) { return mRealContext.getString( - R.string.power_usage_enhanced_debug, invocation.getArguments()[0]); + R.string.power_usage_enhanced_debug, invocation.getArguments()[0]); } }).when(mFeatureFactory.powerUsageFeatureProvider).getEnhancedEstimateDebugString(any()); @@ -336,6 +355,24 @@ public class PowerUsageSummaryTest { verify(mFragment).restartBatteryTipLoader(); } + @Test + public void onResume_registerContentObserver() { + mFragment.onResume(); + + verify(mContentResolver).registerContentObserver( + Settings.Global.getUriFor(Settings.Global.BATTERY_ESTIMATES_LAST_UPDATE_TIME), + false, + mFragment.mSettingsObserver); + } + + @Test + public void onPause_unregisterContentObserver() { + mFragment.onPause(); + + verify(mContentResolver).unregisterContentObserver( + mFragment.mSettingsObserver); + } + public static class TestFragment extends PowerUsageSummary { private Context mContext; @@ -348,6 +385,12 @@ public class PowerUsageSummaryTest { return mContext; } + @Override + protected ContentResolver getContentResolver() { + // Override it so we can access this method in test + return super.getContentResolver(); + } + @Override void showBothEstimates() { List fakeBatteryInfo = new ArrayList<>(2);