From e2897aedf582fe491597a609b1991c7798b98e1e Mon Sep 17 00:00:00 2001 From: Julia Reynolds Date: Thu, 19 Apr 2018 10:04:53 -0400 Subject: [PATCH] Fix crash on rotation Load app/channel data early so that any open dialogs can be properly reconstructed. Never call done on an entityheadercontroller with an activity that's not yet started. Test: robotests Change-Id: Ib2b9f8f1985ef038959062204aaceff686f4ebcf Fixes: 74114917 --- AndroidManifest.xml | 1 + res/xml/app_notification_settings.xml | 19 ++++- res/xml/channel_notification_settings.xml | 9 ++- .../notification/AppNotificationSettings.java | 7 +- .../HeaderPreferenceController.java | 23 ++++-- .../NotificationPreferenceController.java | 2 +- .../NotificationSettingsBase.java | 80 +++++++++++++------ 7 files changed, 101 insertions(+), 40 deletions(-) diff --git a/AndroidManifest.xml b/AndroidManifest.xml index e87951b649b..af565d6a02f 100644 --- a/AndroidManifest.xml +++ b/AndroidManifest.xml @@ -2743,6 +2743,7 @@ diff --git a/res/xml/app_notification_settings.xml b/res/xml/app_notification_settings.xml index 2d5dc57ca4f..3ddfac54b2d 100644 --- a/res/xml/app_notification_settings.xml +++ b/res/xml/app_notification_settings.xml @@ -31,15 +31,32 @@ + + + + + + + + + - + () { @Override @@ -106,7 +103,7 @@ public class AppNotificationSettings extends NotificationSettingsBase { @Override protected int getPreferenceScreenResId() { - return R.xml.notification_settings; + return R.xml.app_notification_settings; } @Override diff --git a/src/com/android/settings/notification/HeaderPreferenceController.java b/src/com/android/settings/notification/HeaderPreferenceController.java index d5e289b3173..c6f6a80621f 100644 --- a/src/com/android/settings/notification/HeaderPreferenceController.java +++ b/src/com/android/settings/notification/HeaderPreferenceController.java @@ -18,6 +18,8 @@ package com.android.settings.notification; import static com.android.settings.widget.EntityHeaderController.PREF_KEY_APP_HEADER; +import android.arch.lifecycle.LifecycleObserver; +import android.arch.lifecycle.OnLifecycleEvent; import android.content.Context; import android.support.v14.preference.PreferenceFragment; import android.support.v7.preference.Preference; @@ -30,13 +32,16 @@ import com.android.settings.R; import com.android.settings.applications.LayoutPreference; import com.android.settings.core.PreferenceControllerMixin; import com.android.settings.widget.EntityHeaderController; +import com.android.settingslib.core.lifecycle.Lifecycle; +import com.android.settingslib.core.lifecycle.events.OnStart; import java.util.Objects; public class HeaderPreferenceController extends NotificationPreferenceController - implements PreferenceControllerMixin { + implements PreferenceControllerMixin, LifecycleObserver { private final PreferenceFragment mFragment; + private EntityHeaderController mHeaderController; public HeaderPreferenceController(Context context, PreferenceFragment fragment) { super(context, null); @@ -57,10 +62,9 @@ public class HeaderPreferenceController extends NotificationPreferenceController public void updateState(Preference preference) { if (mAppRow != null && mFragment != null) { LayoutPreference pref = (LayoutPreference) preference; - EntityHeaderController controller = EntityHeaderController - .newInstance(mFragment.getActivity(), mFragment, - pref.findViewById(R.id.entity_header)); - pref = controller.setIcon(mAppRow.icon) + mHeaderController = EntityHeaderController.newInstance( + mFragment.getActivity(), mFragment, pref.findViewById(R.id.entity_header)); + pref = mHeaderController.setIcon(mAppRow.icon) .setLabel(getLabel()) .setSummary(getSummary()) .setPackageName(mAppRow.pkg) @@ -68,7 +72,7 @@ public class HeaderPreferenceController extends NotificationPreferenceController .setButtonActions(EntityHeaderController.ActionType.ACTION_NOTIF_PREFERENCE, EntityHeaderController.ActionType.ACTION_NONE) .setHasAppInfoLink(true) - .done(mFragment.getActivity(), mContext); + .done(null, mContext); pref.findViewById(R.id.entity_header).setVisibility(View.VISIBLE); } } @@ -101,4 +105,11 @@ public class HeaderPreferenceController extends NotificationPreferenceController return ""; } } + + @OnLifecycleEvent(Lifecycle.Event.ON_START) + public void onStart() { + if (mHeaderController != null) { + mHeaderController.styleActionBar(mFragment.getActivity()); + } + } } diff --git a/src/com/android/settings/notification/NotificationPreferenceController.java b/src/com/android/settings/notification/NotificationPreferenceController.java index 1a65351659e..1e477c41fd2 100644 --- a/src/com/android/settings/notification/NotificationPreferenceController.java +++ b/src/com/android/settings/notification/NotificationPreferenceController.java @@ -96,7 +96,7 @@ public abstract class NotificationPreferenceController extends AbstractPreferenc if (preference != null) { mPreference = preference; } - if (this instanceof Preference.OnPreferenceChangeListener) { + if (mPreference != null && this instanceof Preference.OnPreferenceChangeListener) { mPreference.setOnPreferenceChangeListener( (Preference.OnPreferenceChangeListener) this); } diff --git a/src/com/android/settings/notification/NotificationSettingsBase.java b/src/com/android/settings/notification/NotificationSettingsBase.java index 7eb0ba4e503..faf6fb3e1dc 100644 --- a/src/com/android/settings/notification/NotificationSettingsBase.java +++ b/src/com/android/settings/notification/NotificationSettingsBase.java @@ -20,6 +20,7 @@ import static android.app.NotificationManager.IMPORTANCE_LOW; import static android.app.NotificationManager.IMPORTANCE_NONE; import static com.android.settingslib.RestrictedLockUtils.EnforcedAdmin; +import android.app.Activity; import android.app.Notification; import android.app.NotificationChannel; import android.app.NotificationChannelGroup; @@ -81,28 +82,25 @@ abstract public class NotificationSettingsBase extends DashboardFragment { protected List mDynamicPreferences = new ArrayList<>(); protected ImportanceListener mImportanceListener = new ImportanceListener(); + protected Intent mIntent; + protected Bundle mArgs; + @Override - public void onCreate(Bundle savedInstanceState) { - super.onCreate(savedInstanceState); + public void onAttach(Context context) { + super.onAttach(context); mContext = getActivity(); - Intent intent = getActivity().getIntent(); - Bundle args = getArguments(); - if (DEBUG) Log.d(TAG, "onCreate getIntent()=" + intent); - if (intent == null && args == null) { - Log.w(TAG, "No intent"); - toastAndFinish(); - return; - } + mIntent = getActivity().getIntent(); + mArgs = getArguments(); mPm = getPackageManager(); mNm = NotificationManager.from(mContext); - mPkg = args != null && args.containsKey(AppInfoBase.ARG_PACKAGE_NAME) - ? args.getString(AppInfoBase.ARG_PACKAGE_NAME) - : intent.getStringExtra(Settings.EXTRA_APP_PACKAGE); - mUid = args != null && args.containsKey(AppInfoBase.ARG_PACKAGE_UID) - ? args.getInt(AppInfoBase.ARG_PACKAGE_UID) - : intent.getIntExtra(Settings.EXTRA_APP_UID, -1); + mPkg = mArgs != null && mArgs.containsKey(AppInfoBase.ARG_PACKAGE_NAME) + ? mArgs.getString(AppInfoBase.ARG_PACKAGE_NAME) + : mIntent.getStringExtra(Settings.EXTRA_APP_PACKAGE); + mUid = mArgs != null && mArgs.containsKey(AppInfoBase.ARG_PACKAGE_UID) + ? mArgs.getInt(AppInfoBase.ARG_PACKAGE_UID) + : mIntent.getIntExtra(Settings.EXTRA_APP_UID, -1); if (mUid < 0) { try { @@ -113,13 +111,38 @@ abstract public class NotificationSettingsBase extends DashboardFragment { mPkgInfo = findPackageInfo(mPkg, mUid); + mUserId = UserHandle.getUserId(mUid); + mSuspendedAppsAdmin = RestrictedLockUtils.checkIfApplicationIsSuspended( + mContext, mPkg, mUserId); + + loadChannel(); + loadAppRow(); + loadChannelGroup(); + collectConfigActivities(); + + getLifecycle().addObserver(use(HeaderPreferenceController.class)); + + for (NotificationPreferenceController controller : mControllers) { + controller.onResume(mAppRow, mChannel, mChannelGroup, mSuspendedAppsAdmin); + } + } + + @Override + public void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + + if (mIntent == null && mArgs == null) { + Log.w(TAG, "No intent"); + toastAndFinish(); + return; + } + if (mUid < 0 || TextUtils.isEmpty(mPkg) || mPkgInfo == null) { Log.w(TAG, "Missing package or uid or packageinfo"); toastAndFinish(); return; } - mUserId = UserHandle.getUserId(mUid); startListeningToPackageRemove(); } @@ -132,18 +155,26 @@ abstract public class NotificationSettingsBase extends DashboardFragment { @Override public void onResume() { super.onResume(); - if (mUid < 0 || TextUtils.isEmpty(mPkg) || mPkgInfo == null) { + if (mUid < 0 || TextUtils.isEmpty(mPkg) || mPkgInfo == null || mAppRow == null) { Log.w(TAG, "Missing package or uid or packageinfo"); finish(); return; } - mAppRow = mBackend.loadAppRow(mContext, mPm, mPkgInfo); + // Reload app, channel, etc onResume in case they've changed. A little wasteful if we've + // just done onAttach but better than making every preference controller reload all + // the data + loadAppRow(); if (mAppRow == null) { Log.w(TAG, "Can't load package"); finish(); return; } + loadChannel(); + loadChannelGroup(); collectConfigActivities(); + } + + private void loadChannel() { Intent intent = getActivity().getIntent(); String channelId = intent != null ? intent.getStringExtra(Settings.EXTRA_CHANNEL_ID) : null; if (channelId == null && intent != null) { @@ -151,12 +182,13 @@ abstract public class NotificationSettingsBase extends DashboardFragment { channelId = args != null ? args.getString(Settings.EXTRA_CHANNEL_ID) : null; } mChannel = mBackend.getChannel(mPkg, mUid, channelId); + } - NotificationChannelGroup group = null; - - mSuspendedAppsAdmin = RestrictedLockUtils.checkIfApplicationIsSuspended( - mContext, mPkg, mUserId); + private void loadAppRow() { + mAppRow = mBackend.loadAppRow(mContext, mPm, mPkgInfo); + } + private void loadChannelGroup() { mShowLegacyChannelConfig = mBackend.onlyHasDefaultChannel(mAppRow.pkg, mAppRow.uid) || (mChannel != null && NotificationChannel.DEFAULT_CHANNEL_ID.equals(mChannel.getId())); @@ -166,7 +198,7 @@ abstract public class NotificationSettingsBase extends DashboardFragment { mAppRow.pkg, mAppRow.uid, NotificationChannel.DEFAULT_CHANNEL_ID); } if (mChannel != null && !TextUtils.isEmpty(mChannel.getGroup())) { - group = mBackend.getGroup(mPkg, mUid, mChannel.getGroup()); + NotificationChannelGroup group = mBackend.getGroup(mPkg, mUid, mChannel.getGroup()); if (group != null) { mChannelGroup = group; }