Deprecate AppListPreference and AppListPrefWithSettings
- Convert ManageAssist into DashboardFragment - Convert default assist pref to DefaultAppPickerFragment - Add PreferenceController for each pref - Add tests Bug: 35203386 Test: make RunSettingsRoboTests Change-Id: I0350a06cae7457809fb261e2d8ec99eda80cc50a
This commit is contained in:
@@ -614,7 +614,7 @@
|
||||
<category android:name="android.intent.category.DEFAULT" />
|
||||
</intent-filter>
|
||||
<meta-data android:name="com.android.settings.FRAGMENT_CLASS"
|
||||
android:value="com.android.settings.applications.ManageAssist" />
|
||||
android:value="com.android.settings.applications.assist.ManageAssist" />
|
||||
</activity>
|
||||
|
||||
<activity android:name="Settings$KeyboardLayoutPickerActivity"
|
||||
|
@@ -6959,12 +6959,6 @@
|
||||
<!-- Title for Default Assist settings [CHAR LIMIT=30] -->
|
||||
<string name="default_assist_title">Assist app</string>
|
||||
|
||||
<!-- Summary for No Default Assist settings [CHAR LIMIT=45] -->
|
||||
<string name="default_assist_none">None</string>
|
||||
|
||||
<!-- Title for Choose Assist dialog [CHAR LIMIT=35] -->
|
||||
<string name="choose_assist_title">Choose Assist app</string>
|
||||
|
||||
<!-- [CHAR_LIMIT=45] Title of the security warning dialog for setting an assitant -->
|
||||
<string name="assistant_security_warning_title">
|
||||
Make <xliff:g id="assistant_app_name">%s</xliff:g> your assistant?
|
||||
|
@@ -23,7 +23,7 @@
|
||||
<Preference
|
||||
android:key="assist_and_voice_input"
|
||||
android:title="@string/assist_and_voice_input_title"
|
||||
android:fragment="com.android.settings.applications.ManageAssist"
|
||||
android:fragment="com.android.settings.applications.assist.ManageAssist"
|
||||
android:order="-20"/>
|
||||
|
||||
<Preference
|
||||
|
@@ -19,10 +19,11 @@
|
||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:title="@string/assist_and_voice_input_title">
|
||||
|
||||
<com.android.settings.applications.DefaultAssistPreference
|
||||
<com.android.settings.widget.GearPreference
|
||||
android:key="default_assist"
|
||||
android:title="@string/default_assist_title"
|
||||
android:summary="@string/default_assist_none"/>
|
||||
android:summary="@string/app_list_preference_none"
|
||||
android:fragment="com.android.settings.applications.assist.DefaultAssistPicker"/>
|
||||
|
||||
<Preference
|
||||
android:key="gesture_assist"
|
||||
@@ -36,7 +37,6 @@
|
||||
|
||||
<SwitchPreference
|
||||
android:key="screenshot"
|
||||
android:dependency="context"
|
||||
android:title="@string/assist_access_screenshot_title"
|
||||
android:summary="@string/assist_access_screenshot_summary"/>
|
||||
|
||||
@@ -45,8 +45,9 @@
|
||||
android:title="@string/assist_flash_title"
|
||||
android:summary="@string/assist_flash_summary"/>
|
||||
|
||||
<com.android.settings.voice.VoiceInputListPreference
|
||||
<com.android.settings.widget.GearPreference
|
||||
android:key="voice_input_settings"
|
||||
android:title="@string/voice_input_settings_title"/>
|
||||
android:title="@string/voice_input_settings_title"
|
||||
android:fragment="com.android.settings.applications.assist.DefaultVoiceInputPicker"/>
|
||||
|
||||
</PreferenceScreen>
|
||||
|
@@ -1,356 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2013 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.android.settings;
|
||||
|
||||
import android.app.AlertDialog;
|
||||
import android.app.AppGlobals;
|
||||
import android.content.ComponentName;
|
||||
import android.content.Context;
|
||||
import android.content.DialogInterface;
|
||||
import android.content.pm.ActivityInfo;
|
||||
import android.content.pm.ApplicationInfo;
|
||||
import android.content.pm.PackageManager;
|
||||
import android.content.pm.PackageManager.NameNotFoundException;
|
||||
import android.content.res.TypedArray;
|
||||
import android.graphics.drawable.Drawable;
|
||||
import android.os.Parcel;
|
||||
import android.os.Parcelable;
|
||||
import android.os.RemoteException;
|
||||
import android.os.UserHandle;
|
||||
import android.os.UserManager;
|
||||
import android.text.TextUtils;
|
||||
import android.util.AttributeSet;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.widget.ArrayAdapter;
|
||||
import android.widget.ImageView;
|
||||
import android.widget.ListAdapter;
|
||||
import android.widget.TextView;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* Extends ListPreference to allow us to show the icons for a given list of applications. We do this
|
||||
* because the names of applications are very similar and the user may not be able to determine what
|
||||
* app they are selecting without an icon.
|
||||
*
|
||||
* @deprecated Selecting app from a list should be done in full UI. Use DefaultAppPickerFragment
|
||||
* instead.
|
||||
*/
|
||||
@Deprecated
|
||||
public class AppListPreference extends CustomListPreference {
|
||||
|
||||
public static final String ITEM_NONE_VALUE = "";
|
||||
|
||||
protected final boolean mForWork;
|
||||
protected final int mUserId;
|
||||
|
||||
|
||||
private boolean mSavesState = true;
|
||||
private Drawable[] mEntryDrawables;
|
||||
private boolean mShowItemNone = false;
|
||||
private CharSequence[] mSummaries;
|
||||
private int mSystemAppIndex = -1;
|
||||
|
||||
public class AppArrayAdapter extends ArrayAdapter<CharSequence> {
|
||||
private Drawable[] mImageDrawables = null;
|
||||
private int mSelectedIndex = 0;
|
||||
|
||||
public AppArrayAdapter(Context context, int textViewResourceId,
|
||||
CharSequence[] objects, Drawable[] imageDrawables, int selectedIndex) {
|
||||
super(context, textViewResourceId, objects);
|
||||
mSelectedIndex = selectedIndex;
|
||||
mImageDrawables = imageDrawables;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isEnabled(int position) {
|
||||
return mSummaries == null || mSummaries[position] == null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public View getView(int position, View convertView, ViewGroup parent) {
|
||||
LayoutInflater inflater = LayoutInflater.from(getContext());
|
||||
View view = inflater.inflate(R.layout.app_preference_item, parent, false);
|
||||
TextView textView = (TextView) view.findViewById(android.R.id.title);
|
||||
textView.setText(getItem(position));
|
||||
if (position == mSelectedIndex && position == mSystemAppIndex) {
|
||||
view.findViewById(R.id.system_default_label).setVisibility(View.VISIBLE);
|
||||
} else if (position == mSelectedIndex) {
|
||||
view.findViewById(R.id.default_label).setVisibility(View.VISIBLE);
|
||||
} else if (position == mSystemAppIndex) {
|
||||
view.findViewById(R.id.system_label).setVisibility(View.VISIBLE);
|
||||
}
|
||||
ImageView imageView = (ImageView) view.findViewById(android.R.id.icon);
|
||||
imageView.setImageDrawable(mImageDrawables[position]);
|
||||
// Summaries are describing why a item is disabled, so anything with a summary
|
||||
// is not enabled.
|
||||
boolean enabled = mSummaries == null || mSummaries[position] == null;
|
||||
view.setEnabled(enabled);
|
||||
if (!enabled) {
|
||||
TextView summary = (TextView) view.findViewById(android.R.id.summary);
|
||||
summary.setText(mSummaries[position]);
|
||||
summary.setVisibility(View.VISIBLE);
|
||||
}
|
||||
return view;
|
||||
}
|
||||
}
|
||||
|
||||
public AppListPreference(Context context, AttributeSet attrs, int defStyle, int defAttrs) {
|
||||
super(context, attrs, defStyle, defAttrs);
|
||||
|
||||
TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.WorkPreference, 0, 0);
|
||||
mForWork = a.getBoolean(R.styleable.WorkPreference_forWork, false);
|
||||
final UserHandle managedProfile = Utils.getManagedProfile(UserManager.get(context));
|
||||
mUserId = mForWork && managedProfile != null ? managedProfile.getIdentifier()
|
||||
: UserHandle.myUserId();
|
||||
}
|
||||
|
||||
public AppListPreference(Context context, AttributeSet attrs) {
|
||||
super(context, attrs);
|
||||
|
||||
TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.WorkPreference, 0, 0);
|
||||
mForWork = a.getBoolean(R.styleable.WorkPreference_forWork, false);
|
||||
final UserHandle managedProfile = Utils.getManagedProfile(UserManager.get(context));
|
||||
mUserId = mForWork && managedProfile != null ? managedProfile.getIdentifier()
|
||||
: UserHandle.myUserId();
|
||||
}
|
||||
|
||||
public void setSavesState(boolean savesState) {
|
||||
mSavesState = savesState;
|
||||
}
|
||||
|
||||
public void setShowItemNone(boolean showItemNone) {
|
||||
mShowItemNone = showItemNone;
|
||||
}
|
||||
|
||||
public void setPackageNames(CharSequence[] packageNames, CharSequence defaultPackageName) {
|
||||
setPackageNames(packageNames, defaultPackageName, null);
|
||||
}
|
||||
|
||||
public void setPackageNames(CharSequence[] packageNames, CharSequence defaultPackageName,
|
||||
CharSequence systemPackageName) {
|
||||
// Look up all package names in PackageManager. Skip ones we can't find.
|
||||
PackageManager pm = getContext().getPackageManager();
|
||||
final int entryCount = packageNames.length + (mShowItemNone ? 1 : 0);
|
||||
List<CharSequence> applicationNames = new ArrayList<>(entryCount);
|
||||
List<CharSequence> validatedPackageNames = new ArrayList<>(entryCount);
|
||||
List<Drawable> entryDrawables = new ArrayList<>(entryCount);
|
||||
int selectedIndex = -1;
|
||||
mSystemAppIndex = -1;
|
||||
for (int i = 0; i < packageNames.length; i++) {
|
||||
try {
|
||||
ApplicationInfo appInfo = pm.getApplicationInfoAsUser(packageNames[i].toString(), 0,
|
||||
mUserId);
|
||||
applicationNames.add(appInfo.loadLabel(pm));
|
||||
validatedPackageNames.add(appInfo.packageName);
|
||||
entryDrawables.add(appInfo.loadIcon(pm));
|
||||
if (defaultPackageName != null &&
|
||||
appInfo.packageName.contentEquals(defaultPackageName)) {
|
||||
selectedIndex = i;
|
||||
}
|
||||
if (appInfo.packageName != null && systemPackageName != null &&
|
||||
appInfo.packageName.contentEquals(systemPackageName)) {
|
||||
mSystemAppIndex = i;
|
||||
}
|
||||
} catch (NameNotFoundException e) {
|
||||
// Skip unknown packages.
|
||||
}
|
||||
}
|
||||
|
||||
if (mShowItemNone) {
|
||||
applicationNames.add(
|
||||
getContext().getResources().getText(R.string.app_list_preference_none));
|
||||
validatedPackageNames.add(ITEM_NONE_VALUE);
|
||||
entryDrawables.add(getContext().getDrawable(R.drawable.ic_remove_circle));
|
||||
}
|
||||
|
||||
setEntries(applicationNames.toArray(new CharSequence[applicationNames.size()]));
|
||||
setEntryValues(
|
||||
validatedPackageNames.toArray(new CharSequence[validatedPackageNames.size()]));
|
||||
mEntryDrawables = entryDrawables.toArray(new Drawable[entryDrawables.size()]);
|
||||
|
||||
if (selectedIndex != -1) {
|
||||
setValueIndex(selectedIndex);
|
||||
} else {
|
||||
setValue(null);
|
||||
}
|
||||
}
|
||||
|
||||
public void setComponentNames(ComponentName[] componentNames, ComponentName defaultCN) {
|
||||
setComponentNames(componentNames, defaultCN, null);
|
||||
}
|
||||
|
||||
public void setComponentNames(ComponentName[] componentNames, ComponentName defaultCN,
|
||||
CharSequence[] summaries) {
|
||||
mSummaries = summaries;
|
||||
// Look up all package names in PackageManager. Skip ones we can't find.
|
||||
PackageManager pm = getContext().getPackageManager();
|
||||
final int entryCount = componentNames.length + (mShowItemNone ? 1 : 0);
|
||||
List<CharSequence> applicationNames = new ArrayList<>(entryCount);
|
||||
List<CharSequence> validatedComponentNames = new ArrayList<>(entryCount);
|
||||
List<Drawable> entryDrawables = new ArrayList<>(entryCount);
|
||||
int selectedIndex = -1;
|
||||
for (int i = 0; i < componentNames.length; i++) {
|
||||
try {
|
||||
ActivityInfo activityInfo = AppGlobals.getPackageManager().getActivityInfo(
|
||||
componentNames[i], 0, mUserId);
|
||||
if (activityInfo != null) {
|
||||
applicationNames.add(activityInfo.loadLabel(pm));
|
||||
validatedComponentNames.add(componentNames[i].flattenToString());
|
||||
entryDrawables.add(activityInfo.loadIcon(pm));
|
||||
} else {
|
||||
ApplicationInfo appInfo = pm.getApplicationInfoAsUser(
|
||||
componentNames[i].getPackageName().toString(), 0, mUserId);
|
||||
applicationNames.add(appInfo.loadLabel(pm));
|
||||
validatedComponentNames.add(componentNames[i].flattenToString());
|
||||
entryDrawables.add(appInfo.loadIcon(pm));
|
||||
}
|
||||
if (defaultCN != null && componentNames[i].equals(defaultCN)) {
|
||||
selectedIndex = i;
|
||||
}
|
||||
} catch (RemoteException|NameNotFoundException e) {
|
||||
// Skip unknown packages.
|
||||
}
|
||||
}
|
||||
|
||||
if (mShowItemNone) {
|
||||
applicationNames.add(
|
||||
getContext().getResources().getText(R.string.app_list_preference_none));
|
||||
validatedComponentNames.add(ITEM_NONE_VALUE);
|
||||
entryDrawables.add(getContext().getDrawable(R.drawable.ic_remove_circle));
|
||||
}
|
||||
|
||||
setEntries(applicationNames.toArray(new CharSequence[applicationNames.size()]));
|
||||
setEntryValues(
|
||||
validatedComponentNames.toArray(new CharSequence[validatedComponentNames.size()]));
|
||||
mEntryDrawables = entryDrawables.toArray(new Drawable[entryDrawables.size()]);
|
||||
|
||||
if (selectedIndex != -1) {
|
||||
setValueIndex(selectedIndex);
|
||||
} else {
|
||||
setValue(null);
|
||||
}
|
||||
}
|
||||
|
||||
protected ListAdapter createListAdapter() {
|
||||
final String selectedValue = getValue();
|
||||
final boolean selectedNone = selectedValue == null ||
|
||||
(mShowItemNone && selectedValue.contentEquals(ITEM_NONE_VALUE));
|
||||
int selectedIndex = selectedNone ? -1 : findIndexOfValue(selectedValue);
|
||||
return new AppArrayAdapter(getContext(),
|
||||
R.layout.app_preference_item, getEntries(), mEntryDrawables, selectedIndex);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onPrepareDialogBuilder(AlertDialog.Builder builder,
|
||||
DialogInterface.OnClickListener listener) {
|
||||
builder.setAdapter(createListAdapter(), listener);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Parcelable onSaveInstanceState() {
|
||||
Parcelable superState = super.onSaveInstanceState();
|
||||
if (mSavesState) {
|
||||
return new SavedState(getEntryValues(), getValue(), mSummaries, mShowItemNone, superState);
|
||||
} else {
|
||||
return superState;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onRestoreInstanceState(Parcelable state) {
|
||||
if (mSavesState || state instanceof SavedState) {
|
||||
SavedState savedState = (SavedState) state;
|
||||
mShowItemNone = savedState.showItemNone;
|
||||
setPackageNames(savedState.entryValues, savedState.value);
|
||||
mSummaries = savedState.summaries;
|
||||
super.onRestoreInstanceState(savedState.superState);
|
||||
} else {
|
||||
super.onRestoreInstanceState(state);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets app label as summary if there is only 1 app applicable to this preference.
|
||||
*/
|
||||
protected void setSoleAppLabelAsSummary() {
|
||||
final CharSequence soleLauncherLabel = getSoleAppLabel();
|
||||
if (!TextUtils.isEmpty(soleLauncherLabel)) {
|
||||
setSummary(soleLauncherLabel);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns app label if there is only 1 app applicable to this preference.
|
||||
*/
|
||||
protected CharSequence getSoleAppLabel() {
|
||||
// Intentionally left empty so subclasses can override with necessary logic.
|
||||
return null;
|
||||
}
|
||||
|
||||
private static class SavedState implements Parcelable {
|
||||
|
||||
public final CharSequence[] entryValues;
|
||||
public final CharSequence value;
|
||||
public final boolean showItemNone;
|
||||
public final Parcelable superState;
|
||||
public final CharSequence[] summaries;
|
||||
|
||||
public SavedState(CharSequence[] entryValues, CharSequence value, CharSequence[] summaries,
|
||||
boolean showItemNone, Parcelable superState) {
|
||||
this.entryValues = entryValues;
|
||||
this.value = value;
|
||||
this.showItemNone = showItemNone;
|
||||
this.superState = superState;
|
||||
this.summaries = summaries;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int describeContents() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void writeToParcel(Parcel dest, int flags) {
|
||||
dest.writeCharSequenceArray(entryValues);
|
||||
dest.writeCharSequence(value);
|
||||
dest.writeInt(showItemNone ? 1 : 0);
|
||||
dest.writeParcelable(superState, flags);
|
||||
dest.writeCharSequenceArray(summaries);
|
||||
}
|
||||
|
||||
public static Creator<SavedState> CREATOR = new Creator<SavedState>() {
|
||||
@Override
|
||||
public SavedState createFromParcel(Parcel source) {
|
||||
CharSequence[] entryValues = source.readCharSequenceArray();
|
||||
CharSequence value = source.readCharSequence();
|
||||
boolean showItemNone = source.readInt() != 0;
|
||||
Parcelable superState = source.readParcelable(getClass().getClassLoader());
|
||||
CharSequence[] summaries = source.readCharSequenceArray();
|
||||
return new SavedState(entryValues, value, summaries, showItemNone, superState);
|
||||
}
|
||||
|
||||
@Override
|
||||
public SavedState[] newArray(int size) {
|
||||
return new SavedState[size];
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
@@ -1,61 +0,0 @@
|
||||
package com.android.settings;
|
||||
|
||||
import android.content.ComponentName;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.support.v7.preference.PreferenceViewHolder;
|
||||
import android.util.AttributeSet;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
|
||||
/**
|
||||
* An AppListPreference with optional settings button.
|
||||
*/
|
||||
@Deprecated
|
||||
public class AppListPreferenceWithSettings extends AppListPreference {
|
||||
|
||||
private View mSettingsIcon;
|
||||
private ComponentName mSettingsComponent;
|
||||
|
||||
public AppListPreferenceWithSettings(Context context, AttributeSet attrs) {
|
||||
super(context, attrs);
|
||||
setWidgetLayoutResource(R.layout.preference_widget_settings);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onBindViewHolder(PreferenceViewHolder view) {
|
||||
super.onBindViewHolder(view);
|
||||
|
||||
mSettingsIcon = view.findViewById(R.id.settings_button);
|
||||
mSettingsIcon.setOnClickListener(new View.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(View v) {
|
||||
Intent intent = new Intent(Intent.ACTION_MAIN);
|
||||
intent.setComponent(mSettingsComponent);
|
||||
getContext().startActivity(new Intent(intent));
|
||||
}
|
||||
});
|
||||
|
||||
ViewGroup container = (ViewGroup) mSettingsIcon.getParent();
|
||||
container.setPaddingRelative(0, 0, 0, 0);
|
||||
|
||||
updateSettingsVisibility();
|
||||
}
|
||||
|
||||
private void updateSettingsVisibility() {
|
||||
if (mSettingsIcon == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (mSettingsComponent == null) {
|
||||
mSettingsIcon.setVisibility(View.GONE);
|
||||
} else {
|
||||
mSettingsIcon.setVisibility(View.VISIBLE);
|
||||
}
|
||||
}
|
||||
|
||||
protected void setSettingsComponent(ComponentName settings) {
|
||||
mSettingsComponent = settings;
|
||||
updateSettingsVisibility();
|
||||
}
|
||||
}
|
@@ -1,212 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2015 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License
|
||||
*/
|
||||
|
||||
package com.android.settings.applications;
|
||||
|
||||
import android.app.AlertDialog;
|
||||
import android.content.ComponentName;
|
||||
import android.content.DialogInterface;
|
||||
import android.os.Bundle;
|
||||
import android.os.Handler;
|
||||
import android.provider.Settings;
|
||||
import android.support.v14.preference.SwitchPreference;
|
||||
import android.support.v7.preference.Preference;
|
||||
|
||||
import com.android.internal.app.AssistUtils;
|
||||
import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
|
||||
import com.android.settings.R;
|
||||
import com.android.settings.SettingsPreferenceFragment;
|
||||
import com.android.settings.gestures.AssistGestureFeatureProvider;
|
||||
import com.android.settings.overlay.FeatureFactory;
|
||||
import com.android.settings.voice.VoiceInputListPreference;
|
||||
|
||||
/**
|
||||
* Settings screen to manage everything about assist.
|
||||
*/
|
||||
public class ManageAssist extends SettingsPreferenceFragment
|
||||
implements Preference.OnPreferenceChangeListener {
|
||||
|
||||
private static final String KEY_DEFAULT_ASSIST = "default_assist";
|
||||
private static final String KEY_ASSIST_GESTURE = "gesture_assist";
|
||||
private static final String KEY_CONTEXT = "context";
|
||||
private static final String KEY_SCREENSHOT = "screenshot";
|
||||
private static final String KEY_VOICE_INPUT = "voice_input_settings";
|
||||
private static final String KEY_FLASH = "flash";
|
||||
|
||||
private DefaultAssistPreference mDefaultAssitPref;
|
||||
private SwitchPreference mContextPref;
|
||||
private SwitchPreference mScreenshotPref;
|
||||
private SwitchPreference mFlashPref;
|
||||
private VoiceInputListPreference mVoiceInputPref;
|
||||
private Handler mHandler = new Handler();
|
||||
|
||||
private Preference mAssistGesturePref;
|
||||
private AssistGestureFeatureProvider mAssistGestureFeatureProvider;
|
||||
|
||||
@Override
|
||||
public void onCreate(Bundle icicle) {
|
||||
super.onCreate(icicle);
|
||||
addPreferencesFromResource(R.xml.manage_assist);
|
||||
|
||||
mDefaultAssitPref = (DefaultAssistPreference) findPreference(KEY_DEFAULT_ASSIST);
|
||||
mDefaultAssitPref.setOnPreferenceChangeListener(this);
|
||||
|
||||
mAssistGesturePref = findPreference(KEY_ASSIST_GESTURE);
|
||||
mAssistGestureFeatureProvider =
|
||||
FeatureFactory.getFactory(getContext()).getAssistGestureFeatureProvider();
|
||||
|
||||
mContextPref = (SwitchPreference) findPreference(KEY_CONTEXT);
|
||||
mContextPref.setChecked(Settings.Secure.getInt(getContentResolver(),
|
||||
Settings.Secure.ASSIST_STRUCTURE_ENABLED, 1) != 0);
|
||||
mContextPref.setOnPreferenceChangeListener(this);
|
||||
|
||||
mScreenshotPref = (SwitchPreference) findPreference(KEY_SCREENSHOT);
|
||||
mScreenshotPref.setOnPreferenceChangeListener(this);
|
||||
|
||||
mFlashPref = (SwitchPreference) findPreference(KEY_FLASH);
|
||||
mFlashPref.setOnPreferenceChangeListener(this);
|
||||
mFooterPreferenceMixin.createFooterPreference()
|
||||
.setTitle(R.string.assist_footer);
|
||||
mVoiceInputPref = (VoiceInputListPreference) findPreference(KEY_VOICE_INPUT);
|
||||
updateUi();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getMetricsCategory() {
|
||||
return MetricsEvent.APPLICATIONS_MANAGE_ASSIST;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onPreferenceChange(Preference preference, Object newValue) {
|
||||
if (preference == mContextPref) {
|
||||
Settings.Secure.putInt(getContentResolver(), Settings.Secure.ASSIST_STRUCTURE_ENABLED,
|
||||
(boolean) newValue ? 1 : 0);
|
||||
mHandler.post(() -> {
|
||||
guardFlashPref();
|
||||
});
|
||||
return true;
|
||||
}
|
||||
if (preference == mScreenshotPref) {
|
||||
Settings.Secure.putInt(getContentResolver(), Settings.Secure.ASSIST_SCREENSHOT_ENABLED,
|
||||
(boolean) newValue ? 1 : 0);
|
||||
return true;
|
||||
}
|
||||
if (preference == mFlashPref) {
|
||||
Settings.Secure.putInt(getContentResolver(), Settings.Secure.ASSIST_DISCLOSURE_ENABLED,
|
||||
(boolean) newValue ? 1 : 0);
|
||||
return true;
|
||||
}
|
||||
if (preference == mDefaultAssitPref) {
|
||||
String newAssitPackage = (String)newValue;
|
||||
if (newAssitPackage == null ||
|
||||
newAssitPackage.contentEquals(DefaultAssistPreference.ITEM_NONE_VALUE)) {
|
||||
setDefaultAssist(DefaultAssistPreference.ITEM_NONE_VALUE);
|
||||
return false;
|
||||
}
|
||||
|
||||
final String currentPackage = mDefaultAssitPref.getValue();
|
||||
if (currentPackage == null || !newAssitPackage.contentEquals(currentPackage)) {
|
||||
confirmNewAssist(newAssitPackage);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
private void guardFlashPref() {
|
||||
ComponentName assistant = mDefaultAssitPref.getCurrentAssist();
|
||||
|
||||
boolean isContextChecked = mContextPref.isChecked();
|
||||
boolean willShowFlash = AssistUtils.shouldDisclose(getContext(), assistant);
|
||||
boolean isSystemAssistant = AssistUtils.isPreinstalledAssistant(getContext(), assistant);
|
||||
|
||||
mFlashPref.setEnabled(isContextChecked && isSystemAssistant);
|
||||
mFlashPref.setChecked(willShowFlash);
|
||||
}
|
||||
|
||||
private void updateUi() {
|
||||
mDefaultAssitPref.refreshAssistApps();
|
||||
mVoiceInputPref.refreshVoiceInputs();
|
||||
|
||||
final ComponentName currentAssist = mDefaultAssitPref.getCurrentAssist();
|
||||
final boolean hasAssistant = currentAssist != null;
|
||||
if (hasAssistant) {
|
||||
getPreferenceScreen().addPreference(mContextPref);
|
||||
getPreferenceScreen().addPreference(mScreenshotPref);
|
||||
} else {
|
||||
getPreferenceScreen().removePreference(mContextPref);
|
||||
getPreferenceScreen().removePreference(mScreenshotPref);
|
||||
getPreferenceScreen().removePreference(mFlashPref);
|
||||
}
|
||||
|
||||
if (hasAssistant && mAssistGestureFeatureProvider.isSupported(getContext())) {
|
||||
getPreferenceScreen().addPreference(mAssistGesturePref);
|
||||
} else {
|
||||
getPreferenceScreen().removePreference(mAssistGesturePref);
|
||||
}
|
||||
|
||||
if (hasAssistant && AssistUtils.allowDisablingAssistDisclosure(getContext())) {
|
||||
getPreferenceScreen().addPreference(mFlashPref);
|
||||
} else {
|
||||
getPreferenceScreen().removePreference(mFlashPref);
|
||||
}
|
||||
|
||||
if (isCurrentAssistVoiceService()) {
|
||||
getPreferenceScreen().removePreference(mVoiceInputPref);
|
||||
} else {
|
||||
getPreferenceScreen().addPreference(mVoiceInputPref);
|
||||
mVoiceInputPref.setAssistRestrict(currentAssist);
|
||||
}
|
||||
|
||||
guardFlashPref();
|
||||
}
|
||||
|
||||
private boolean isCurrentAssistVoiceService() {
|
||||
ComponentName currentAssist = mDefaultAssitPref.getCurrentAssist();
|
||||
ComponentName activeService = mVoiceInputPref.getCurrentService();
|
||||
return currentAssist == null && activeService == null ||
|
||||
currentAssist != null && currentAssist.equals(activeService);
|
||||
}
|
||||
|
||||
private void confirmNewAssist(final String newAssitPackage) {
|
||||
final int selected = mDefaultAssitPref.findIndexOfValue(newAssitPackage);
|
||||
final CharSequence appLabel = mDefaultAssitPref.getEntries()[selected];
|
||||
|
||||
final String title = getString(R.string.assistant_security_warning_title, appLabel);
|
||||
final String message = getString(R.string.assistant_security_warning, appLabel);
|
||||
|
||||
final DialogInterface.OnClickListener onAgree = new DialogInterface.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(DialogInterface dialog, int which) {
|
||||
setDefaultAssist(newAssitPackage);
|
||||
}
|
||||
};
|
||||
|
||||
AlertDialog.Builder builder = new AlertDialog.Builder(getContext());
|
||||
builder.setTitle(title)
|
||||
.setMessage(message)
|
||||
.setCancelable(true)
|
||||
.setPositiveButton(R.string.assistant_security_warning_agree, onAgree)
|
||||
.setNegativeButton(R.string.assistant_security_warning_disagree, null);
|
||||
AlertDialog dialog = builder.create();
|
||||
dialog.show();
|
||||
}
|
||||
|
||||
private void setDefaultAssist(String assistPackage) {
|
||||
mDefaultAssitPref.setValue(assistPackage);
|
||||
updateUi();
|
||||
}
|
||||
}
|
@@ -0,0 +1,136 @@
|
||||
/*
|
||||
* Copyright (C) 2017 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.android.settings.applications.assist;
|
||||
|
||||
import android.content.Context;
|
||||
import android.net.Uri;
|
||||
import android.os.UserHandle;
|
||||
import android.provider.Settings;
|
||||
import android.support.v7.preference.Preference;
|
||||
import android.support.v7.preference.PreferenceScreen;
|
||||
import android.support.v7.preference.TwoStatePreference;
|
||||
|
||||
import com.android.internal.app.AssistUtils;
|
||||
import com.android.settings.core.PreferenceController;
|
||||
import com.android.settings.core.lifecycle.Lifecycle;
|
||||
import com.android.settings.core.lifecycle.LifecycleObserver;
|
||||
import com.android.settings.core.lifecycle.events.OnPause;
|
||||
import com.android.settings.core.lifecycle.events.OnResume;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
|
||||
public class AssistContextPreferenceController extends PreferenceController
|
||||
implements Preference.OnPreferenceChangeListener, LifecycleObserver, OnResume, OnPause {
|
||||
|
||||
private static final String KEY_CONTEXT = "context";
|
||||
|
||||
private final AssistUtils mAssistUtils;
|
||||
private final SettingObserver mSettingObserver;
|
||||
|
||||
private Preference mPreference;
|
||||
private PreferenceScreen mScreen;
|
||||
|
||||
public AssistContextPreferenceController(Context context, Lifecycle lifecycle) {
|
||||
super(context);
|
||||
mAssistUtils = new AssistUtils(context);
|
||||
mSettingObserver = new SettingObserver();
|
||||
|
||||
if (lifecycle != null) {
|
||||
lifecycle.addObserver(this);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isAvailable() {
|
||||
return mAssistUtils.getAssistComponentForUser(UserHandle.myUserId()) != null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getPreferenceKey() {
|
||||
return KEY_CONTEXT;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void displayPreference(PreferenceScreen screen) {
|
||||
mScreen = screen;
|
||||
mPreference = screen.findPreference(getPreferenceKey());
|
||||
super.displayPreference(screen);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onResume() {
|
||||
mSettingObserver.register(mContext.getContentResolver(), true);
|
||||
updatePreference();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void updateState(Preference preference) {
|
||||
updatePreference();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onPause() {
|
||||
mSettingObserver.register(mContext.getContentResolver(), false);
|
||||
}
|
||||
|
||||
|
||||
private void updatePreference() {
|
||||
if (mPreference == null || !(mPreference instanceof TwoStatePreference)) {
|
||||
return;
|
||||
}
|
||||
if (isAvailable()) {
|
||||
if (mScreen.findPreference(getPreferenceKey()) == null) {
|
||||
// add it if it's not on scree
|
||||
mScreen.addPreference(mPreference);
|
||||
}
|
||||
} else {
|
||||
mScreen.removePreference(mPreference);
|
||||
}
|
||||
|
||||
((TwoStatePreference) mPreference).setChecked(isChecked(mContext));
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onPreferenceChange(Preference preference, Object newValue) {
|
||||
Settings.Secure.putInt(mContext.getContentResolver(),
|
||||
Settings.Secure.ASSIST_STRUCTURE_ENABLED,
|
||||
(boolean) newValue ? 1 : 0);
|
||||
return true;
|
||||
}
|
||||
|
||||
static boolean isChecked(Context context) {
|
||||
return Settings.Secure.getInt(context.getContentResolver(),
|
||||
Settings.Secure.ASSIST_STRUCTURE_ENABLED, 1) != 0;
|
||||
}
|
||||
|
||||
class SettingObserver extends AssistSettingObserver {
|
||||
|
||||
private final Uri URI =
|
||||
Settings.Secure.getUriFor(Settings.Secure.ASSIST_STRUCTURE_ENABLED);
|
||||
|
||||
@Override
|
||||
protected List<Uri> getSettingUris() {
|
||||
return Arrays.asList(URI);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onSettingChange() {
|
||||
updatePreference();
|
||||
}
|
||||
}
|
||||
}
|
@@ -0,0 +1,158 @@
|
||||
/*
|
||||
* Copyright (C) 2017 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.android.settings.applications.assist;
|
||||
|
||||
import android.content.ComponentName;
|
||||
import android.content.Context;
|
||||
import android.net.Uri;
|
||||
import android.os.UserHandle;
|
||||
import android.provider.Settings;
|
||||
import android.support.v7.preference.Preference;
|
||||
import android.support.v7.preference.PreferenceScreen;
|
||||
import android.support.v7.preference.TwoStatePreference;
|
||||
|
||||
import com.android.internal.annotations.VisibleForTesting;
|
||||
import com.android.internal.app.AssistUtils;
|
||||
import com.android.settings.core.PreferenceController;
|
||||
import com.android.settings.core.lifecycle.Lifecycle;
|
||||
import com.android.settings.core.lifecycle.LifecycleObserver;
|
||||
import com.android.settings.core.lifecycle.events.OnPause;
|
||||
import com.android.settings.core.lifecycle.events.OnResume;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
|
||||
public class AssistFlashScreenPreferenceController extends PreferenceController
|
||||
implements Preference.OnPreferenceChangeListener, LifecycleObserver, OnResume, OnPause {
|
||||
|
||||
private static final String KEY_FLASH = "flash";
|
||||
|
||||
private final AssistUtils mAssistUtils;
|
||||
private final SettingObserver mSettingObserver;
|
||||
private PreferenceScreen mScreen;
|
||||
private Preference mPreference;
|
||||
|
||||
public AssistFlashScreenPreferenceController(Context context, Lifecycle lifecycle) {
|
||||
super(context);
|
||||
mAssistUtils = new AssistUtils(context);
|
||||
mSettingObserver = new SettingObserver();
|
||||
|
||||
if (lifecycle != null) {
|
||||
lifecycle.addObserver(this);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isAvailable() {
|
||||
return getCurrentAssist() != null && allowDisablingAssistDisclosure();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getPreferenceKey() {
|
||||
return KEY_FLASH;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void displayPreference(PreferenceScreen screen) {
|
||||
mScreen = screen;
|
||||
mPreference = screen.findPreference(getPreferenceKey());
|
||||
super.displayPreference(screen);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onResume() {
|
||||
mSettingObserver.register(mContext.getContentResolver(), true);
|
||||
updatePreference();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void updateState(Preference preference) {
|
||||
updatePreference();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onPause() {
|
||||
mSettingObserver.register(mContext.getContentResolver(), false);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onPreferenceChange(Preference preference, Object newValue) {
|
||||
Settings.Secure.putInt(mContext.getContentResolver(),
|
||||
Settings.Secure.ASSIST_DISCLOSURE_ENABLED,
|
||||
(boolean) newValue ? 1 : 0);
|
||||
return true;
|
||||
}
|
||||
|
||||
private void updatePreference() {
|
||||
if (mPreference == null || !(mPreference instanceof TwoStatePreference)) {
|
||||
return;
|
||||
}
|
||||
if (isAvailable()) {
|
||||
if (mScreen.findPreference(getPreferenceKey()) == null) {
|
||||
// add it if it's not on scree
|
||||
mScreen.addPreference(mPreference);
|
||||
}
|
||||
} else {
|
||||
mScreen.removePreference(mPreference);
|
||||
}
|
||||
ComponentName assistant = getCurrentAssist();
|
||||
|
||||
boolean isContextChecked = AssistContextPreferenceController.isChecked(mContext);
|
||||
|
||||
mPreference.setEnabled(isContextChecked && isPreInstalledAssistant(assistant));
|
||||
((TwoStatePreference) mPreference).setChecked(willShowFlash(assistant));
|
||||
}
|
||||
|
||||
@VisibleForTesting
|
||||
boolean willShowFlash(ComponentName assistant) {
|
||||
return AssistUtils.shouldDisclose(mContext, assistant);
|
||||
}
|
||||
|
||||
@VisibleForTesting
|
||||
boolean isPreInstalledAssistant(ComponentName assistant) {
|
||||
return AssistUtils.isPreinstalledAssistant(mContext, assistant);
|
||||
}
|
||||
|
||||
@VisibleForTesting
|
||||
boolean allowDisablingAssistDisclosure() {
|
||||
return AssistUtils.allowDisablingAssistDisclosure(mContext);
|
||||
}
|
||||
|
||||
private ComponentName getCurrentAssist() {
|
||||
return mAssistUtils.getAssistComponentForUser(UserHandle.myUserId());
|
||||
}
|
||||
|
||||
class SettingObserver extends AssistSettingObserver {
|
||||
|
||||
private final Uri URI =
|
||||
Settings.Secure.getUriFor(Settings.Secure.ASSIST_DISCLOSURE_ENABLED);
|
||||
private final Uri CONTEXT_URI =
|
||||
Settings.Secure.getUriFor(Settings.Secure.ASSIST_STRUCTURE_ENABLED);
|
||||
|
||||
@Override
|
||||
protected List<Uri> getSettingUris() {
|
||||
return Arrays.asList(URI, CONTEXT_URI);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onSettingChange() {
|
||||
updatePreference();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
@@ -0,0 +1,135 @@
|
||||
/*
|
||||
* Copyright (C) 2017 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.android.settings.applications.assist;
|
||||
|
||||
import android.content.Context;
|
||||
import android.net.Uri;
|
||||
import android.os.UserHandle;
|
||||
import android.provider.Settings;
|
||||
import android.support.v7.preference.Preference;
|
||||
import android.support.v7.preference.PreferenceScreen;
|
||||
import android.support.v7.preference.TwoStatePreference;
|
||||
|
||||
import com.android.internal.app.AssistUtils;
|
||||
import com.android.settings.core.PreferenceController;
|
||||
import com.android.settings.core.lifecycle.Lifecycle;
|
||||
import com.android.settings.core.lifecycle.LifecycleObserver;
|
||||
import com.android.settings.core.lifecycle.events.OnPause;
|
||||
import com.android.settings.core.lifecycle.events.OnResume;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
|
||||
public class AssistScreenshotPreferenceController extends PreferenceController
|
||||
implements Preference.OnPreferenceChangeListener, LifecycleObserver, OnResume, OnPause {
|
||||
|
||||
private static final String KEY_SCREENSHOT = "screenshot";
|
||||
|
||||
private final AssistUtils mAssistUtils;
|
||||
private final SettingObserver mSettingObserver;
|
||||
|
||||
private PreferenceScreen mScreen;
|
||||
private Preference mPreference;
|
||||
|
||||
public AssistScreenshotPreferenceController(Context context, Lifecycle lifecycle) {
|
||||
super(context);
|
||||
mAssistUtils = new AssistUtils(context);
|
||||
mSettingObserver = new SettingObserver();
|
||||
if (lifecycle != null) {
|
||||
lifecycle.addObserver(this);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isAvailable() {
|
||||
return mAssistUtils.getAssistComponentForUser(UserHandle.myUserId()) != null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void displayPreference(PreferenceScreen screen) {
|
||||
mScreen = screen;
|
||||
mPreference = screen.findPreference(getPreferenceKey());
|
||||
super.displayPreference(screen);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getPreferenceKey() {
|
||||
return KEY_SCREENSHOT;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onResume() {
|
||||
mSettingObserver.register(mContext.getContentResolver(), true);
|
||||
updatePreference();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void updateState(Preference preference) {
|
||||
updatePreference();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onPause() {
|
||||
mSettingObserver.register(mContext.getContentResolver(), false);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onPreferenceChange(Preference preference, Object newValue) {
|
||||
Settings.Secure.putInt(mContext.getContentResolver(),
|
||||
Settings.Secure.ASSIST_SCREENSHOT_ENABLED,
|
||||
(boolean) newValue ? 1 : 0);
|
||||
return true;
|
||||
}
|
||||
|
||||
private void updatePreference() {
|
||||
if (mPreference == null || !(mPreference instanceof TwoStatePreference)) {
|
||||
return;
|
||||
}
|
||||
if (isAvailable()) {
|
||||
if (mScreen.findPreference(getPreferenceKey()) == null) {
|
||||
// add it if it's not on scree
|
||||
mScreen.addPreference(mPreference);
|
||||
}
|
||||
} else {
|
||||
mScreen.removePreference(mPreference);
|
||||
}
|
||||
final boolean checked = Settings.Secure.getInt(mContext.getContentResolver(),
|
||||
Settings.Secure.ASSIST_SCREENSHOT_ENABLED, 1) != 0;
|
||||
((TwoStatePreference) mPreference).setChecked(checked);
|
||||
final boolean contextChecked = Settings.Secure.getInt(mContext.getContentResolver(),
|
||||
Settings.Secure.ASSIST_STRUCTURE_ENABLED, 1) != 0;
|
||||
mPreference.setEnabled(contextChecked);
|
||||
}
|
||||
|
||||
class SettingObserver extends AssistSettingObserver {
|
||||
|
||||
private final Uri URI =
|
||||
Settings.Secure.getUriFor(Settings.Secure.ASSIST_SCREENSHOT_ENABLED);
|
||||
private final Uri CONTEXT_URI =
|
||||
Settings.Secure.getUriFor(Settings.Secure.ASSIST_STRUCTURE_ENABLED);
|
||||
|
||||
@Override
|
||||
protected List<Uri> getSettingUris() {
|
||||
return Arrays.asList(URI, CONTEXT_URI);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onSettingChange() {
|
||||
updatePreference();
|
||||
}
|
||||
}
|
||||
}
|
@@ -0,0 +1,65 @@
|
||||
/*
|
||||
* Copyright (C) 2017 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.android.settings.applications.assist;
|
||||
|
||||
import android.content.ContentResolver;
|
||||
import android.database.ContentObserver;
|
||||
import android.net.Uri;
|
||||
import android.os.Handler;
|
||||
import android.provider.Settings;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
public abstract class AssistSettingObserver extends ContentObserver {
|
||||
|
||||
private final Uri ASSIST_URI =
|
||||
Settings.Secure.getUriFor(Settings.Secure.ASSISTANT);
|
||||
|
||||
public AssistSettingObserver() {
|
||||
super(new Handler());
|
||||
}
|
||||
|
||||
public void register(ContentResolver cr, boolean register) {
|
||||
if (register) {
|
||||
cr.registerContentObserver(ASSIST_URI, false, this);
|
||||
final List<Uri> settingUri = getSettingUris();
|
||||
if (settingUri != null) {
|
||||
for (Uri uri : settingUri)
|
||||
cr.registerContentObserver(uri, false, this);
|
||||
}
|
||||
} else {
|
||||
cr.unregisterContentObserver(this);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onChange(boolean selfChange, Uri uri) {
|
||||
super.onChange(selfChange, uri);
|
||||
boolean shouldUpdatePreference = false;
|
||||
final List<Uri> settingUri = getSettingUris();
|
||||
if (ASSIST_URI.equals(uri) || (settingUri != null && settingUri.contains(uri))) {
|
||||
shouldUpdatePreference = true;
|
||||
}
|
||||
if (shouldUpdatePreference) {
|
||||
onSettingChange();
|
||||
}
|
||||
}
|
||||
|
||||
protected abstract List<Uri> getSettingUris();
|
||||
|
||||
public abstract void onSettingChange();
|
||||
}
|
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (C) 2015 The Android Open Source Project
|
||||
* Copyright (C) 2017 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -11,49 +11,105 @@
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.android.settings.applications;
|
||||
package com.android.settings.applications.assist;
|
||||
|
||||
import android.content.ComponentName;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.content.pm.PackageManager;
|
||||
import android.content.pm.ResolveInfo;
|
||||
import android.os.UserHandle;
|
||||
import android.provider.Settings;
|
||||
import android.service.voice.VoiceInteractionService;
|
||||
import android.service.voice.VoiceInteractionServiceInfo;
|
||||
import android.speech.RecognitionService;
|
||||
import android.util.AttributeSet;
|
||||
import android.text.TextUtils;
|
||||
import android.util.Log;
|
||||
|
||||
import com.android.internal.app.AssistUtils;
|
||||
import com.android.settings.AppListPreferenceWithSettings;
|
||||
import com.android.internal.logging.nano.MetricsProto;
|
||||
import com.android.settings.R;
|
||||
import com.android.settings.applications.defaultapps.DefaultAppInfo;
|
||||
import com.android.settings.applications.defaultapps.DefaultAppPickerFragment;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
public class DefaultAssistPreference extends AppListPreferenceWithSettings {
|
||||
|
||||
private static final String TAG = DefaultAssistPreference.class.getSimpleName();
|
||||
public class DefaultAssistPicker extends DefaultAppPickerFragment {
|
||||
|
||||
private static final String TAG = "DefaultAssistPicker";
|
||||
private static final Intent ASSIST_SERVICE_PROBE =
|
||||
new Intent(VoiceInteractionService.SERVICE_INTERFACE);
|
||||
private static final Intent ASSIST_ACTIVITY_PROBE =
|
||||
new Intent(Intent.ACTION_ASSIST);
|
||||
private final List<Info> mAvailableAssistants = new ArrayList<>();
|
||||
|
||||
private final AssistUtils mAssistUtils;
|
||||
private AssistUtils mAssistUtils;
|
||||
|
||||
public DefaultAssistPreference(Context context, AttributeSet attrs) {
|
||||
super(context, attrs);
|
||||
setShowItemNone(true);
|
||||
setDialogTitle(R.string.choose_assist_title);
|
||||
@Override
|
||||
public int getMetricsCategory() {
|
||||
return MetricsProto.MetricsEvent.DEFAULT_ASSIST_PICKER;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean shouldShowItemNone() {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onAttach(Context context) {
|
||||
super.onAttach(context);
|
||||
mAssistUtils = new AssistUtils(context);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean persistString(String value) {
|
||||
final Info info = findAssistantByPackageName(value);
|
||||
protected List<DefaultAppInfo> getCandidates() {
|
||||
mAvailableAssistants.clear();
|
||||
addAssistServices();
|
||||
addAssistActivities();
|
||||
|
||||
final List<String> packages = new ArrayList<>();
|
||||
final List<DefaultAppInfo> candidates = new ArrayList<>();
|
||||
for (Info info : mAvailableAssistants) {
|
||||
final String packageName = info.component.getPackageName();
|
||||
if (packages.contains(packageName)) {
|
||||
// A service appears before an activity thus overrides it if from the same package.
|
||||
continue;
|
||||
}
|
||||
packages.add(packageName);
|
||||
candidates.add(new DefaultAppInfo(mUserId, info.component));
|
||||
}
|
||||
return candidates;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected String getDefaultAppKey() {
|
||||
final ComponentName cn = getCurrentAssist();
|
||||
if (cn != null) {
|
||||
return new DefaultAppInfo(mUserId, cn).getKey();
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected String getConfirmationMessage(DefaultAppInfo appInfo) {
|
||||
if (appInfo == null) {
|
||||
return null;
|
||||
}
|
||||
return getContext().getString(R.string.assistant_security_warning,
|
||||
appInfo.loadLabel(mPm.getPackageManager()));
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean setDefaultAppKey(String key) {
|
||||
if (TextUtils.isEmpty(key)) {
|
||||
setAssistNone();
|
||||
return true;
|
||||
}
|
||||
ComponentName cn = ComponentName.unflattenFromString(key);
|
||||
final Info info = findAssistantByPackageName(cn.getPackageName());
|
||||
if (info == null) {
|
||||
setAssistNone();
|
||||
return true;
|
||||
@@ -67,20 +123,60 @@ public class DefaultAssistPreference extends AppListPreferenceWithSettings {
|
||||
return true;
|
||||
}
|
||||
|
||||
public ComponentName getCurrentAssist() {
|
||||
return mAssistUtils.getAssistComponentForUser(mUserId);
|
||||
}
|
||||
|
||||
private void addAssistServices() {
|
||||
final PackageManager pm = mPm.getPackageManager();
|
||||
final List<ResolveInfo> services = pm.queryIntentServices(
|
||||
ASSIST_SERVICE_PROBE, PackageManager.GET_META_DATA);
|
||||
for (ResolveInfo resolveInfo : services) {
|
||||
VoiceInteractionServiceInfo voiceInteractionServiceInfo =
|
||||
new VoiceInteractionServiceInfo(pm, resolveInfo.serviceInfo);
|
||||
if (!voiceInteractionServiceInfo.getSupportsAssist()) {
|
||||
continue;
|
||||
}
|
||||
|
||||
mAvailableAssistants.add(new Info(
|
||||
new ComponentName(resolveInfo.serviceInfo.packageName,
|
||||
resolveInfo.serviceInfo.name),
|
||||
voiceInteractionServiceInfo));
|
||||
}
|
||||
}
|
||||
|
||||
private void addAssistActivities() {
|
||||
final PackageManager pm = mPm.getPackageManager();
|
||||
final List<ResolveInfo> activities = pm.queryIntentActivities(
|
||||
ASSIST_ACTIVITY_PROBE, PackageManager.MATCH_DEFAULT_ONLY);
|
||||
for (ResolveInfo resolveInfo : activities) {
|
||||
mAvailableAssistants.add(new Info(
|
||||
new ComponentName(resolveInfo.activityInfo.packageName,
|
||||
resolveInfo.activityInfo.name)));
|
||||
}
|
||||
}
|
||||
|
||||
private Info findAssistantByPackageName(String packageName) {
|
||||
for (Info info : mAvailableAssistants) {
|
||||
if (TextUtils.equals(info.component.getPackageName(), packageName)) {
|
||||
return info;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
private void setAssistNone() {
|
||||
Settings.Secure.putString(getContext().getContentResolver(),
|
||||
Settings.Secure.ASSISTANT, ITEM_NONE_VALUE);
|
||||
Settings.Secure.ASSISTANT, "");
|
||||
Settings.Secure.putString(getContext().getContentResolver(),
|
||||
Settings.Secure.VOICE_INTERACTION_SERVICE, "");
|
||||
Settings.Secure.putString(getContext().getContentResolver(),
|
||||
Settings.Secure.VOICE_RECOGNITION_SERVICE, getDefaultRecognizer());
|
||||
|
||||
setSummary(getContext().getText(R.string.default_assist_none));
|
||||
setSettingsComponent(null);
|
||||
}
|
||||
|
||||
private void setAssistService(Info serviceInfo) {
|
||||
final String serviceComponentName = serviceInfo.component.flattenToShortString();
|
||||
final String serviceComponentName = serviceInfo.component.
|
||||
flattenToShortString();
|
||||
final String serviceRecognizerName = new ComponentName(
|
||||
serviceInfo.component.getPackageName(),
|
||||
serviceInfo.voiceInteractionServiceInfo.getRecognitionService())
|
||||
@@ -92,13 +188,6 @@ public class DefaultAssistPreference extends AppListPreferenceWithSettings {
|
||||
Settings.Secure.VOICE_INTERACTION_SERVICE, serviceComponentName);
|
||||
Settings.Secure.putString(getContext().getContentResolver(),
|
||||
Settings.Secure.VOICE_RECOGNITION_SERVICE, serviceRecognizerName);
|
||||
|
||||
setSummary(getEntry());
|
||||
final String settingsActivity =
|
||||
serviceInfo.voiceInteractionServiceInfo.getSettingsActivity();
|
||||
setSettingsComponent(settingsActivity == null ?
|
||||
null :
|
||||
new ComponentName(serviceInfo.component.getPackageName(), settingsActivity));
|
||||
}
|
||||
|
||||
private void setAssistActivity(Info activityInfo) {
|
||||
@@ -108,13 +197,10 @@ public class DefaultAssistPreference extends AppListPreferenceWithSettings {
|
||||
Settings.Secure.VOICE_INTERACTION_SERVICE, "");
|
||||
Settings.Secure.putString(getContext().getContentResolver(),
|
||||
Settings.Secure.VOICE_RECOGNITION_SERVICE, getDefaultRecognizer());
|
||||
|
||||
setSummary(getEntry());
|
||||
setSettingsComponent(null);
|
||||
}
|
||||
|
||||
private String getDefaultRecognizer() {
|
||||
ResolveInfo resolveInfo = getContext().getPackageManager().resolveService(
|
||||
final ResolveInfo resolveInfo = mPm.getPackageManager().resolveService(
|
||||
new Intent(RecognitionService.SERVICE_INTERFACE),
|
||||
PackageManager.GET_META_DATA);
|
||||
if (resolveInfo == null || resolveInfo.serviceInfo == null) {
|
||||
@@ -126,76 +212,7 @@ public class DefaultAssistPreference extends AppListPreferenceWithSettings {
|
||||
resolveInfo.serviceInfo.name).flattenToShortString();
|
||||
}
|
||||
|
||||
private Info findAssistantByPackageName(String packageName) {
|
||||
for (int i = 0; i < mAvailableAssistants.size(); ++i) {
|
||||
Info info = mAvailableAssistants.get(i);
|
||||
if (info.component.getPackageName().equals(packageName)) {
|
||||
return info;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
private void addAssistServices() {
|
||||
PackageManager pm = getContext().getPackageManager();
|
||||
|
||||
List<ResolveInfo> services = pm.queryIntentServices(
|
||||
new Intent(VoiceInteractionService.SERVICE_INTERFACE),
|
||||
PackageManager.GET_META_DATA);
|
||||
for (int i = 0; i < services.size(); ++i) {
|
||||
ResolveInfo resolveInfo = services.get(i);
|
||||
VoiceInteractionServiceInfo voiceInteractionServiceInfo =
|
||||
new VoiceInteractionServiceInfo(pm, resolveInfo.serviceInfo);
|
||||
if (!voiceInteractionServiceInfo.getSupportsAssist()) {
|
||||
continue;
|
||||
}
|
||||
|
||||
mAvailableAssistants.add(new Info(
|
||||
new ComponentName(resolveInfo.serviceInfo.packageName,
|
||||
resolveInfo.serviceInfo.name),
|
||||
voiceInteractionServiceInfo));
|
||||
}
|
||||
}
|
||||
|
||||
private void addAssistActivities() {
|
||||
PackageManager pm = getContext().getPackageManager();
|
||||
|
||||
List<ResolveInfo> activities = pm.queryIntentActivities(
|
||||
new Intent(Intent.ACTION_ASSIST),
|
||||
PackageManager.MATCH_DEFAULT_ONLY);
|
||||
for (int i = 0; i < activities.size(); ++i) {
|
||||
ResolveInfo resolveInfo = activities.get(i);
|
||||
mAvailableAssistants.add(new Info(
|
||||
new ComponentName(resolveInfo.activityInfo.packageName,
|
||||
resolveInfo.activityInfo.name)));
|
||||
}
|
||||
}
|
||||
|
||||
public ComponentName getCurrentAssist() {
|
||||
return mAssistUtils.getAssistComponentForUser(UserHandle.myUserId());
|
||||
}
|
||||
|
||||
public void refreshAssistApps() {
|
||||
mAvailableAssistants.clear();
|
||||
addAssistServices();
|
||||
addAssistActivities();
|
||||
|
||||
List<String> packages = new ArrayList<>();
|
||||
for (int i = 0; i < mAvailableAssistants.size(); ++i) {
|
||||
String packageName = mAvailableAssistants.get(i).component.getPackageName();
|
||||
if (packages.contains(packageName)) {
|
||||
// A service appears before an activity thus overrides it if from the same package.
|
||||
continue;
|
||||
}
|
||||
packages.add(packageName);
|
||||
}
|
||||
|
||||
ComponentName currentAssist = getCurrentAssist();
|
||||
setPackageNames(packages.toArray(new String[packages.size()]),
|
||||
currentAssist == null ? null : currentAssist.getPackageName());
|
||||
}
|
||||
|
||||
private static class Info {
|
||||
static class Info {
|
||||
public final ComponentName component;
|
||||
public final VoiceInteractionServiceInfo voiceInteractionServiceInfo;
|
||||
|
@@ -0,0 +1,88 @@
|
||||
/*
|
||||
* Copyright (C) 2017 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.android.settings.applications.assist;
|
||||
|
||||
import android.content.ComponentName;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.content.pm.PackageManager;
|
||||
import android.content.pm.ResolveInfo;
|
||||
import android.service.voice.VoiceInteractionService;
|
||||
import android.service.voice.VoiceInteractionServiceInfo;
|
||||
|
||||
import com.android.internal.app.AssistUtils;
|
||||
import com.android.settings.applications.defaultapps.DefaultAppInfo;
|
||||
import com.android.settings.applications.defaultapps.DefaultAppPreferenceController;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
public class DefaultAssistPreferenceController extends DefaultAppPreferenceController {
|
||||
|
||||
private static final String KEY_DEFAULT_ASSIST = "default_assist";
|
||||
|
||||
private AssistUtils mAssistUtils;
|
||||
|
||||
public DefaultAssistPreferenceController(Context context) {
|
||||
super(context);
|
||||
mAssistUtils = new AssistUtils(context);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Intent getSettingIntent(DefaultAppInfo info) {
|
||||
final ComponentName cn = mAssistUtils.getAssistComponentForUser(mUserId);
|
||||
if (cn == null) {
|
||||
return null;
|
||||
}
|
||||
final Intent probe = new Intent(VoiceInteractionService.SERVICE_INTERFACE)
|
||||
.setPackage(cn.getPackageName());
|
||||
|
||||
final PackageManager pm = mPackageManager.getPackageManager();
|
||||
final List<ResolveInfo> services = pm.queryIntentServices(probe, PackageManager
|
||||
.GET_META_DATA);
|
||||
if (services == null || services.isEmpty()) {
|
||||
return null;
|
||||
}
|
||||
final ResolveInfo resolveInfo = services.get(0);
|
||||
final VoiceInteractionServiceInfo voiceInfo =
|
||||
new VoiceInteractionServiceInfo(pm, resolveInfo.serviceInfo);
|
||||
if (!voiceInfo.getSupportsAssist()) {
|
||||
return null;
|
||||
}
|
||||
final String activity = voiceInfo.getSettingsActivity();
|
||||
return new Intent(Intent.ACTION_MAIN)
|
||||
.setComponent(new ComponentName(cn.getPackageName(), activity));
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isAvailable() {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getPreferenceKey() {
|
||||
return KEY_DEFAULT_ASSIST;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected DefaultAppInfo getDefaultAppInfo() {
|
||||
final ComponentName cn = mAssistUtils.getAssistComponentForUser(mUserId);
|
||||
if (cn == null) {
|
||||
return null;
|
||||
}
|
||||
return new DefaultAppInfo(mUserId, cn);
|
||||
}
|
||||
}
|
@@ -0,0 +1,162 @@
|
||||
/*
|
||||
* Copyright (C) 2017 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.android.settings.applications.assist;
|
||||
|
||||
import android.content.ComponentName;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.content.pm.PackageManager;
|
||||
import android.provider.Settings;
|
||||
import android.text.TextUtils;
|
||||
|
||||
import com.android.internal.app.AssistUtils;
|
||||
import com.android.internal.logging.nano.MetricsProto;
|
||||
import com.android.settings.applications.defaultapps.DefaultAppInfo;
|
||||
import com.android.settings.applications.defaultapps.DefaultAppPickerFragment;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
public class DefaultVoiceInputPicker extends DefaultAppPickerFragment {
|
||||
|
||||
private VoiceInputHelper mHelper;
|
||||
private AssistUtils mAssistUtils;
|
||||
private String mAssistRestrict;
|
||||
|
||||
@Override
|
||||
public int getMetricsCategory() {
|
||||
return MetricsProto.MetricsEvent.DEFAULT_VOICE_INPUT_PICKER;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onAttach(Context context) {
|
||||
super.onAttach(context);
|
||||
mAssistUtils = new AssistUtils(context);
|
||||
mHelper = new VoiceInputHelper(context);
|
||||
mHelper.buildUi();
|
||||
final ComponentName assist = getCurrentAssist();
|
||||
if (isCurrentAssistVoiceService(assist, getCurrentService(mHelper))) {
|
||||
mAssistRestrict = assist.flattenToShortString();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected List<VoiceInputDefaultAppInfo> getCandidates() {
|
||||
final List<VoiceInputDefaultAppInfo> candidates = new ArrayList<>();
|
||||
boolean hasEnabled = true;
|
||||
for (VoiceInputHelper.InteractionInfo info : mHelper.mAvailableInteractionInfos) {
|
||||
final boolean enabled = TextUtils.equals(info.key, mAssistRestrict);
|
||||
hasEnabled |= enabled;
|
||||
candidates.add(new VoiceInputDefaultAppInfo(mUserId, info, enabled));
|
||||
}
|
||||
|
||||
final boolean assistIsService = !hasEnabled;
|
||||
for (VoiceInputHelper.RecognizerInfo info : mHelper.mAvailableRecognizerInfos) {
|
||||
final boolean enabled = !assistIsService;
|
||||
candidates.add(new VoiceInputDefaultAppInfo(mUserId, info, enabled));
|
||||
}
|
||||
return candidates;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected String getDefaultAppKey() {
|
||||
final ComponentName currentService = getCurrentService(mHelper);
|
||||
if (currentService == null) {
|
||||
return null;
|
||||
}
|
||||
return currentService.flattenToShortString();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean setDefaultAppKey(String value) {
|
||||
for (VoiceInputHelper.InteractionInfo info : mHelper.mAvailableInteractionInfos) {
|
||||
if (TextUtils.equals(value, info.key)) {
|
||||
Settings.Secure.putString(getContext().getContentResolver(),
|
||||
Settings.Secure.VOICE_INTERACTION_SERVICE, value);
|
||||
Settings.Secure.putString(getContext().getContentResolver(),
|
||||
Settings.Secure.VOICE_RECOGNITION_SERVICE,
|
||||
new ComponentName(info.service.packageName,
|
||||
info.serviceInfo.getRecognitionService())
|
||||
.flattenToShortString());
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
for (VoiceInputHelper.RecognizerInfo info : mHelper.mAvailableRecognizerInfos) {
|
||||
if (TextUtils.equals(value, info.key)) {
|
||||
Settings.Secure.putString(getContext().getContentResolver(),
|
||||
Settings.Secure.VOICE_INTERACTION_SERVICE, "");
|
||||
Settings.Secure.putString(getContext().getContentResolver(),
|
||||
Settings.Secure.VOICE_RECOGNITION_SERVICE, value);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
public static ComponentName getCurrentService(VoiceInputHelper helper) {
|
||||
if (helper.mCurrentVoiceInteraction != null) {
|
||||
return helper.mCurrentVoiceInteraction;
|
||||
} else if (helper.mCurrentRecognizer != null) {
|
||||
return helper.mCurrentRecognizer;
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
private ComponentName getCurrentAssist() {
|
||||
return mAssistUtils.getAssistComponentForUser(mUserId);
|
||||
}
|
||||
|
||||
public static boolean isCurrentAssistVoiceService(ComponentName currentAssist,
|
||||
ComponentName currentVoiceService) {
|
||||
return currentAssist == null && currentVoiceService == null ||
|
||||
currentAssist != null && currentAssist.equals(currentVoiceService);
|
||||
}
|
||||
|
||||
public static class VoiceInputDefaultAppInfo extends DefaultAppInfo {
|
||||
|
||||
public VoiceInputHelper.BaseInfo mInfo;
|
||||
|
||||
public VoiceInputDefaultAppInfo(int userId, VoiceInputHelper.BaseInfo info,
|
||||
boolean enabled) {
|
||||
super(userId, info.componentName, null /* summary */, enabled);
|
||||
mInfo = info;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getKey() {
|
||||
return mInfo.key;
|
||||
}
|
||||
|
||||
@Override
|
||||
public CharSequence loadLabel(PackageManager pm) {
|
||||
if (mInfo instanceof VoiceInputHelper.InteractionInfo) {
|
||||
return mInfo.appLabel;
|
||||
} else {
|
||||
return mInfo.label;
|
||||
}
|
||||
}
|
||||
|
||||
public Intent getSettingIntent() {
|
||||
if (mInfo.settings == null) {
|
||||
return null;
|
||||
}
|
||||
return new Intent(Intent.ACTION_MAIN).setComponent(mInfo.settings);
|
||||
}
|
||||
}
|
||||
}
|
@@ -0,0 +1,165 @@
|
||||
/*
|
||||
* Copyright (C) 2017 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.android.settings.applications.assist;
|
||||
|
||||
import android.content.ComponentName;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.net.Uri;
|
||||
import android.support.v7.preference.Preference;
|
||||
import android.support.v7.preference.PreferenceScreen;
|
||||
import android.text.TextUtils;
|
||||
|
||||
import com.android.internal.app.AssistUtils;
|
||||
import com.android.settings.applications.defaultapps.DefaultAppInfo;
|
||||
import com.android.settings.applications.defaultapps.DefaultAppPreferenceController;
|
||||
import com.android.settings.core.lifecycle.Lifecycle;
|
||||
import com.android.settings.core.lifecycle.LifecycleObserver;
|
||||
import com.android.settings.core.lifecycle.events.OnPause;
|
||||
import com.android.settings.core.lifecycle.events.OnResume;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
public class DefaultVoiceInputPreferenceController extends DefaultAppPreferenceController
|
||||
implements LifecycleObserver, OnResume, OnPause {
|
||||
|
||||
private static final String KEY_VOICE_INPUT = "voice_input_settings";
|
||||
|
||||
private VoiceInputHelper mHelper;
|
||||
private AssistUtils mAssistUtils;
|
||||
private PreferenceScreen mScreen;
|
||||
private Preference mPreference;
|
||||
private SettingObserver mSettingObserver;
|
||||
|
||||
public DefaultVoiceInputPreferenceController(Context context, Lifecycle lifecycle) {
|
||||
super(context);
|
||||
mSettingObserver = new SettingObserver();
|
||||
mAssistUtils = new AssistUtils(context);
|
||||
mHelper = new VoiceInputHelper(context);
|
||||
mHelper.buildUi();
|
||||
if (lifecycle != null) {
|
||||
lifecycle.addObserver(this);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isAvailable() {
|
||||
// If current assist is also voice service, don't show voice preference.
|
||||
final ComponentName currentVoiceService =
|
||||
DefaultVoiceInputPicker.getCurrentService(mHelper);
|
||||
final ComponentName currentAssist =
|
||||
mAssistUtils.getAssistComponentForUser(mUserId);
|
||||
return !DefaultVoiceInputPicker.isCurrentAssistVoiceService(
|
||||
currentAssist, currentVoiceService);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getPreferenceKey() {
|
||||
return KEY_VOICE_INPUT;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void displayPreference(PreferenceScreen screen) {
|
||||
mScreen = screen;
|
||||
mPreference = screen.findPreference(getPreferenceKey());
|
||||
super.displayPreference(screen);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onResume() {
|
||||
mSettingObserver.register(mContext.getContentResolver(), true);
|
||||
updatePreference();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void updateState(Preference preference) {
|
||||
super.updateState(mPreference);
|
||||
updatePreference();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onPause() {
|
||||
mSettingObserver.register(mContext.getContentResolver(), false);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected DefaultAppInfo getDefaultAppInfo() {
|
||||
final String defaultKey = getDefaultAppKey();
|
||||
if (defaultKey == null) {
|
||||
return null;
|
||||
}
|
||||
for (VoiceInputHelper.InteractionInfo info : mHelper.mAvailableInteractionInfos) {
|
||||
if (TextUtils.equals(defaultKey, info.key)) {
|
||||
return new DefaultVoiceInputPicker.VoiceInputDefaultAppInfo(
|
||||
mUserId, info, true /* enabled */);
|
||||
}
|
||||
}
|
||||
|
||||
for (VoiceInputHelper.RecognizerInfo info : mHelper.mAvailableRecognizerInfos) {
|
||||
if (TextUtils.equals(defaultKey, info.key)) {
|
||||
return new DefaultVoiceInputPicker.VoiceInputDefaultAppInfo(
|
||||
mUserId, info, true /* enabled */);
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Intent getSettingIntent(DefaultAppInfo info) {
|
||||
final DefaultAppInfo appInfo = getDefaultAppInfo();
|
||||
if (appInfo == null
|
||||
|| !(appInfo instanceof DefaultVoiceInputPicker.VoiceInputDefaultAppInfo)) {
|
||||
return null;
|
||||
}
|
||||
return ((DefaultVoiceInputPicker.VoiceInputDefaultAppInfo) appInfo).getSettingIntent();
|
||||
}
|
||||
|
||||
private void updatePreference() {
|
||||
if (mPreference == null) {
|
||||
return;
|
||||
}
|
||||
mHelper.buildUi();
|
||||
if (isAvailable()) {
|
||||
if (mScreen.findPreference(getPreferenceKey()) == null) {
|
||||
// add it if it's not on scree
|
||||
mScreen.addPreference(mPreference);
|
||||
}
|
||||
} else {
|
||||
mScreen.removePreference(mPreference);
|
||||
}
|
||||
}
|
||||
|
||||
private String getDefaultAppKey() {
|
||||
final ComponentName currentService = DefaultVoiceInputPicker.getCurrentService(mHelper);
|
||||
if (currentService == null) {
|
||||
return null;
|
||||
}
|
||||
return currentService.flattenToShortString();
|
||||
}
|
||||
|
||||
class SettingObserver extends AssistSettingObserver {
|
||||
@Override
|
||||
protected List<Uri> getSettingUris() {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onSettingChange() {
|
||||
updatePreference();
|
||||
}
|
||||
}
|
||||
}
|
@@ -0,0 +1,46 @@
|
||||
/*
|
||||
* Copyright (C) 2017 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.android.settings.applications.assist;
|
||||
|
||||
import android.content.Context;
|
||||
|
||||
import com.android.settings.core.PreferenceController;
|
||||
import com.android.settings.gestures.AssistGestureFeatureProvider;
|
||||
import com.android.settings.overlay.FeatureFactory;
|
||||
|
||||
public class GestureAssistPreferenceController extends PreferenceController {
|
||||
|
||||
private static final String KEY_ASSIST_GESTURE = "gesture_assist";
|
||||
|
||||
private AssistGestureFeatureProvider mFeatureProvider;
|
||||
|
||||
public GestureAssistPreferenceController(Context context) {
|
||||
super(context);
|
||||
mFeatureProvider = FeatureFactory.getFactory(context)
|
||||
.getAssistGestureFeatureProvider();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isAvailable() {
|
||||
return mFeatureProvider.isSupported(mContext);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getPreferenceKey() {
|
||||
return KEY_ASSIST_GESTURE;
|
||||
}
|
||||
}
|
103
src/com/android/settings/applications/assist/ManageAssist.java
Normal file
103
src/com/android/settings/applications/assist/ManageAssist.java
Normal file
@@ -0,0 +1,103 @@
|
||||
/*
|
||||
* Copyright (C) 2017 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.android.settings.applications.assist;
|
||||
|
||||
import android.content.Context;
|
||||
import android.provider.SearchIndexableResource;
|
||||
|
||||
import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
|
||||
import com.android.settings.R;
|
||||
import com.android.settings.core.PreferenceController;
|
||||
import com.android.settings.core.lifecycle.Lifecycle;
|
||||
import com.android.settings.dashboard.DashboardFragment;
|
||||
import com.android.settings.search.BaseSearchIndexProvider;
|
||||
import com.android.settings.search.Indexable;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* Settings screen to manage everything about assist.
|
||||
*/
|
||||
public class ManageAssist extends DashboardFragment {
|
||||
|
||||
private static final String TAG = "ManageAssist";
|
||||
|
||||
@Override
|
||||
protected String getLogTag() {
|
||||
return TAG;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected int getPreferenceScreenResId() {
|
||||
return R.xml.manage_assist;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected List<PreferenceController> getPreferenceControllers(Context context) {
|
||||
final Lifecycle lifecycle = getLifecycle();
|
||||
final List<PreferenceController> controllers = new ArrayList<>();
|
||||
controllers.add(new DefaultAssistPreferenceController(context));
|
||||
controllers.add(new GestureAssistPreferenceController(context));
|
||||
controllers.add(new AssistContextPreferenceController(context, lifecycle));
|
||||
controllers.add(new AssistScreenshotPreferenceController(context, lifecycle));
|
||||
controllers.add(new AssistFlashScreenPreferenceController(context, lifecycle));
|
||||
controllers.add(new DefaultVoiceInputPreferenceController(context, lifecycle));
|
||||
return controllers;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getMetricsCategory() {
|
||||
return MetricsEvent.APPLICATIONS_MANAGE_ASSIST;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onResume() {
|
||||
super.onResume();
|
||||
|
||||
mFooterPreferenceMixin.createFooterPreference()
|
||||
.setTitle(R.string.assist_footer);
|
||||
}
|
||||
|
||||
public static final Indexable.SearchIndexProvider SEARCH_INDEX_DATA_PROVIDER =
|
||||
new BaseSearchIndexProvider() {
|
||||
@Override
|
||||
public List<SearchIndexableResource> getXmlResourcesToIndex(Context context,
|
||||
boolean enabled) {
|
||||
final SearchIndexableResource sir = new SearchIndexableResource(context);
|
||||
sir.xmlResId = R.xml.manage_assist;
|
||||
return Arrays.asList(sir);
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<String> getNonIndexableKeys(Context context) {
|
||||
List<String> result = new ArrayList<>();
|
||||
new DefaultAssistPreferenceController(context).updateNonIndexableKeys(result);
|
||||
new GestureAssistPreferenceController(context).updateNonIndexableKeys(result);
|
||||
new AssistContextPreferenceController(context, null)
|
||||
.updateNonIndexableKeys(result);
|
||||
new AssistScreenshotPreferenceController(context, null)
|
||||
.updateNonIndexableKeys(result);
|
||||
new AssistFlashScreenPreferenceController(context, null)
|
||||
.updateNonIndexableKeys(result);
|
||||
new DefaultVoiceInputPreferenceController(context, null)
|
||||
.updateNonIndexableKeys(result);
|
||||
return result;
|
||||
}
|
||||
};
|
||||
}
|
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (C) 2014 The Android Open Source Project
|
||||
* Copyright (C) 2017 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -14,7 +14,7 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.android.settings.voice;
|
||||
package com.android.settings.applications.assist;
|
||||
|
||||
import android.content.ComponentName;
|
||||
import android.content.Context;
|
||||
@@ -71,7 +71,7 @@ public final class VoiceInputHelper {
|
||||
|
||||
@Override
|
||||
public int compareTo(Object another) {
|
||||
return labelStr.compareTo(((BaseInfo)another).labelStr);
|
||||
return labelStr.compareTo(((BaseInfo) another).labelStr);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -100,15 +100,11 @@ public final class VoiceInputHelper {
|
||||
mContext = context;
|
||||
|
||||
mAvailableVoiceInteractions = mContext.getPackageManager().queryIntentServices(
|
||||
new Intent(VoiceInteractionService.SERVICE_INTERFACE),
|
||||
PackageManager.GET_META_DATA);
|
||||
new Intent(VoiceInteractionService.SERVICE_INTERFACE),
|
||||
PackageManager.GET_META_DATA);
|
||||
mAvailableRecognition = mContext.getPackageManager().queryIntentServices(
|
||||
new Intent(RecognitionService.SERVICE_INTERFACE),
|
||||
PackageManager.GET_META_DATA);
|
||||
}
|
||||
|
||||
public boolean hasItems() {
|
||||
return mAvailableVoiceInteractions.size() > 0 || mAvailableRecognition.size() > 0;
|
||||
new Intent(RecognitionService.SERVICE_INTERFACE),
|
||||
PackageManager.GET_META_DATA);
|
||||
}
|
||||
|
||||
public void buildUi() {
|
||||
@@ -178,7 +174,7 @@ public final class VoiceInputHelper {
|
||||
AttributeSet attrs = Xml.asAttributeSet(parser);
|
||||
|
||||
int type;
|
||||
while ((type=parser.next()) != XmlPullParser.END_DOCUMENT
|
||||
while ((type = parser.next()) != XmlPullParser.END_DOCUMENT
|
||||
&& type != XmlPullParser.START_TAG) {
|
||||
}
|
||||
|
@@ -37,13 +37,23 @@ public class DefaultAppInfo {
|
||||
public final String summary;
|
||||
// Description for why this item is disabled, if null, the item is enabled.
|
||||
public final String disabledDescription;
|
||||
public final boolean enabled;
|
||||
|
||||
public DefaultAppInfo(int uid, ComponentName cn) {
|
||||
this(uid, cn, null /* summary */);
|
||||
}
|
||||
|
||||
public DefaultAppInfo(int uid, ComponentName cn, String summary) {
|
||||
this(uid, cn, summary, true /* enabled */);
|
||||
}
|
||||
|
||||
public DefaultAppInfo(int uid, ComponentName cn, String summary, boolean enabled) {
|
||||
packageItemInfo = null;
|
||||
userId = uid;
|
||||
componentName = cn;
|
||||
this.summary = summary;
|
||||
this.disabledDescription = null;
|
||||
this.enabled = enabled;
|
||||
}
|
||||
|
||||
public DefaultAppInfo(PackageItemInfo info, String description) {
|
||||
@@ -52,6 +62,7 @@ public class DefaultAppInfo {
|
||||
componentName = null;
|
||||
summary = null;
|
||||
this.disabledDescription = description;
|
||||
enabled = true;
|
||||
}
|
||||
|
||||
public DefaultAppInfo(PackageItemInfo info) {
|
||||
|
@@ -97,7 +97,7 @@ public abstract class DefaultAppPickerFragment extends InstrumentedPreferenceFra
|
||||
@VisibleForTesting
|
||||
public void updateCandidates() {
|
||||
mCandidates.clear();
|
||||
final List<DefaultAppInfo> candidateList = getCandidates();
|
||||
final List<? extends DefaultAppInfo> candidateList = getCandidates();
|
||||
if (candidateList != null) {
|
||||
for (DefaultAppInfo info : candidateList) {
|
||||
mCandidates.put(info.getKey(), info);
|
||||
@@ -134,6 +134,7 @@ public abstract class DefaultAppPickerFragment extends InstrumentedPreferenceFra
|
||||
pref.setEnabled(false);
|
||||
pref.setSummary(app.getValue().disabledDescription);
|
||||
}
|
||||
pref.setEnabled(info.enabled);
|
||||
pref.setOnClickListener(this);
|
||||
screen.addPreference(pref);
|
||||
}
|
||||
@@ -200,14 +201,15 @@ public abstract class DefaultAppPickerFragment extends InstrumentedPreferenceFra
|
||||
return null;
|
||||
}
|
||||
|
||||
protected abstract List<DefaultAppInfo> getCandidates();
|
||||
protected abstract List<? extends DefaultAppInfo> getCandidates();
|
||||
|
||||
protected abstract String getDefaultAppKey();
|
||||
|
||||
protected abstract boolean setDefaultAppKey(String key);
|
||||
|
||||
// Called after the user tries to select an item.
|
||||
protected void onSelectionPerformed(boolean success) {}
|
||||
protected void onSelectionPerformed(boolean success) {
|
||||
}
|
||||
|
||||
protected String getConfirmationMessage(DefaultAppInfo appInfo) {
|
||||
return null;
|
||||
|
@@ -54,7 +54,7 @@ public class DefaultAutoFillPicker extends DefaultAppPickerFragment {
|
||||
.queryIntentServices(AUTO_FILL_PROBE, PackageManager.GET_META_DATA);
|
||||
for (ResolveInfo info : resolveInfos) {
|
||||
candidates.add(new DefaultAppInfo(mUserId, new ComponentName(
|
||||
info.serviceInfo.packageName, info.serviceInfo.name), null /* summary */));
|
||||
info.serviceInfo.packageName, info.serviceInfo.name)));
|
||||
}
|
||||
return candidates;
|
||||
}
|
||||
|
@@ -55,7 +55,7 @@ public class DefaultAutoFillPreferenceController extends DefaultAppPreferenceCon
|
||||
DefaultAutoFillPicker.SETTING);
|
||||
if (!TextUtils.isEmpty(flattenComponent)) {
|
||||
DefaultAppInfo appInfo = new DefaultAppInfo(
|
||||
mUserId, ComponentName.unflattenFromString(flattenComponent), null /*summary*/);
|
||||
mUserId, ComponentName.unflattenFromString(flattenComponent));
|
||||
return appInfo;
|
||||
}
|
||||
return null;
|
||||
|
@@ -75,7 +75,7 @@ public class DefaultHomePreferenceController extends DefaultAppPreferenceControl
|
||||
final ArrayList<ResolveInfo> homeActivities = new ArrayList<>();
|
||||
final ComponentName currentDefaultHome = mPackageManager.getHomeActivities(homeActivities);
|
||||
|
||||
return new DefaultAppInfo(mUserId, currentDefaultHome, null /* summary */);
|
||||
return new DefaultAppInfo(mUserId, currentDefaultHome);
|
||||
}
|
||||
|
||||
private String getOnlyAppLabel() {
|
||||
|
@@ -76,7 +76,7 @@ public class DefaultNotificationAssistantPicker extends DefaultAppPickerFragment
|
||||
}
|
||||
|
||||
candidates.add(new DefaultAppInfo(
|
||||
mUserId, new ComponentName(info.packageName, info.name), null /* summary */));
|
||||
mUserId, new ComponentName(info.packageName, info.name)));
|
||||
}
|
||||
return candidates;
|
||||
}
|
||||
|
@@ -47,7 +47,7 @@ public class DefaultSmsPreferenceController extends DefaultAppPreferenceControll
|
||||
protected DefaultAppInfo getDefaultAppInfo() {
|
||||
final ComponentName app = SmsApplication.getDefaultSmsApplication(mContext, true);
|
||||
if (app != null) {
|
||||
return new DefaultAppInfo(mUserId, app, null /* summary */);
|
||||
return new DefaultAppInfo(mUserId, app);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
@@ -54,7 +54,7 @@ import com.android.settings.applications.AppAndNotificationDashboardFragment;
|
||||
import com.android.settings.applications.DrawOverlayDetails;
|
||||
import com.android.settings.applications.InstalledAppDetails;
|
||||
import com.android.settings.applications.ManageApplications;
|
||||
import com.android.settings.applications.ManageAssist;
|
||||
import com.android.settings.applications.assist.ManageAssist;
|
||||
import com.android.settings.applications.ManageDomainUrls;
|
||||
import com.android.settings.applications.NotificationApps;
|
||||
import com.android.settings.applications.PictureInPictureSettings;
|
||||
|
@@ -37,6 +37,7 @@ import com.android.settings.accounts.UserAndAccountDashboardFragment;
|
||||
import com.android.settings.applications.AdvancedAppSettings;
|
||||
import com.android.settings.applications.AppAndNotificationDashboardFragment;
|
||||
import com.android.settings.applications.SpecialAccessSettings;
|
||||
import com.android.settings.applications.assist.ManageAssist;
|
||||
import com.android.settings.backup.BackupSettingsFragment;
|
||||
import com.android.settings.bluetooth.BluetoothSettings;
|
||||
import com.android.settings.connecteddevice.ConnectedDeviceDashboardFragment;
|
||||
@@ -133,6 +134,7 @@ public final class SearchIndexableResources {
|
||||
addIndex(BatterySaverSettings.class,
|
||||
R.xml.battery_saver_settings, R.drawable.ic_settings_battery);
|
||||
addIndex(AdvancedAppSettings.class, NO_DATA_RES_ID, R.drawable.ic_settings_applications);
|
||||
addIndex(ManageAssist.class, NO_DATA_RES_ID, R.drawable.ic_settings_applications);
|
||||
addIndex(SpecialAccessSettings.class,
|
||||
R.xml.special_access, R.drawable.ic_settings_applications);
|
||||
addIndex(UserSettings.class, NO_DATA_RES_ID, R.drawable.ic_settings_multiuser);
|
||||
|
@@ -1,158 +0,0 @@
|
||||
package com.android.settings.voice;
|
||||
|
||||
import android.content.ComponentName;
|
||||
import android.content.Context;
|
||||
import android.provider.Settings;
|
||||
import android.util.AttributeSet;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.widget.ArrayAdapter;
|
||||
import android.widget.ListAdapter;
|
||||
|
||||
import com.android.settings.AppListPreferenceWithSettings;
|
||||
import com.android.settings.R;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
public class VoiceInputListPreference extends AppListPreferenceWithSettings {
|
||||
|
||||
private VoiceInputHelper mHelper;
|
||||
|
||||
// The assist component name to restrict available voice inputs.
|
||||
private ComponentName mAssistRestrict;
|
||||
|
||||
private final List<Integer> mAvailableIndexes = new ArrayList<>();
|
||||
|
||||
public VoiceInputListPreference(Context context, AttributeSet attrs) {
|
||||
super(context, attrs);
|
||||
setDialogTitle(R.string.choose_voice_input_title);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected ListAdapter createListAdapter() {
|
||||
return new CustomAdapter(getContext(), getEntries());
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean persistString(String value) {
|
||||
for (int i = 0; i < mHelper.mAvailableInteractionInfos.size(); ++i) {
|
||||
VoiceInputHelper.InteractionInfo info = mHelper.mAvailableInteractionInfos.get(i);
|
||||
if (info.key.equals(value)) {
|
||||
Settings.Secure.putString(getContext().getContentResolver(),
|
||||
Settings.Secure.VOICE_INTERACTION_SERVICE, value);
|
||||
Settings.Secure.putString(getContext().getContentResolver(),
|
||||
Settings.Secure.VOICE_RECOGNITION_SERVICE,
|
||||
new ComponentName(info.service.packageName,
|
||||
info.serviceInfo.getRecognitionService())
|
||||
.flattenToShortString());
|
||||
setSummary(getEntry());
|
||||
setSettingsComponent(info.settings);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
for (int i = 0; i < mHelper.mAvailableRecognizerInfos.size(); ++i) {
|
||||
VoiceInputHelper.RecognizerInfo info = mHelper.mAvailableRecognizerInfos.get(i);
|
||||
if (info.key.equals(value)) {
|
||||
Settings.Secure.putString(getContext().getContentResolver(),
|
||||
Settings.Secure.VOICE_INTERACTION_SERVICE, "");
|
||||
Settings.Secure.putString(getContext().getContentResolver(),
|
||||
Settings.Secure.VOICE_RECOGNITION_SERVICE, value);
|
||||
setSummary(getEntry());
|
||||
setSettingsComponent(info.settings);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
setSettingsComponent(null);
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setPackageNames(CharSequence[] packageNames, CharSequence defaultPackageName) {
|
||||
// Skip since all entries are created from |mHelper|.
|
||||
}
|
||||
|
||||
public void setAssistRestrict(ComponentName assistRestrict) {
|
||||
mAssistRestrict = assistRestrict;
|
||||
}
|
||||
|
||||
public void refreshVoiceInputs() {
|
||||
mHelper = new VoiceInputHelper(getContext());
|
||||
mHelper.buildUi();
|
||||
|
||||
final String assistKey =
|
||||
mAssistRestrict == null ? "" : mAssistRestrict.flattenToShortString();
|
||||
|
||||
mAvailableIndexes.clear();
|
||||
List<CharSequence> entries = new ArrayList<>();
|
||||
List<CharSequence> values = new ArrayList<>();
|
||||
for (int i = 0; i < mHelper.mAvailableInteractionInfos.size(); ++i) {
|
||||
VoiceInputHelper.InteractionInfo info = mHelper.mAvailableInteractionInfos.get(i);
|
||||
entries.add(info.appLabel);
|
||||
values.add(info.key);
|
||||
|
||||
if (info.key.contentEquals(assistKey)) {
|
||||
mAvailableIndexes.add(i);
|
||||
}
|
||||
}
|
||||
|
||||
final boolean assitIsService = !mAvailableIndexes.isEmpty();
|
||||
final int serviceCount = entries.size();
|
||||
|
||||
for (int i = 0; i < mHelper.mAvailableRecognizerInfos.size(); ++i) {
|
||||
VoiceInputHelper.RecognizerInfo info = mHelper.mAvailableRecognizerInfos.get(i);
|
||||
entries.add(info.label);
|
||||
values.add(info.key);
|
||||
if (!assitIsService) {
|
||||
mAvailableIndexes.add(serviceCount + i);
|
||||
}
|
||||
}
|
||||
setEntries(entries.toArray(new CharSequence[entries.size()]));
|
||||
setEntryValues(values.toArray(new CharSequence[values.size()]));
|
||||
|
||||
if (mHelper.mCurrentVoiceInteraction != null) {
|
||||
setValue(mHelper.mCurrentVoiceInteraction.flattenToShortString());
|
||||
} else if (mHelper.mCurrentRecognizer != null) {
|
||||
setValue(mHelper.mCurrentRecognizer.flattenToShortString());
|
||||
} else {
|
||||
setValue(null);
|
||||
}
|
||||
}
|
||||
|
||||
public ComponentName getCurrentService() {
|
||||
if (mHelper.mCurrentVoiceInteraction != null) {
|
||||
return mHelper.mCurrentVoiceInteraction;
|
||||
} else if (mHelper.mCurrentRecognizer != null) {
|
||||
return mHelper.mCurrentRecognizer;
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
private class CustomAdapter extends ArrayAdapter<CharSequence> {
|
||||
|
||||
public CustomAdapter(Context context, CharSequence[] objects) {
|
||||
super(context, com.android.internal.R.layout.select_dialog_singlechoice_material,
|
||||
android.R.id.text1, objects);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean areAllItemsEnabled() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isEnabled(int position) {
|
||||
return mAvailableIndexes.contains(position);
|
||||
}
|
||||
|
||||
@Override
|
||||
public View getView(int position, View convertView, ViewGroup parent) {
|
||||
View view = super.getView(position, convertView, parent);
|
||||
view.setEnabled(isEnabled(position));
|
||||
return view;
|
||||
}
|
||||
}
|
||||
}
|
@@ -65,7 +65,7 @@ com.android.settings.fuelgauge.BatteryHistoryDetail
|
||||
com.android.settings.fuelgauge.PowerUsageSummary
|
||||
com.android.settings.applications.RunningServices
|
||||
com.android.settings.wifi.p2p.WifiP2pSettings
|
||||
com.android.settings.applications.ManageAssist
|
||||
com.android.settings.applications.assistant.ManageAssist
|
||||
com.android.settings.applications.ConfirmConvertToFbe
|
||||
com.android.settings.deviceinfo.PublicVolumeSettings
|
||||
com.android.settings.applications.InstalledAppDetails
|
||||
|
@@ -16,7 +16,6 @@
|
||||
|
||||
package com.android.settings;
|
||||
|
||||
import android.content.ContentResolver;
|
||||
import android.content.Context;
|
||||
import android.content.IContentProvider;
|
||||
import android.content.pm.PackageManager;
|
||||
@@ -26,6 +25,7 @@ import android.provider.Settings;
|
||||
|
||||
import com.android.settings.dashboard.SummaryLoader;
|
||||
import com.android.settings.testutils.FakeFeatureFactory;
|
||||
import com.android.settings.testutils.shadow.ShadowSecureSettings;
|
||||
import com.android.settingslib.drawer.DashboardCategory;
|
||||
import com.android.settingslib.drawer.Tile;
|
||||
import com.android.settingslib.drawer.TileUtils;
|
||||
@@ -40,7 +40,6 @@ import org.robolectric.annotation.Config;
|
||||
import org.robolectric.annotation.Implementation;
|
||||
import org.robolectric.annotation.Implements;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
import static com.google.common.truth.Truth.assertThat;
|
||||
@@ -67,24 +66,6 @@ public class SecuritySettingsTest {
|
||||
|
||||
private SecuritySettings.SummaryProvider mSummaryProvider;
|
||||
|
||||
@Implements(Settings.Secure.class)
|
||||
public static class ShadowSecureSettings {
|
||||
|
||||
private static final Map<String, Object> mValueMap = new HashMap<>();
|
||||
|
||||
@Implementation
|
||||
public static boolean putInt(ContentResolver resolver, String name, int value) {
|
||||
mValueMap.put(name, value);
|
||||
return true;
|
||||
}
|
||||
|
||||
@Implementation
|
||||
public static int getInt(ContentResolver resolver, String name, int defaultValue) {
|
||||
Integer value = (Integer) mValueMap.get(name);
|
||||
return value == null ? defaultValue : value;
|
||||
}
|
||||
}
|
||||
|
||||
@Implements(com.android.settingslib.drawer.TileUtils.class)
|
||||
public static class ShadowTileUtils {
|
||||
@Implementation
|
||||
|
@@ -0,0 +1,95 @@
|
||||
/*
|
||||
* Copyright (C) 2017 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.android.settings.applications.assist;
|
||||
|
||||
import android.content.ContentResolver;
|
||||
import android.content.Context;
|
||||
import android.provider.Settings;
|
||||
import android.support.v7.preference.PreferenceScreen;
|
||||
import android.support.v7.preference.TwoStatePreference;
|
||||
|
||||
import com.android.settings.SettingsRobolectricTestRunner;
|
||||
import com.android.settings.TestConfig;
|
||||
import com.android.settings.core.lifecycle.Lifecycle;
|
||||
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.mockito.Mock;
|
||||
import org.mockito.MockitoAnnotations;
|
||||
import org.robolectric.RuntimeEnvironment;
|
||||
import org.robolectric.annotation.Config;
|
||||
import org.robolectric.util.ReflectionHelpers;
|
||||
|
||||
import static com.google.common.truth.Truth.assertThat;
|
||||
import static org.mockito.Matchers.any;
|
||||
import static org.mockito.Matchers.anyString;
|
||||
import static org.mockito.Matchers.eq;
|
||||
import static org.mockito.Mockito.verify;
|
||||
import static org.mockito.Mockito.when;
|
||||
|
||||
@RunWith(SettingsRobolectricTestRunner.class)
|
||||
@Config(manifest = TestConfig.MANIFEST_PATH, sdk = TestConfig.SDK_VERSION)
|
||||
public class AssistContextPreferenceControllerTest {
|
||||
|
||||
@Mock
|
||||
private PreferenceScreen mScreen;
|
||||
@Mock
|
||||
private TwoStatePreference mPreference;
|
||||
@Mock
|
||||
private AssistContextPreferenceController.SettingObserver mObserver;
|
||||
private Context mContext;
|
||||
private AssistContextPreferenceController mController;
|
||||
private Lifecycle mLifecycle;
|
||||
|
||||
@Before
|
||||
public void setUp() {
|
||||
MockitoAnnotations.initMocks(this);
|
||||
when(mScreen.findPreference(anyString())).thenReturn(mPreference);
|
||||
mLifecycle = new Lifecycle();
|
||||
mContext = RuntimeEnvironment.application;
|
||||
mController = new AssistContextPreferenceController(mContext, mLifecycle);
|
||||
ReflectionHelpers.setField(mController, "mSettingObserver", mObserver);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void isAvailable_hasAssistant_shouldReturnTrue() {
|
||||
Settings.Secure.putString(mContext.getContentResolver(),
|
||||
Settings.Secure.ASSISTANT, "com.android.settings/assist");
|
||||
assertThat(mController.isAvailable()).isTrue();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void isAvailable_hasNoAssistant_shouldReturnFalse() {
|
||||
Settings.Secure.putString(mContext.getContentResolver(),
|
||||
Settings.Secure.ASSISTANT, "");
|
||||
assertThat(mController.isAvailable()).isFalse();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void onResume_shouldUpdatePreference() {
|
||||
Settings.Secure.putString(mContext.getContentResolver(),
|
||||
Settings.Secure.ASSISTANT, "com.android.settings/assist");
|
||||
mController.displayPreference(mScreen);
|
||||
Settings.Secure.putInt(mContext.getContentResolver(),
|
||||
Settings.Secure.ASSIST_STRUCTURE_ENABLED, 1);
|
||||
|
||||
mLifecycle.onResume();
|
||||
verify(mObserver).register(any(ContentResolver.class), eq(true));
|
||||
verify(mPreference).setChecked(true);
|
||||
}
|
||||
}
|
@@ -0,0 +1,125 @@
|
||||
/*
|
||||
* Copyright (C) 2017 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.android.settings.applications.assist;
|
||||
|
||||
import android.content.ComponentName;
|
||||
import android.content.ContentResolver;
|
||||
import android.content.Context;
|
||||
import android.provider.Settings;
|
||||
import android.support.v7.preference.PreferenceScreen;
|
||||
import android.support.v7.preference.TwoStatePreference;
|
||||
|
||||
import com.android.settings.SettingsRobolectricTestRunner;
|
||||
import com.android.settings.TestConfig;
|
||||
import com.android.settings.core.lifecycle.Lifecycle;
|
||||
import com.android.settings.testutils.shadow.ShadowSecureSettings;
|
||||
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.mockito.Answers;
|
||||
import org.mockito.Mock;
|
||||
import org.mockito.MockitoAnnotations;
|
||||
import org.robolectric.RuntimeEnvironment;
|
||||
import org.robolectric.annotation.Config;
|
||||
import org.robolectric.util.ReflectionHelpers;
|
||||
|
||||
import static com.google.common.truth.Truth.assertThat;
|
||||
import static org.mockito.Matchers.any;
|
||||
import static org.mockito.Matchers.anyString;
|
||||
import static org.mockito.Matchers.eq;
|
||||
import static org.mockito.Mockito.doReturn;
|
||||
import static org.mockito.Mockito.spy;
|
||||
import static org.mockito.Mockito.verify;
|
||||
import static org.mockito.Mockito.when;
|
||||
|
||||
@RunWith(SettingsRobolectricTestRunner.class)
|
||||
@Config(manifest = TestConfig.MANIFEST_PATH, sdk = TestConfig.SDK_VERSION)
|
||||
public class AssistFlashScreenPreferenceControllerTest {
|
||||
|
||||
@Mock(answer = Answers.RETURNS_DEEP_STUBS)
|
||||
private Context mMockContext;
|
||||
@Mock
|
||||
private PreferenceScreen mScreen;
|
||||
@Mock
|
||||
private TwoStatePreference mPreference;
|
||||
@Mock
|
||||
private AssistFlashScreenPreferenceController.SettingObserver mObserver;
|
||||
private Context mContext;
|
||||
private AssistFlashScreenPreferenceController mController;
|
||||
private Lifecycle mLifecycle;
|
||||
|
||||
@Before
|
||||
public void setUp() {
|
||||
MockitoAnnotations.initMocks(this);
|
||||
when(mScreen.findPreference(anyString())).thenReturn(mPreference);
|
||||
mLifecycle = new Lifecycle();
|
||||
mContext = RuntimeEnvironment.application;
|
||||
mController = spy(new AssistFlashScreenPreferenceController(mContext, mLifecycle));
|
||||
mLifecycle.addObserver(mController);
|
||||
ReflectionHelpers.setField(mController, "mSettingObserver", mObserver);
|
||||
}
|
||||
|
||||
@Test
|
||||
@Config(shadows = {ShadowSecureSettings.class})
|
||||
public void isAvailable_hasAssistantAndAllowDisclosure_shouldReturnTrue() {
|
||||
ReflectionHelpers.setField(mController, "mContext", mMockContext);
|
||||
ShadowSecureSettings.putString(null, Settings.Secure.ASSISTANT,
|
||||
"com.android.settings/assist");
|
||||
doReturn(true).when(mController).allowDisablingAssistDisclosure();
|
||||
|
||||
assertThat(mController.isAvailable()).isTrue();
|
||||
}
|
||||
|
||||
@Test
|
||||
@Config(shadows = {ShadowSecureSettings.class})
|
||||
public void isAvailable_hasAssistantAndDisallowDisclosure_shouldReturnTrue() {
|
||||
ReflectionHelpers.setField(mController, "mContext", mMockContext);
|
||||
ShadowSecureSettings.putString(null, Settings.Secure.ASSISTANT,
|
||||
"com.android.settings/assist");
|
||||
doReturn(false).when(mController).allowDisablingAssistDisclosure();
|
||||
|
||||
assertThat(mController.isAvailable()).isFalse();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void isAvailable_hasNoAssistant_shouldReturnFalse() {
|
||||
Settings.Secure.putString(mContext.getContentResolver(),
|
||||
Settings.Secure.ASSISTANT, "");
|
||||
|
||||
assertThat(mController.isAvailable()).isFalse();
|
||||
}
|
||||
|
||||
@Test
|
||||
@Config(shadows = {ShadowSecureSettings.class})
|
||||
public void onResume_shouldUpdatePreference() {
|
||||
Settings.Secure.putString(mContext.getContentResolver(),
|
||||
Settings.Secure.ASSISTANT, "com.android.settings/assist");
|
||||
doReturn(true).when(mController).isAvailable();
|
||||
doReturn(true).when(mController).isPreInstalledAssistant(any(ComponentName.class));
|
||||
doReturn(true).when(mController).willShowFlash(any(ComponentName.class));
|
||||
|
||||
mController.displayPreference(mScreen);
|
||||
Settings.Secure.putInt(mContext.getContentResolver(),
|
||||
Settings.Secure.ASSIST_DISCLOSURE_ENABLED, 1);
|
||||
|
||||
mLifecycle.onResume();
|
||||
|
||||
verify(mObserver).register(any(ContentResolver.class), eq(true));
|
||||
verify(mPreference).setChecked(true);
|
||||
}
|
||||
}
|
@@ -0,0 +1,99 @@
|
||||
/*
|
||||
* Copyright (C) 2017 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.android.settings.applications.assist;
|
||||
|
||||
|
||||
import android.content.ComponentName;
|
||||
import android.content.Context;
|
||||
import android.provider.Settings;
|
||||
|
||||
import com.android.settings.SettingsRobolectricTestRunner;
|
||||
import com.android.settings.TestConfig;
|
||||
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.robolectric.RuntimeEnvironment;
|
||||
import org.robolectric.annotation.Config;
|
||||
import org.robolectric.util.ReflectionHelpers;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import static com.google.common.truth.Truth.assertThat;
|
||||
import static org.mockito.Mockito.doReturn;
|
||||
import static org.mockito.Mockito.spy;
|
||||
|
||||
@RunWith(SettingsRobolectricTestRunner.class)
|
||||
@Config(manifest = TestConfig.MANIFEST_PATH, sdk = TestConfig.SDK_VERSION)
|
||||
public class DefaultAssistPickerTest {
|
||||
|
||||
private static final ComponentName TEST_ASSIST =
|
||||
new ComponentName("com.android.settings", "assist");
|
||||
|
||||
private Context mContext;
|
||||
private DefaultAssistPicker mPicker;
|
||||
|
||||
@Before
|
||||
public void setUp() {
|
||||
mContext = RuntimeEnvironment.application;
|
||||
mPicker = spy(new DefaultAssistPicker());
|
||||
mPicker.onAttach(mContext);
|
||||
doReturn(mContext).when(mPicker).getContext();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void setDefaultAppKey_shouldUpdateDefaultAssist() {
|
||||
final List<DefaultAssistPicker.Info> assistants = new ArrayList<>();
|
||||
assistants.add(new DefaultAssistPicker.Info(TEST_ASSIST));
|
||||
ReflectionHelpers.setField(mPicker, "mAvailableAssistants", assistants);
|
||||
mPicker.setDefaultAppKey(TEST_ASSIST.flattenToString());
|
||||
|
||||
assertThat(Settings.Secure.getString(mContext.getContentResolver(),
|
||||
Settings.Secure.ASSISTANT))
|
||||
.isEqualTo(TEST_ASSIST.flattenToString());
|
||||
assertThat(mPicker.getDefaultAppKey())
|
||||
.isEqualTo(TEST_ASSIST.flattenToString());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void setDefaultAppKey_noAvaialbleAssit_shouldClearDefaultAssist() {
|
||||
final List<DefaultAssistPicker.Info> assistants = new ArrayList<>();
|
||||
ReflectionHelpers.setField(mPicker, "mAvailableAssistants", assistants);
|
||||
mPicker.setDefaultAppKey(TEST_ASSIST.flattenToString());
|
||||
|
||||
assertThat(Settings.Secure.getString(mContext.getContentResolver(),
|
||||
Settings.Secure.ASSISTANT))
|
||||
.isEmpty();
|
||||
assertThat(mPicker.getDefaultAppKey())
|
||||
.isNull();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void setDefaultAppKeyToNull_shouldClearDefaultAssist() {
|
||||
final List<DefaultAssistPicker.Info> assistants = new ArrayList<>();
|
||||
assistants.add(new DefaultAssistPicker.Info(TEST_ASSIST));
|
||||
ReflectionHelpers.setField(mPicker, "mAvailableAssistants", assistants);
|
||||
mPicker.setDefaultAppKey(null);
|
||||
|
||||
assertThat(Settings.Secure.getString(mContext.getContentResolver(),
|
||||
Settings.Secure.ASSISTANT))
|
||||
.isEmpty();
|
||||
assertThat(mPicker.getDefaultAppKey())
|
||||
.isNull();
|
||||
}
|
||||
}
|
@@ -0,0 +1,64 @@
|
||||
/*
|
||||
* Copyright (C) 2017 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.android.settings.applications.assist;
|
||||
|
||||
import android.content.Context;
|
||||
import android.provider.Settings;
|
||||
|
||||
import com.android.settings.SettingsRobolectricTestRunner;
|
||||
import com.android.settings.TestConfig;
|
||||
import com.android.settings.applications.defaultapps.DefaultAppInfo;
|
||||
import com.android.settings.testutils.shadow.ShadowSecureSettings;
|
||||
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.mockito.Mock;
|
||||
import org.mockito.MockitoAnnotations;
|
||||
import org.robolectric.annotation.Config;
|
||||
|
||||
import static com.google.common.truth.Truth.assertThat;
|
||||
|
||||
@RunWith(SettingsRobolectricTestRunner.class)
|
||||
@Config(manifest = TestConfig.MANIFEST_PATH, sdk = TestConfig.SDK_VERSION)
|
||||
public class DefaultAssistPreferenceControllerTest {
|
||||
|
||||
@Mock
|
||||
private Context mContext;
|
||||
private DefaultAssistPreferenceController mController;
|
||||
|
||||
@Before
|
||||
public void setUp() {
|
||||
MockitoAnnotations.initMocks(this);
|
||||
mController = new DefaultAssistPreferenceController(mContext);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void isAlwaysAvailable() {
|
||||
assertThat(mController.isAvailable()).isTrue();
|
||||
}
|
||||
|
||||
@Test
|
||||
@Config(shadows = {ShadowSecureSettings.class})
|
||||
public void getDefaultAppInfo_hasDefaultAssist_shouldReturnKey() {
|
||||
final String flattenKey = "com.android.settings/assist";
|
||||
ShadowSecureSettings.putString(null, Settings.Secure.ASSISTANT, flattenKey);
|
||||
DefaultAppInfo appInfo = mController.getDefaultAppInfo();
|
||||
|
||||
assertThat(appInfo.getKey()).isEqualTo(flattenKey);
|
||||
}
|
||||
}
|
@@ -0,0 +1,64 @@
|
||||
/*
|
||||
* Copyright (C) 2017 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.android.settings.applications.assist;
|
||||
|
||||
import android.content.Context;
|
||||
|
||||
import com.android.settings.SettingsRobolectricTestRunner;
|
||||
import com.android.settings.TestConfig;
|
||||
import com.android.settings.testutils.FakeFeatureFactory;
|
||||
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.mockito.Answers;
|
||||
import org.mockito.Mock;
|
||||
import org.mockito.MockitoAnnotations;
|
||||
import org.robolectric.annotation.Config;
|
||||
|
||||
import static com.google.common.truth.Truth.assertThat;
|
||||
import static org.mockito.Matchers.any;
|
||||
import static org.mockito.Mockito.when;
|
||||
|
||||
@RunWith(SettingsRobolectricTestRunner.class)
|
||||
@Config(manifest = TestConfig.MANIFEST_PATH, sdk = TestConfig.SDK_VERSION)
|
||||
public class GestureAssistPreferenceControllerTest {
|
||||
|
||||
@Mock(answer = Answers.RETURNS_DEEP_STUBS)
|
||||
private Context mContext;
|
||||
private FakeFeatureFactory mFeatureFactory;
|
||||
private GestureAssistPreferenceController mController;
|
||||
|
||||
@Before
|
||||
public void setUp() {
|
||||
MockitoAnnotations.initMocks(this);
|
||||
FakeFeatureFactory.setupForTest(mContext);
|
||||
mFeatureFactory = (FakeFeatureFactory) FakeFeatureFactory.getFactory(mContext);
|
||||
mController = new GestureAssistPreferenceController(mContext);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void isAvailable_shouldReturnFeatureProviderValue() {
|
||||
when(mFeatureFactory.assistGestureFeatureProvider.isSupported(any(Context.class)))
|
||||
.thenReturn(true);
|
||||
assertThat(mController.isAvailable()).isTrue();
|
||||
|
||||
when(mFeatureFactory.assistGestureFeatureProvider.isSupported(any(Context.class)))
|
||||
.thenReturn(false);
|
||||
assertThat(mController.isAvailable()).isFalse();
|
||||
}
|
||||
}
|
@@ -0,0 +1,59 @@
|
||||
/*
|
||||
* Copyright (C) 2017 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.android.settings.applications.assist;
|
||||
|
||||
import com.android.internal.logging.nano.MetricsProto;
|
||||
import com.android.settings.R;
|
||||
import com.android.settings.SettingsRobolectricTestRunner;
|
||||
import com.android.settings.TestConfig;
|
||||
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.robolectric.annotation.Config;
|
||||
|
||||
import static com.google.common.truth.Truth.assertThat;
|
||||
|
||||
@RunWith(SettingsRobolectricTestRunner.class)
|
||||
@Config(manifest = TestConfig.MANIFEST_PATH, sdk = TestConfig.SDK_VERSION)
|
||||
public class ManageAssistTest {
|
||||
|
||||
private ManageAssist mSettings;
|
||||
|
||||
@Before
|
||||
public void setUp() {
|
||||
mSettings = new ManageAssist();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGetMetricsCategory() {
|
||||
assertThat(mSettings.getMetricsCategory())
|
||||
.isEqualTo(MetricsProto.MetricsEvent.APPLICATIONS_MANAGE_ASSIST);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGetCategoryKey() {
|
||||
assertThat(mSettings.getCategoryKey()).isNull();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGetPreferenceScreenResId() {
|
||||
assertThat(mSettings.getPreferenceScreenResId())
|
||||
.isEqualTo(R.xml.manage_assist);
|
||||
}
|
||||
|
||||
}
|
@@ -85,7 +85,7 @@ public class DefaultAppInfoTest {
|
||||
public void initInfoWithComponent_shouldLoadInfo() {
|
||||
when(mComponentName.getPackageName()).thenReturn("com.android.settings");
|
||||
|
||||
mInfo = new DefaultAppInfo(0 /* uid */, mComponentName, null /*summary */);
|
||||
mInfo = new DefaultAppInfo(0 /* uid */, mComponentName);
|
||||
mInfo.getKey();
|
||||
|
||||
verify(mComponentName).flattenToString();
|
||||
|
@@ -36,7 +36,7 @@ public class SearchIndexProviderCodeInspector extends CodeInspector {
|
||||
private static final String TAG = "SearchCodeInspector";
|
||||
|
||||
private static final String NOT_IMPLEMENTING_INDEXABLE_ERROR =
|
||||
"SettingsPreferenceFragment should implement Indexable, but these are not:\n";
|
||||
"SettingsPreferenceFragment should implement Indexable, but these do not:\n";
|
||||
private static final String NOT_CONTAINING_PROVIDER_OBJECT_ERROR =
|
||||
"Indexable should have public field " + Index.FIELD_NAME_SEARCH_INDEX_DATA_PROVIDER
|
||||
+ " but these are not:\n";
|
||||
|
@@ -0,0 +1,60 @@
|
||||
/*
|
||||
* Copyright (C) 2017 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.android.settings.testutils.shadow;
|
||||
|
||||
import android.content.ContentResolver;
|
||||
import android.provider.Settings;
|
||||
|
||||
import org.robolectric.annotation.Implementation;
|
||||
import org.robolectric.annotation.Implements;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
@Implements(Settings.Secure.class)
|
||||
public class ShadowSecureSettings {
|
||||
|
||||
private static final Map<String, Object> mValueMap = new HashMap<>();
|
||||
|
||||
@Implementation
|
||||
public static boolean putInt(ContentResolver resolver, String name, int value) {
|
||||
mValueMap.put(name, value);
|
||||
return true;
|
||||
}
|
||||
|
||||
@Implementation
|
||||
public static boolean putString(ContentResolver resolver, String name, String value) {
|
||||
mValueMap.put(name, value);
|
||||
return true;
|
||||
}
|
||||
|
||||
@Implementation
|
||||
public static String getString(ContentResolver resolver, String name) {
|
||||
return (String) mValueMap.get(name);
|
||||
}
|
||||
|
||||
@Implementation
|
||||
public static String getStringForUser(ContentResolver resolver, String name, int userHandle) {
|
||||
return getString(resolver, name);
|
||||
}
|
||||
|
||||
@Implementation
|
||||
public static int getInt(ContentResolver resolver, String name, int defaultValue) {
|
||||
Integer value = (Integer) mValueMap.get(name);
|
||||
return value == null ? defaultValue : value;
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user