1 /* 2 * Copyright (C) 2019 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 package com.android.settings.notification; 18 19 import android.content.ComponentName; 20 import android.content.Context; 21 import android.content.Intent; 22 import android.content.pm.PackageManager; 23 import android.content.pm.ResolveInfo; 24 import android.os.UserHandle; 25 import android.os.UserManager; 26 import android.provider.Settings; 27 import android.service.notification.NotificationAssistantService; 28 29 import androidx.fragment.app.Fragment; 30 import androidx.preference.Preference; 31 32 import com.android.settings.R; 33 import com.android.settings.core.TogglePreferenceController; 34 import com.android.settingslib.PrimarySwitchPreference; 35 36 import com.google.common.annotations.VisibleForTesting; 37 38 import java.util.List; 39 40 public class NotificationAssistantPreferenceController extends TogglePreferenceController { 41 private static final String TAG = "NASPreferenceController"; 42 static final String KEY_NAS = "notification_assistant"; 43 44 private static final int AVAILABLE = 1; 45 private final UserManager mUserManager; 46 private final PackageManager mPackageManager; 47 private Fragment mFragment; 48 private int mUserId = UserHandle.myUserId(); 49 50 @VisibleForTesting 51 protected NotificationBackend mNotificationBackend; 52 private ComponentName mDefaultNASComponent; 53 private Intent mNASSettingIntent; 54 NotificationAssistantPreferenceController(Context context)55 public NotificationAssistantPreferenceController(Context context) { 56 super(context, KEY_NAS); 57 mUserManager = UserManager.get(context); 58 mNotificationBackend = new NotificationBackend(); 59 mPackageManager = context.getPackageManager(); 60 getDefaultNASIntent(); 61 } 62 63 64 @Override getAvailabilityStatus()65 public int getAvailabilityStatus() { 66 return AVAILABLE; 67 } 68 69 @Override isChecked()70 public boolean isChecked() { 71 ComponentName acn = mNotificationBackend.getAllowedNotificationAssistant(); 72 return (acn != null && acn.equals(mDefaultNASComponent)); 73 } 74 75 @Override setChecked(boolean isChecked)76 public boolean setChecked(boolean isChecked) { 77 ComponentName cn = isChecked 78 ? mDefaultNASComponent : null; 79 if (isChecked) { 80 if (mFragment == null) { 81 throw new IllegalStateException("No fragment to start activity"); 82 } 83 showDialog(cn); 84 return false; 85 } else { 86 setNotificationAssistantGranted(null); 87 return true; 88 } 89 } 90 91 @Override getSliceHighlightMenuRes()92 public int getSliceHighlightMenuRes() { 93 return R.string.menu_key_notifications; 94 } 95 setNotificationAssistantGranted(ComponentName cn)96 protected void setNotificationAssistantGranted(ComponentName cn) { 97 if (Settings.Secure.getIntForUser(mContext.getContentResolver(), 98 Settings.Secure.NAS_SETTINGS_UPDATED, 0, mUserId) == 0) { 99 mNotificationBackend.setNASMigrationDoneAndResetDefault(mUserId, cn != null); 100 } 101 mNotificationBackend.setNotificationAssistantGranted(cn); 102 } 103 showDialog(ComponentName cn)104 protected void showDialog(ComponentName cn) { 105 NotificationAssistantDialogFragment dialogFragment = 106 NotificationAssistantDialogFragment.newInstance(mFragment, cn); 107 dialogFragment.show(mFragment.getFragmentManager(), TAG); 108 } 109 setFragment(Fragment fragment)110 public void setFragment(Fragment fragment) { 111 mFragment = fragment; 112 } 113 114 @VisibleForTesting setBackend(NotificationBackend backend)115 void setBackend(NotificationBackend backend) { 116 mNotificationBackend = backend; 117 } 118 119 @VisibleForTesting getDefaultNASIntent()120 void getDefaultNASIntent() { 121 mDefaultNASComponent = mNotificationBackend.getDefaultNotificationAssistant(); 122 if (mDefaultNASComponent != null) { 123 mNASSettingIntent = new Intent( 124 NotificationAssistantService.ACTION_NOTIFICATION_ASSISTANT_DETAIL_SETTINGS); 125 mNASSettingIntent.setPackage(mDefaultNASComponent.getPackageName()); 126 mNASSettingIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); 127 } 128 } 129 130 @Override isSliceable()131 public boolean isSliceable() { 132 return (mFragment != null && mFragment instanceof ConfigureNotificationSettings); 133 } 134 isNASSettingActivityAvailable()135 private boolean isNASSettingActivityAvailable() { 136 final List<ResolveInfo> resolved = mPackageManager.queryIntentActivities(mNASSettingIntent, 137 PackageManager.ResolveInfoFlags.of(PackageManager.MATCH_ALL)); 138 return (resolved != null && !resolved.isEmpty()); 139 } 140 141 @Override updateState(Preference preference)142 public void updateState(Preference preference) { 143 super.updateState(preference); 144 if (mDefaultNASComponent == null) { 145 preference.setEnabled(false); 146 ((PrimarySwitchPreference) preference).setSwitchEnabled(false); 147 } else if (isNASSettingActivityAvailable()) { 148 preference.setIntent(mNASSettingIntent); 149 } else { 150 // Cannot find settings activity from the default NAS app 151 preference.setIntent(null); 152 preference.setOnPreferenceClickListener( 153 preference1 -> { 154 onPreferenceChange(preference1, !isChecked()); 155 ((PrimarySwitchPreference) preference1).setChecked(isChecked()); 156 return true; 157 } 158 ); 159 } 160 } 161 } 162