1 /* 2 * Copyright (C) 2015 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.applications; 18 19 import android.app.AlertDialog; 20 import android.content.ComponentName; 21 import android.content.DialogInterface; 22 import android.os.Bundle; 23 import android.os.Handler; 24 import android.provider.Settings; 25 import android.support.v14.preference.SwitchPreference; 26 import android.support.v7.preference.Preference; 27 28 import com.android.internal.app.AssistUtils; 29 import com.android.internal.logging.MetricsProto.MetricsEvent; 30 import com.android.settings.R; 31 import com.android.settings.SettingsPreferenceFragment; 32 import com.android.settings.voice.VoiceInputListPreference; 33 34 /** 35 * Settings screen to manage everything about assist. 36 */ 37 public class ManageAssist extends SettingsPreferenceFragment 38 implements Preference.OnPreferenceChangeListener { 39 40 private static final String KEY_DEFAULT_ASSIST = "default_assist"; 41 private static final String KEY_CONTEXT = "context"; 42 private static final String KEY_SCREENSHOT = "screenshot"; 43 private static final String KEY_VOICE_INPUT = "voice_input_settings"; 44 private static final String KEY_FLASH = "flash"; 45 46 private DefaultAssistPreference mDefaultAssitPref; 47 private SwitchPreference mContextPref; 48 private SwitchPreference mScreenshotPref; 49 private SwitchPreference mFlashPref; 50 private VoiceInputListPreference mVoiceInputPref; 51 private Handler mHandler = new Handler(); 52 53 @Override 54 public void onCreate(Bundle icicle) { 55 super.onCreate(icicle); 56 addPreferencesFromResource(R.xml.manage_assist); 57 58 mDefaultAssitPref = (DefaultAssistPreference) findPreference(KEY_DEFAULT_ASSIST); 59 mDefaultAssitPref.setOnPreferenceChangeListener(this); 60 61 mContextPref = (SwitchPreference) findPreference(KEY_CONTEXT); 62 mContextPref.setChecked(Settings.Secure.getInt(getContentResolver(), 63 Settings.Secure.ASSIST_STRUCTURE_ENABLED, 1) != 0); 64 mContextPref.setOnPreferenceChangeListener(this); 65 66 mScreenshotPref = (SwitchPreference) findPreference(KEY_SCREENSHOT); 67 mScreenshotPref.setOnPreferenceChangeListener(this); 68 69 mFlashPref = (SwitchPreference) findPreference(KEY_FLASH); 70 mFlashPref.setOnPreferenceChangeListener(this); 71 72 mVoiceInputPref = (VoiceInputListPreference) findPreference(KEY_VOICE_INPUT); 73 updateUi(); 74 } 75 76 @Override 77 protected int getMetricsCategory() { 78 return MetricsEvent.APPLICATIONS_MANAGE_ASSIST; 79 } 80 81 @Override 82 public boolean onPreferenceChange(Preference preference, Object newValue) { 83 if (preference == mContextPref) { 84 Settings.Secure.putInt(getContentResolver(), Settings.Secure.ASSIST_STRUCTURE_ENABLED, 85 (boolean) newValue ? 1 : 0); 86 mHandler.post(() -> { 87 guardScreenshotPref(); 88 guardFlashPref(); 89 }); 90 return true; 91 } 92 if (preference == mScreenshotPref) { 93 Settings.Secure.putInt(getContentResolver(), Settings.Secure.ASSIST_SCREENSHOT_ENABLED, 94 (boolean) newValue ? 1 : 0); 95 return true; 96 } 97 if (preference == mFlashPref) { 98 Settings.Secure.putInt(getContentResolver(), Settings.Secure.ASSIST_DISCLOSURE_ENABLED, 99 (boolean) newValue ? 1 : 0); 100 return true; 101 } 102 if (preference == mDefaultAssitPref) { 103 String newAssitPackage = (String)newValue; 104 if (newAssitPackage == null || 105 newAssitPackage.contentEquals(DefaultAssistPreference.ITEM_NONE_VALUE)) { 106 setDefaultAssist(DefaultAssistPreference.ITEM_NONE_VALUE); 107 return false; 108 } 109 110 final String currentPackage = mDefaultAssitPref.getValue(); 111 if (currentPackage == null || !newAssitPackage.contentEquals(currentPackage)) { 112 confirmNewAssist(newAssitPackage); 113 } 114 return false; 115 } 116 return false; 117 } 118 119 private void guardScreenshotPref() { 120 boolean isChecked = mContextPref.isChecked(); 121 boolean screenshotPrefWasSet = Settings.Secure.getInt( 122 getContentResolver(), Settings.Secure.ASSIST_SCREENSHOT_ENABLED, 1) != 0; 123 mScreenshotPref.setEnabled(isChecked); 124 mScreenshotPref.setChecked(isChecked && screenshotPrefWasSet); 125 } 126 127 private void guardFlashPref() { 128 ComponentName assistant = mDefaultAssitPref.getCurrentAssist(); 129 130 boolean isContextChecked = mContextPref.isChecked(); 131 boolean willShowFlash = AssistUtils.shouldDisclose(getContext(), assistant); 132 boolean isSystemAssistant = AssistUtils.isPreinstalledAssistant(getContext(), assistant); 133 134 mFlashPref.setEnabled(isContextChecked && isSystemAssistant); 135 mFlashPref.setChecked(willShowFlash); 136 } 137 138 private void updateUi() { 139 mDefaultAssitPref.refreshAssistApps(); 140 mVoiceInputPref.refreshVoiceInputs(); 141 142 final ComponentName currentAssist = mDefaultAssitPref.getCurrentAssist(); 143 final boolean hasAssistant = currentAssist != null; 144 if (hasAssistant) { 145 getPreferenceScreen().addPreference(mContextPref); 146 getPreferenceScreen().addPreference(mScreenshotPref); 147 } else { 148 getPreferenceScreen().removePreference(mContextPref); 149 getPreferenceScreen().removePreference(mScreenshotPref); 150 getPreferenceScreen().removePreference(mFlashPref); 151 } 152 153 if (hasAssistant && AssistUtils.allowDisablingAssistDisclosure(getContext())) { 154 getPreferenceScreen().addPreference(mFlashPref); 155 } else { 156 getPreferenceScreen().removePreference(mFlashPref); 157 } 158 159 if (isCurrentAssistVoiceService()) { 160 getPreferenceScreen().removePreference(mVoiceInputPref); 161 } else { 162 getPreferenceScreen().addPreference(mVoiceInputPref); 163 mVoiceInputPref.setAssistRestrict(currentAssist); 164 } 165 166 guardScreenshotPref(); 167 guardFlashPref(); 168 } 169 170 private boolean isCurrentAssistVoiceService() { 171 ComponentName currentAssist = mDefaultAssitPref.getCurrentAssist(); 172 ComponentName activeService = mVoiceInputPref.getCurrentService(); 173 return currentAssist == null && activeService == null || 174 currentAssist != null && currentAssist.equals(activeService); 175 } 176 177 private void confirmNewAssist(final String newAssitPackage) { 178 final int selected = mDefaultAssitPref.findIndexOfValue(newAssitPackage); 179 final CharSequence appLabel = mDefaultAssitPref.getEntries()[selected]; 180 181 final String title = getString(R.string.assistant_security_warning_title, appLabel); 182 final String message = getString(R.string.assistant_security_warning, appLabel); 183 184 final DialogInterface.OnClickListener onAgree = new DialogInterface.OnClickListener() { 185 @Override 186 public void onClick(DialogInterface dialog, int which) { 187 setDefaultAssist(newAssitPackage); 188 } 189 }; 190 191 AlertDialog.Builder builder = new AlertDialog.Builder(getContext()); 192 builder.setTitle(title) 193 .setMessage(message) 194 .setCancelable(true) 195 .setPositiveButton(R.string.assistant_security_warning_agree, onAgree) 196 .setNegativeButton(R.string.assistant_security_warning_disagree, null); 197 AlertDialog dialog = builder.create(); 198 dialog.show(); 199 } 200 201 private void setDefaultAssist(String assistPackage) { 202 mDefaultAssitPref.setValue(assistPackage); 203 updateUi(); 204 } 205 } 206