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
This commit is contained in:
Julia Reynolds
2018-04-19 10:04:53 -04:00
parent 7f50a0c837
commit e2897aedf5
7 changed files with 101 additions and 40 deletions

View File

@@ -68,10 +68,7 @@ public class AppNotificationSettings extends NotificationSettingsBase {
mDynamicPreferences.clear();
}
if (mShowLegacyChannelConfig) {
addPreferencesFromResource(R.xml.channel_notification_settings);
} else {
addPreferencesFromResource(R.xml.app_notification_settings);
if (!mShowLegacyChannelConfig) {
// Load channel settings
new AsyncTask<Void, Void, Void>() {
@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

View File

@@ -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());
}
}
}

View File

@@ -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);
}

View File

@@ -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<Preference> 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;
}