Full screen default app fragment

Fix: 34280137
Test: make RunSettingsRoboTests
Change-Id: Ib44e39589781d68c7952a2c16a44682791a422f1
This commit is contained in:
Fan Zhang
2017-01-13 16:01:14 -08:00
parent d9d463be8b
commit 35692cf439
47 changed files with 2654 additions and 1007 deletions

View File

@@ -293,10 +293,6 @@
<!-- Scrollbar style OUTSIDE_OVERLAY --> <!-- Scrollbar style OUTSIDE_OVERLAY -->
<integer name="preference_scrollbar_style">33554432</integer> <integer name="preference_scrollbar_style">33554432</integer>
<style name="AppListSwitchPreference" parent="@*android:style/Preference.Material.DialogPreference">
<item name="android:widgetLayout">@*android:layout/preference_widget_switch</item>
</style>
<style name="TextAppearance.Medium" parent="@android:style/TextAppearance.Material.Medium" /> <style name="TextAppearance.Medium" parent="@android:style/TextAppearance.Material.Medium" />
<style name="TextAppearance.Small" parent="@android:style/TextAppearance.Material.Small" /> <style name="TextAppearance.Small" parent="@android:style/TextAppearance.Material.Small" />
<style name="TextAppearance.Switch" parent="@android:style/TextAppearance.Material.Title" /> <style name="TextAppearance.Switch" parent="@android:style/TextAppearance.Material.Title" />

View File

@@ -1,101 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- 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.
-->
<PreferenceScreen
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:settings="http://schemas.android.com/apk/res/com.android.settings"
android:key="applications_settings">
<Preference
android:key="manage_perms"
android:title="@string/app_permissions"
settings:keywords="@string/keywords_app_permissions">
<intent android:action="android.intent.action.MANAGE_PERMISSIONS"/>
</Preference>
<PreferenceCategory
android:title="@string/default_apps_title">
<Preference
android:key="domain_urls"
android:title="@string/domain_urls_title"
android:fragment="com.android.settings.applications.ManageDomainUrls" />
<Preference
android:key="assist_and_voice_input"
android:fragment="com.android.settings.applications.ManageAssist"
android:title="@string/assist_and_voice_input_title" />
<com.android.settings.applications.DefaultHomePreference
android:key="default_home"
android:title="@string/home_app"
android:summary="@string/no_default_home"
settings:keywords="@string/keywords_home" />
<com.android.settings.applications.DefaultBrowserPreference
android:key="default_browser"
android:title="@string/default_browser_title"
android:summary="@string/default_browser_title_none" />
<com.android.settings.applications.DefaultPhonePreference
android:key="default_phone_app"
android:title="@string/default_phone_title"
settings:keywords="@string/keywords_default_phone_app" />
<com.android.settings.applications.DefaultEmergencyPreference
android:key="default_emergency_app"
android:title="@string/default_emergency_app"
settings:keywords="@string/keywords_emergency_app" />
<com.android.settings.applications.DefaultSmsPreference
android:key="default_sms_app"
android:title="@string/sms_application_title"
settings:keywords="@string/keywords_more_default_sms_app" />
<com.android.settings.applications.DefaultNotificationAssistantPreference
android:key="default_notification_asst_app"
android:title="@string/default_notification_assistant" />
</PreferenceCategory>
<com.android.settings.WorkOnlyCategory
android:key="work_defaults"
android:title="@string/default_for_work">
<com.android.settings.applications.DefaultBrowserPreference
android:key="work_default_browser"
android:title="@string/default_browser_title"
android:summary="@string/default_browser_title_none"
settings:forWork="true" />
<com.android.settings.applications.DefaultPhonePreference
android:key="work_default_phone_app"
android:title="@string/default_phone_title"
settings:keywords="@string/keywords_default_phone_app"
settings:forWork="true" />
</com.android.settings.WorkOnlyCategory>
<PreferenceCategory
android:title="@string/advanced_apps">
<Preference
android:key="special_access"
android:fragment="com.android.settings.applications.SpecialAccessSettings"
android:title="@string/special_access" />
</PreferenceCategory>
</PreferenceScreen>

View File

@@ -15,8 +15,7 @@
--> -->
<PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android" <PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:settings="http://schemas.android.com/apk/res/com.android.settings" android:title="@string/apn_edit">
android:title="@string/apn_edit">
<EditTextPreference <EditTextPreference
android:title="@string/apn_name" android:title="@string/apn_name"
android:dialogTitle="@string/apn_name" android:dialogTitle="@string/apn_name"

View File

@@ -26,40 +26,48 @@
android:fragment="com.android.settings.applications.ManageAssist" android:fragment="com.android.settings.applications.ManageAssist"
android:order="-20"/> android:order="-20"/>
<com.android.settings.applications.DefaultBrowserPreference <Preference
android:key="default_browser" android:key="default_browser"
android:title="@string/default_browser_title" android:title="@string/default_browser_title"
android:summary="@string/default_browser_title_none" android:summary="@string/default_browser_title_none"
android:order="-19"/> android:fragment="com.android.settings.applications.defaultapps.DefaultBrowserPicker"
android:order="-19">
<extra android:name="for_work" android:value="false"/>
</Preference>
<com.android.settings.applications.DefaultHomePreference <Preference
android:key="default_home" android:key="default_home"
android:title="@string/home_app" android:title="@string/home_app"
android:summary="@string/no_default_home" android:summary="@string/no_default_home"
settings:keywords="@string/keywords_home" settings:keywords="@string/keywords_home"
android:fragment="com.android.settings.applications.defaultapps.DefaultHomePicker"
android:order="-18"/> android:order="-18"/>
<com.android.settings.applications.DefaultPhonePreference <Preference
android:key="default_phone_app" android:key="default_phone_app"
android:title="@string/default_phone_title" android:title="@string/default_phone_title"
android:fragment="com.android.settings.applications.defaultapps.DefaultPhonePicker"
settings:keywords="@string/keywords_default_phone_app" settings:keywords="@string/keywords_default_phone_app"
android:order="-17"/> android:order="-17"/>
<com.android.settings.applications.DefaultSmsPreference <Preference
android:key="default_sms_app" android:key="default_sms_app"
android:title="@string/sms_application_title" android:title="@string/sms_application_title"
android:fragment="com.android.settings.applications.defaultapps.DefaultSmsPicker"
settings:keywords="@string/keywords_more_default_sms_app" settings:keywords="@string/keywords_more_default_sms_app"
android:order="-16"/> android:order="-16"/>
<com.android.settings.applications.DefaultEmergencyPreference <Preference
android:key="default_emergency_app" android:key="default_emergency_app"
android:title="@string/default_emergency_app" android:title="@string/default_emergency_app"
settings:keywords="@string/keywords_emergency_app" settings:keywords="@string/keywords_emergency_app"
android:fragment="com.android.settings.applications.defaultapps.DefaultEmergencyPicker"
android:order="-15"/> android:order="-15"/>
<com.android.settings.applications.DefaultNotificationAssistantPreference <Preference
android:key="default_notification_asst_app" android:key="default_notification_asst_app"
android:title="@string/default_notification_assistant" android:title="@string/default_notification_assistant"
android:fragment="com.android.settings.applications.defaultapps.DefaultNotificationAssistantPicker"
android:order="-14"/> android:order="-14"/>
<Preference <Preference
@@ -71,17 +79,21 @@
android:key="work_defaults" android:key="work_defaults"
android:title="@string/default_for_work"> android:title="@string/default_for_work">
<com.android.settings.applications.DefaultBrowserPreference <Preference
android:key="work_default_browser" android:key="work_default_browser"
android:title="@string/default_browser_title" android:title="@string/default_browser_title"
android:summary="@string/default_browser_title_none" android:summary="@string/default_browser_title_none"
settings:forWork="true"/> android:fragment="com.android.settings.applications.defaultapps.DefaultBrowserPicker">
<extra android:name="for_work" android:value="true"/>
</Preference>
<com.android.settings.applications.DefaultPhonePreference <Preference
android:key="work_default_phone_app" android:key="work_default_phone_app_new"
android:title="@string/default_phone_title" android:title="new phone pref work"
settings:keywords="@string/keywords_default_phone_app" android:fragment="com.android.settings.applications.defaultapps.DefaultPhonePicker"
settings:forWork="true"/> settings:keywords="@string/keywords_default_phone_app">
<extra android:name="for_work" android:value="true"/>
</Preference>
</com.android.settings.WorkOnlyCategory> </com.android.settings.WorkOnlyCategory>

View File

@@ -0,0 +1,20 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
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.
-->
<PreferenceScreen>
</PreferenceScreen>

View File

@@ -49,7 +49,11 @@ import java.util.List;
* Extends ListPreference to allow us to show the icons for a given list of applications. We do this * 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 * 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. * 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 class AppListPreference extends CustomListPreference {
public static final String ITEM_NONE_VALUE = ""; public static final String ITEM_NONE_VALUE = "";

View File

@@ -1,58 +0,0 @@
package com.android.settings;
import android.content.Context;
import android.support.v7.preference.PreferenceViewHolder;
import android.util.AttributeSet;
import android.util.Log;
import android.widget.Checkable;
/**
* A hybrid of AppListPreference and SwitchPreference, representing a preference which can be on or
* off but must have a selected value when turned on.
*
* It is invalid to show this preference when zero valid apps are present.
*/
public class AppListSwitchPreference extends AppListPreference {
private static final String TAG = "AppListSwitchPref";
private Checkable mSwitch;
public AppListSwitchPreference(Context context, AttributeSet attrs) {
super(context, attrs, 0, R.style.AppListSwitchPreference);
}
@Override
public void onBindViewHolder(PreferenceViewHolder view) {
super.onBindViewHolder(view);
mSwitch = (Checkable) view.findViewById(com.android.internal.R.id.switch_widget);
mSwitch.setChecked(getValue() != null);
}
@Override
protected void onClick() {
if (getValue() != null) {
// Turning off the current value.
if (callChangeListener(null)) {
setValue(null);
}
} else if (getEntryValues() == null || getEntryValues().length == 0) {
Log.e(TAG, "Attempting to show dialog with zero entries: " + getKey());
} else if (getEntryValues().length == 1) {
// Suppress the dialog and just toggle the preference with the only choice.
String value = getEntryValues()[0].toString();
if (callChangeListener(value)) {
setValue(value);
}
} else {
super.onClick();
}
}
@Override
public void setValue(String value) {
super.setValue(value);
if (mSwitch != null) {
mSwitch.setChecked(value != null);
}
}
}

View File

@@ -727,10 +727,6 @@ public abstract class SettingsPreferenceFragment extends InstrumentedPreferenceF
getActivity().setResult(result); getActivity().setResult(result);
} }
protected final Context getPrefContext() {
return getPreferenceManager().getContext();
}
public boolean startFragment(Fragment caller, String fragmentClass, int titleRes, public boolean startFragment(Fragment caller, String fragmentClass, int titleRes,
int requestCode, Bundle extras) { int requestCode, Bundle extras) {
final Activity activity = getActivity(); final Activity activity = getActivity();

View File

@@ -1,5 +1,5 @@
/* /*
* Copyright (C) 2016 The Android Open Source Project * Copyright (C) 2017 The Android Open Source Project
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
@@ -20,14 +20,20 @@ import android.provider.SearchIndexableResource;
import com.android.internal.logging.nano.MetricsProto.MetricsEvent; import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
import com.android.settings.R; import com.android.settings.R;
import com.android.settings.Utils; import com.android.settings.applications.defaultapps.DefaultBrowserPreferenceController;
import com.android.settings.applications.defaultapps.DefaultEmergencyPreferenceController;
import com.android.settings.applications.defaultapps.DefaultHomePreferenceController;
import com.android.settings.applications.defaultapps.DefaultPhonePreferenceController;
import com.android.settings.applications.defaultapps.DefaultSmsPreferenceController;
import com.android.settings.applications.defaultapps.DefaultWorkBrowserPreferenceController;
import com.android.settings.applications.defaultapps.DefaultWorkPhonePreferenceController;
import com.android.settings.core.PreferenceController; import com.android.settings.core.PreferenceController;
import com.android.settings.dashboard.DashboardFragment; import com.android.settings.dashboard.DashboardFragment;
import com.android.settings.overlay.FeatureFactory;
import com.android.settings.search.BaseSearchIndexProvider; import com.android.settings.search.BaseSearchIndexProvider;
import com.android.settings.search.Indexable; import com.android.settings.search.Indexable;
import com.android.settingslib.drawer.CategoryKey; import com.android.settingslib.drawer.CategoryKey;
import java.util.ArrayList;
import java.util.Arrays; import java.util.Arrays;
import java.util.List; import java.util.List;
@@ -47,14 +53,20 @@ public class AdvancedAppSettings extends DashboardFragment {
@Override @Override
protected int getPreferenceScreenResId() { protected int getPreferenceScreenResId() {
return mDashboardFeatureProvider.isEnabled() return R.xml.app_default_settings;
? R.xml.app_default_settings
: R.xml.advanced_apps;
} }
@Override @Override
protected List<PreferenceController> getPreferenceControllers(Context context) { protected List<PreferenceController> getPreferenceControllers(Context context) {
return null; final List<PreferenceController> controllers = new ArrayList<>();
controllers.add(new DefaultBrowserPreferenceController(context));
controllers.add(new DefaultWorkBrowserPreferenceController(context));
controllers.add(new DefaultPhonePreferenceController(context));
controllers.add(new DefaultWorkPhonePreferenceController(context));
controllers.add(new DefaultSmsPreferenceController(context));
controllers.add(new DefaultEmergencyPreferenceController(context));
controllers.add(new DefaultHomePreferenceController(context));
return controllers;
} }
@Override @Override
@@ -68,16 +80,8 @@ public class AdvancedAppSettings extends DashboardFragment {
public List<SearchIndexableResource> getXmlResourcesToIndex( public List<SearchIndexableResource> getXmlResourcesToIndex(
Context context, boolean enabled) { Context context, boolean enabled) {
final SearchIndexableResource sir = new SearchIndexableResource(context); final SearchIndexableResource sir = new SearchIndexableResource(context);
sir.xmlResId = FeatureFactory.getFactory(context) sir.xmlResId = R.xml.app_default_settings;
.getDashboardFeatureProvider(context).isEnabled()
? R.xml.app_default_settings
: R.xml.advanced_apps;
return Arrays.asList(sir); return Arrays.asList(sir);
} }
@Override
public List<String> getNonIndexableKeys(Context context) {
return Utils.getNonIndexable(R.xml.advanced_apps, context);
}
}; };
} }

View File

@@ -39,12 +39,6 @@ public class AppAndNotificationDashboardFragment extends DashboardFragment {
return MetricsProto.MetricsEvent.SETTINGS_APP_NOTIF_CATEGORY; return MetricsProto.MetricsEvent.SETTINGS_APP_NOTIF_CATEGORY;
} }
@Override
public void onAttach(Context context) {
super.onAttach(context);
mProgressiveDisclosureMixin.setTileLimit(3);
}
@Override @Override
protected String getCategoryKey() { protected String getCategoryKey() {
return CategoryKey.CATEGORY_APPS; return CategoryKey.CATEGORY_APPS;

View File

@@ -1,196 +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.content.Context;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.content.pm.ResolveInfo;
import android.net.Uri;
import android.os.Handler;
import android.os.UserHandle;
import android.text.TextUtils;
import android.util.AttributeSet;
import android.util.Log;
import com.android.internal.content.PackageMonitor;
import com.android.settings.AppListPreference;
import com.android.settings.R;
import java.util.ArrayList;
import java.util.List;
public class DefaultBrowserPreference extends AppListPreference {
private static final String TAG = "DefaultBrowserPref";
private static final boolean DEBUG = Log.isLoggable(TAG, Log.DEBUG);
private static final long DELAY_UPDATE_BROWSER_MILLIS = 500;
private static final Intent BROWSE_PROBE = new Intent()
.setAction(Intent.ACTION_VIEW)
.addCategory(Intent.CATEGORY_BROWSABLE)
.setData(Uri.parse("http:"));
private final Handler mHandler = new Handler();
private final PackageManager mPm;
public DefaultBrowserPreference(Context context, AttributeSet attrs) {
super(context, attrs);
mPm = context.getPackageManager();
refreshBrowserApps();
}
@Override
public void onAttached() {
super.onAttached();
updateDefaultBrowserPreference();
mPackageMonitor.register(getContext(), getContext().getMainLooper(), false);
}
@Override
public void onDetached() {
mPackageMonitor.unregister();
super.onDetached();
}
@Override
protected boolean persistString(String newValue) {
final CharSequence packageName = newValue;
if (TextUtils.isEmpty(packageName)) {
return false;
}
boolean result = mPm.setDefaultBrowserPackageNameAsUser(
packageName.toString(), mUserId);
if (result) {
setSummary("%s");
}
return result && super.persistString(newValue);
}
public void refreshBrowserApps() {
List<String> browsers = resolveBrowserApps();
setPackageNames(browsers.toArray(new String[browsers.size()]), null);
}
private void updateDefaultBrowserPreference() {
refreshBrowserApps();
final PackageManager pm = getContext().getPackageManager();
String packageName = pm.getDefaultBrowserPackageNameAsUser(mUserId);
if (!TextUtils.isEmpty(packageName)) {
// Check if the default Browser package is still there
final Intent intent = new Intent(BROWSE_PROBE)
.setPackage(packageName);
final ResolveInfo info = mPm.resolveActivityAsUser(intent, 0, mUserId);
if (info != null) {
setValue(packageName);
setSummary("%s");
} else {
setSummary(R.string.default_browser_title_none);
}
} else {
if (DEBUG) Log.d(TAG, "No default browser app.");
setSoleAppLabelAsSummary();
}
}
private List<String> resolveBrowserApps() {
List<String> result = new ArrayList<>();
// Resolve that intent and check that the handleAllWebDataURI boolean is set
List<ResolveInfo> list = mPm.queryIntentActivitiesAsUser(BROWSE_PROBE,
PackageManager.MATCH_ALL, mUserId);
final int count = list.size();
for (int i = 0; i < count; i++) {
ResolveInfo info = list.get(i);
if (info.activityInfo == null || result.contains(info.activityInfo.packageName)
|| !info.handleAllWebDataURI) {
continue;
}
result.add(info.activityInfo.packageName);
}
return result;
}
@Override
protected CharSequence getSoleAppLabel() {
// Resolve that intent and check that the handleAllWebDataURI boolean is set
List<ResolveInfo> list = mPm.queryIntentActivitiesAsUser(BROWSE_PROBE,
PackageManager.MATCH_ALL, mUserId);
if (list.size() == 1) {
return list.get(0).loadLabel(mPm);
}
return null;
}
private final Runnable mUpdateRunnable = new Runnable() {
@Override
public void run() {
updateDefaultBrowserPreference();
}
};
private final PackageMonitor mPackageMonitor = new PackageMonitor() {
@Override
public void onPackageAdded(String packageName, int uid) {
sendUpdate();
}
@Override
public void onPackageAppeared(String packageName, int reason) {
sendUpdate();
}
@Override
public void onPackageDisappeared(String packageName, int reason) {
sendUpdate();
}
@Override
public void onPackageRemoved(String packageName, int uid) {
sendUpdate();
}
private void sendUpdate() {
mHandler.postDelayed(mUpdateRunnable, DELAY_UPDATE_BROWSER_MILLIS);
}
};
public static boolean hasBrowserPreference(String pkg, Context context) {
Intent intent = new Intent();
intent.setAction(Intent.ACTION_VIEW);
intent.addCategory(Intent.CATEGORY_BROWSABLE);
intent.setData(Uri.parse("http:"));
intent.setPackage(pkg);
final List<ResolveInfo> resolveInfos =
context.getPackageManager().queryIntentActivities(intent, 0);
return resolveInfos != null && resolveInfos.size() != 0;
}
public static boolean isBrowserDefault(String pkg, Context context) {
String defaultPackage = context.getPackageManager()
.getDefaultBrowserPackageNameAsUser(UserHandle.myUserId());
return defaultPackage != null && defaultPackage.equals(pkg);
}
}

View File

@@ -1,172 +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.content.ContentResolver;
import android.content.Context;
import android.content.Intent;
import android.content.pm.ApplicationInfo;
import android.content.pm.PackageInfo;
import android.content.pm.PackageManager;
import android.content.pm.ResolveInfo;
import android.os.AsyncTask;
import android.provider.Settings;
import android.telephony.TelephonyManager;
import android.text.TextUtils;
import android.util.ArraySet;
import android.util.AttributeSet;
import com.android.settings.AppListPreference;
import com.android.settings.R;
import com.android.settings.SelfAvailablePreference;
import com.android.settings.Utils;
import java.util.List;
import java.util.Objects;
import java.util.Set;
/**
* A preference for choosing the default emergency app
*/
public class DefaultEmergencyPreference extends AppListPreference
implements SelfAvailablePreference {
private static final boolean DEFAULT_EMERGENCY_APP_IS_CONFIGURABLE = false;
private final ContentResolver mContentResolver;
public static final Intent QUERY_INTENT = new Intent(
TelephonyManager.ACTION_EMERGENCY_ASSISTANCE);
public DefaultEmergencyPreference(Context context, AttributeSet attrs) {
super(context, attrs);
mContentResolver = context.getContentResolver();
load();
}
@Override
protected CharSequence getConfirmationMessage(String value) {
return Utils.isPackageDirectBootAware(getContext(), value) ? null
: getContext().getText(R.string.direct_boot_unaware_dialog_message);
}
@Override
protected boolean persistString(String value) {
String previousValue = Settings.Secure.getString(mContentResolver,
Settings.Secure.EMERGENCY_ASSISTANCE_APPLICATION);
if (!TextUtils.isEmpty(value) && !Objects.equals(value, previousValue)) {
Settings.Secure.putString(mContentResolver,
Settings.Secure.EMERGENCY_ASSISTANCE_APPLICATION,
value);
}
setSummary(getEntry());
return true;
}
private void load() {
new AsyncTask<Void, Void, Set<String>>() {
@Override
protected Set<String> doInBackground(Void[] params) {
return resolveAssistPackageAndQueryApps();
}
@Override
protected void onPostExecute(Set<String> entries) {
String currentPkg = Settings.Secure.getString(mContentResolver,
Settings.Secure.EMERGENCY_ASSISTANCE_APPLICATION);
setPackageNames(entries.toArray(new String[entries.size()]), currentPkg);
}
}.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
}
private Set<String> resolveAssistPackageAndQueryApps() {
Set<String> packages = new ArraySet<>();
PackageManager packageManager = getContext().getPackageManager();
List<ResolveInfo> infos = packageManager.queryIntentActivities(QUERY_INTENT, 0);
PackageInfo bestMatch = null;
final int size = infos.size();
for (int i = 0; i < size; i++) {
ResolveInfo info = infos.get(i);
if (info == null || info.activityInfo == null
|| packages.contains(info.activityInfo.packageName)) {
continue;
}
String packageName = info.activityInfo.packageName;
packages.add(packageName);
PackageInfo packageInfo;
try {
packageInfo = packageManager.getPackageInfo(packageName, 0);
} catch (PackageManager.NameNotFoundException e) {
continue;
}
// Get earliest installed system app.
if (isSystemApp(packageInfo) && (bestMatch == null ||
bestMatch.firstInstallTime > packageInfo.firstInstallTime)) {
bestMatch = packageInfo;
}
}
String defaultPackage = Settings.Secure.getString(mContentResolver,
Settings.Secure.EMERGENCY_ASSISTANCE_APPLICATION);
boolean defaultMissing = TextUtils.isEmpty(defaultPackage)
|| !packages.contains(defaultPackage);
if (bestMatch != null && defaultMissing) {
Settings.Secure.putString(mContentResolver,
Settings.Secure.EMERGENCY_ASSISTANCE_APPLICATION,
bestMatch.packageName);
}
return packages;
}
private static boolean isCapable(Context context) {
return TelephonyManager.EMERGENCY_ASSISTANCE_ENABLED
&& context.getResources().getBoolean(
com.android.internal.R.bool.config_voice_capable);
}
private static boolean isSystemApp(PackageInfo info) {
return info.applicationInfo != null
&& (info.applicationInfo.flags & ApplicationInfo.FLAG_SYSTEM) != 0;
}
public boolean isAvailable(Context context) {
return DEFAULT_EMERGENCY_APP_IS_CONFIGURABLE
&& isCapable(context)
&& context.getPackageManager().resolveActivity(QUERY_INTENT, 0) != null;
}
public static boolean hasEmergencyPreference(String pkg, Context context) {
Intent i = new Intent(QUERY_INTENT);
i.setPackage(pkg);
final List<ResolveInfo> resolveInfos =
context.getPackageManager().queryIntentActivities(i, 0);
return resolveInfos != null && resolveInfos.size() != 0;
}
public static boolean isEmergencyDefault(String pkg, Context context) {
String defaultPackage = Settings.Secure.getString(context.getContentResolver(),
Settings.Secure.EMERGENCY_ASSISTANCE_APPLICATION);
return defaultPackage != null && defaultPackage.equals(pkg);
}
}

View File

@@ -1,158 +0,0 @@
/*
* Copyright (C) 2016 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.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.content.pm.ActivityInfo;
import android.content.pm.ApplicationInfo;
import android.content.pm.PackageManager;
import android.content.pm.ResolveInfo;
import android.content.pm.UserInfo;
import android.os.Build;
import android.os.UserManager;
import android.util.AttributeSet;
import com.android.settings.AppListPreference;
import com.android.settings.R;
import java.util.ArrayList;
import java.util.List;
public class DefaultHomePreference extends AppListPreference {
private final ArrayList<ComponentName> mAllHomeComponents = new ArrayList<>();
private final IntentFilter mHomeFilter;
private final String mPackageName;
public DefaultHomePreference(Context context, AttributeSet attrs) {
super(context, attrs);
mPackageName = getContext().getPackageName();
mHomeFilter = new IntentFilter(Intent.ACTION_MAIN);
mHomeFilter.addCategory(Intent.CATEGORY_HOME);
mHomeFilter.addCategory(Intent.CATEGORY_DEFAULT);
refreshHomeOptions();
}
@Override
public void performClick() {
refreshHomeOptions();
super.performClick();
}
@Override
protected boolean persistString(String value) {
if (value != null) {
ComponentName component = ComponentName.unflattenFromString(value);
getContext().getPackageManager().replacePreferredActivity(mHomeFilter,
IntentFilter.MATCH_CATEGORY_EMPTY,
mAllHomeComponents.toArray(new ComponentName[0]), component);
setSummary(getEntry());
} else {
// If there is only 1 launcher, use its label as summary text.
setSoleAppLabelAsSummary();
}
return super.persistString(value);
}
@Override
protected CharSequence getSoleAppLabel() {
final PackageManager pm = getContext().getPackageManager();
final List<ResolveInfo> homeActivities = new ArrayList<>();
final List<CharSequence> appLabels = new ArrayList<>();
pm.getHomeActivities(homeActivities);
for (ResolveInfo candidate : homeActivities) {
final ActivityInfo info = candidate.activityInfo;
if (info.packageName.equals(mPackageName)) {
continue;
}
appLabels.add(info.loadLabel(pm));
}
return appLabels.size() == 1 ? appLabels.get(0) : null;
}
public void refreshHomeOptions() {
ArrayList<ResolveInfo> homeActivities = new ArrayList<>();
PackageManager pm = getContext().getPackageManager();
ComponentName currentDefaultHome = pm.getHomeActivities(homeActivities);
ArrayList<ComponentName> components = new ArrayList<>();
mAllHomeComponents.clear();
List<CharSequence> summaries = new ArrayList<>();
boolean mustSupportManagedProfile = hasManagedProfile();
for (ResolveInfo candidate : homeActivities) {
final ActivityInfo info = candidate.activityInfo;
ComponentName activityName = new ComponentName(info.packageName, info.name);
mAllHomeComponents.add(activityName);
if (info.packageName.equals(mPackageName)) {
continue;
}
components.add(activityName);
if (mustSupportManagedProfile && !launcherHasManagedProfilesFeature(candidate, pm)) {
summaries.add(getContext().getString(R.string.home_work_profile_not_supported));
} else {
summaries.add(null);
}
}
setComponentNames(components.toArray(new ComponentName[0]), currentDefaultHome,
summaries.toArray(new CharSequence[0]));
}
private boolean launcherHasManagedProfilesFeature(ResolveInfo resolveInfo, PackageManager pm) {
try {
ApplicationInfo appInfo = pm.getApplicationInfo(
resolveInfo.activityInfo.packageName, 0 /* default flags */);
return versionNumberAtLeastL(appInfo.targetSdkVersion);
} catch (PackageManager.NameNotFoundException e) {
return false;
}
}
private boolean versionNumberAtLeastL(int versionNumber) {
return versionNumber >= Build.VERSION_CODES.LOLLIPOP;
}
private boolean hasManagedProfile() {
UserManager userManager = getContext().getSystemService(UserManager.class);
List<UserInfo> profiles = userManager.getProfiles(getContext().getUserId());
for (UserInfo userInfo : profiles) {
if (userInfo.isManagedProfile()) return true;
}
return false;
}
public static boolean hasHomePreference(String pkg, Context context) {
ArrayList<ResolveInfo> homeActivities = new ArrayList<ResolveInfo>();
PackageManager pm = context.getPackageManager();
pm.getHomeActivities(homeActivities);
for (int i = 0; i < homeActivities.size(); i++) {
if (homeActivities.get(i).activityInfo.packageName.equals(pkg)) {
return true;
}
}
return false;
}
public static boolean isHomeDefault(String pkg, Context context) {
ArrayList<ResolveInfo> homeActivities = new ArrayList<ResolveInfo>();
PackageManager pm = context.getPackageManager();
ComponentName def = pm.getHomeActivities(homeActivities);
return def != null && def.getPackageName().equals(pkg);
}
}

View File

@@ -1,105 +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.content.Context;
import android.os.UserHandle;
import android.os.UserManager;
import android.telecom.DefaultDialerManager;
import android.telecom.TelecomManager;
import android.telephony.TelephonyManager;
import android.text.TextUtils;
import android.util.AttributeSet;
import com.android.settings.AppListPreference;
import com.android.settings.R;
import com.android.settings.SelfAvailablePreference;
import com.android.settings.Utils;
import java.util.List;
import java.util.Objects;
public class DefaultPhonePreference extends AppListPreference implements SelfAvailablePreference {
public DefaultPhonePreference(Context context, AttributeSet attrs) {
super(context, attrs);
loadDialerApps();
}
@Override
protected CharSequence getConfirmationMessage(String value) {
return Utils.isPackageDirectBootAware(getContext(), value) ? null
: getContext().getText(R.string.direct_boot_unaware_dialog_message);
}
@Override
protected boolean persistString(String value) {
if (!TextUtils.isEmpty(value) && !Objects.equals(value, getDefaultPackage())) {
DefaultDialerManager.setDefaultDialerApplication(getContext(), value, mUserId);
}
setSummary(getEntry());
return true;
}
private void loadDialerApps() {
List<String> dialerPackages =
DefaultDialerManager.getInstalledDialerApplications(getContext(), mUserId);
final String[] dialers = new String[dialerPackages.size()];
for (int i = 0; i < dialerPackages.size(); i++) {
dialers[i] = dialerPackages.get(i);
}
setPackageNames(dialers, getDefaultPackage(), getSystemPackage());
}
private String getDefaultPackage() {
return DefaultDialerManager.getDefaultDialerApplication(getContext(), mUserId);
}
private String getSystemPackage() {
TelecomManager tm = TelecomManager.from(getContext());
return tm.getSystemDialerPackage();
}
@Override
public boolean isAvailable(Context context) {
final TelephonyManager tm =
(TelephonyManager) context.getSystemService(Context.TELEPHONY_SERVICE);
if (!tm.isVoiceCapable()) {
return false;
}
final UserManager um = (UserManager) context.getSystemService(Context.USER_SERVICE);
final boolean hasUserRestriction =
um.hasUserRestriction(UserManager.DISALLOW_OUTGOING_CALLS);
final CharSequence[] entries = getEntries();
return !hasUserRestriction
&& entries != null
&& entries.length > 0;
}
public static boolean hasPhonePreference(String pkg, Context context) {
List<String> dialerPackages =
DefaultDialerManager.getInstalledDialerApplications(context, UserHandle.myUserId());
return dialerPackages.contains(pkg);
}
public static boolean isPhoneDefault(String pkg, Context context) {
String def = DefaultDialerManager.getDefaultDialerApplication(context,
UserHandle.myUserId());
return def != null && def.equals(pkg);
}
}

View File

@@ -1,103 +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.content.ComponentName;
import android.content.Context;
import android.os.UserHandle;
import android.os.UserManager;
import android.telephony.TelephonyManager;
import android.text.TextUtils;
import android.util.AttributeSet;
import com.android.internal.telephony.SmsApplication;
import com.android.internal.telephony.SmsApplication.SmsApplicationData;
import com.android.settings.AppListPreference;
import com.android.settings.R;
import com.android.settings.SelfAvailablePreference;
import com.android.settings.Utils;
import java.util.Collection;
import java.util.Objects;
public class DefaultSmsPreference extends AppListPreference implements SelfAvailablePreference {
public DefaultSmsPreference(Context context, AttributeSet attrs) {
super(context, attrs);
loadSmsApps();
}
private void loadSmsApps() {
Collection<SmsApplicationData> smsApplications =
SmsApplication.getApplicationCollection(getContext());
int count = smsApplications.size();
String[] packageNames = new String[count];
int i = 0;
for (SmsApplicationData smsApplicationData : smsApplications) {
packageNames[i++] = smsApplicationData.mPackageName;
}
setPackageNames(packageNames, getDefaultPackage());
}
private String getDefaultPackage() {
ComponentName appName = SmsApplication.getDefaultSmsApplication(getContext(), true);
if (appName != null) {
return appName.getPackageName();
}
return null;
}
@Override
protected CharSequence getConfirmationMessage(String value) {
return Utils.isPackageDirectBootAware(getContext(), value) ? null
: getContext().getText(R.string.direct_boot_unaware_dialog_message);
}
@Override
protected boolean persistString(String value) {
if (!TextUtils.isEmpty(value) && !Objects.equals(value, getDefaultPackage())) {
SmsApplication.setDefaultApplication(value, getContext());
}
setSummary(getEntry());
return true;
}
@Override
public boolean isAvailable(Context context) {
boolean isRestrictedUser =
UserManager.get(context)
.getUserInfo(UserHandle.myUserId()).isRestricted();
TelephonyManager tm =
(TelephonyManager) context.getSystemService(Context.TELEPHONY_SERVICE);
return !isRestrictedUser && tm.isSmsCapable();
}
public static boolean hasSmsPreference(String pkg, Context context) {
Collection<SmsApplicationData> smsApplications =
SmsApplication.getApplicationCollection(context);
for (SmsApplicationData data : smsApplications) {
if (data.mPackageName.equals(pkg)) {
return true;
}
}
return false;
}
public static boolean isSmsDefault(String pkg, Context context) {
ComponentName appName = SmsApplication.getDefaultSmsApplication(context, true);
return appName != null && appName.getPackageName().equals(pkg);
}
}

View File

@@ -21,8 +21,6 @@ import android.app.Activity;
import android.app.ActivityManager; import android.app.ActivityManager;
import android.app.AlertDialog; import android.app.AlertDialog;
import android.app.LoaderManager.LoaderCallbacks; import android.app.LoaderManager.LoaderCallbacks;
import android.app.Notification;
import android.app.NotificationManager;
import android.app.admin.DevicePolicyManager; import android.app.admin.DevicePolicyManager;
import android.content.ActivityNotFoundException; import android.content.ActivityNotFoundException;
import android.content.BroadcastReceiver; import android.content.BroadcastReceiver;
@@ -52,8 +50,6 @@ import android.os.RemoteException;
import android.os.ServiceManager; import android.os.ServiceManager;
import android.os.UserHandle; import android.os.UserHandle;
import android.os.UserManager; import android.os.UserManager;
import android.provider.Settings;
import android.service.notification.NotificationListenerService.Ranking;
import android.support.annotation.VisibleForTesting; import android.support.annotation.VisibleForTesting;
import android.support.v7.preference.Preference; import android.support.v7.preference.Preference;
import android.support.v7.preference.Preference.OnPreferenceClickListener; import android.support.v7.preference.Preference.OnPreferenceClickListener;
@@ -78,7 +74,6 @@ import android.widget.TextView;
import com.android.internal.logging.nano.MetricsProto.MetricsEvent; import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
import com.android.internal.os.BatterySipper; import com.android.internal.os.BatterySipper;
import com.android.internal.os.BatteryStatsHelper; import com.android.internal.os.BatteryStatsHelper;
import com.android.internal.widget.LockPatternUtils;
import com.android.settings.AppHeader; import com.android.settings.AppHeader;
import com.android.settings.DeviceAdminAdd; import com.android.settings.DeviceAdminAdd;
import com.android.settings.R; import com.android.settings.R;
@@ -86,6 +81,11 @@ import com.android.settings.SettingsActivity;
import com.android.settings.SettingsPreferenceFragment; import com.android.settings.SettingsPreferenceFragment;
import com.android.settings.Utils; import com.android.settings.Utils;
import com.android.settings.applications.PermissionsSummaryHelper.PermissionsResultCallback; import com.android.settings.applications.PermissionsSummaryHelper.PermissionsResultCallback;
import com.android.settings.applications.defaultapps.DefaultBrowserPreferenceController;
import com.android.settings.applications.defaultapps.DefaultEmergencyPreferenceController;
import com.android.settings.applications.defaultapps.DefaultHomePreferenceController;
import com.android.settings.applications.defaultapps.DefaultPhonePreferenceController;
import com.android.settings.applications.defaultapps.DefaultSmsPreferenceController;
import com.android.settings.dashboard.DashboardFeatureProvider; import com.android.settings.dashboard.DashboardFeatureProvider;
import com.android.settings.datausage.AppDataUsage; import com.android.settings.datausage.AppDataUsage;
import com.android.settings.datausage.DataUsageList; import com.android.settings.datausage.DataUsageList;
@@ -908,27 +908,28 @@ public class InstalledAppDetails extends AppInfoBase
return; return;
} }
final PreferenceScreen screen = getPreferenceScreen(); final PreferenceScreen screen = getPreferenceScreen();
if (DefaultHomePreference.hasHomePreference(mPackageName, getContext())) { final Context context = getContext();
if (DefaultHomePreferenceController.hasHomePreference(mPackageName, context)) {
screen.addPreference(new ShortcutPreference(getPrefContext(), screen.addPreference(new ShortcutPreference(getPrefContext(),
AdvancedAppSettings.class, "default_home", R.string.home_app, AdvancedAppSettings.class, "default_home", R.string.home_app,
R.string.configure_apps)); R.string.configure_apps));
} }
if (DefaultBrowserPreference.hasBrowserPreference(mPackageName, getContext())) { if (DefaultBrowserPreferenceController.hasBrowserPreference(mPackageName, context)) {
screen.addPreference(new ShortcutPreference(getPrefContext(), screen.addPreference(new ShortcutPreference(getPrefContext(),
AdvancedAppSettings.class, "default_browser", R.string.default_browser_title, AdvancedAppSettings.class, "default_browser", R.string.default_browser_title,
R.string.configure_apps)); R.string.configure_apps));
} }
if (DefaultPhonePreference.hasPhonePreference(mPackageName, getContext())) { if (DefaultPhonePreferenceController.hasPhonePreference(mPackageName, context)) {
screen.addPreference(new ShortcutPreference(getPrefContext(), screen.addPreference(new ShortcutPreference(getPrefContext(),
AdvancedAppSettings.class, "default_phone_app", R.string.default_phone_title, AdvancedAppSettings.class, "default_phone_app", R.string.default_phone_title,
R.string.configure_apps)); R.string.configure_apps));
} }
if (DefaultEmergencyPreference.hasEmergencyPreference(mPackageName, getContext())) { if (DefaultEmergencyPreferenceController.hasEmergencyPreference(mPackageName, context)) {
screen.addPreference(new ShortcutPreference(getPrefContext(), screen.addPreference(new ShortcutPreference(getPrefContext(),
AdvancedAppSettings.class, "default_emergency_app", AdvancedAppSettings.class, "default_emergency_app",
R.string.default_emergency_app, R.string.configure_apps)); R.string.default_emergency_app, R.string.configure_apps));
} }
if (DefaultSmsPreference.hasSmsPreference(mPackageName, getContext())) { if (DefaultSmsPreferenceController.hasSmsPreference(mPackageName, context)) {
screen.addPreference(new ShortcutPreference(getPrefContext(), screen.addPreference(new ShortcutPreference(getPrefContext(),
AdvancedAppSettings.class, "default_sms_app", R.string.sms_application_title, AdvancedAppSettings.class, "default_sms_app", R.string.sms_application_title,
R.string.configure_apps)); R.string.configure_apps));
@@ -1021,29 +1022,33 @@ public class InstalledAppDetails extends AppInfoBase
} }
private void updateDynamicPrefs() { private void updateDynamicPrefs() {
final Context context = getContext();
Preference pref = findPreference("default_home"); Preference pref = findPreference("default_home");
if (pref != null) { if (pref != null) {
pref.setSummary(DefaultHomePreference.isHomeDefault(mPackageName, getContext()) pref.setSummary(DefaultHomePreferenceController.isHomeDefault(mPackageName, context)
? R.string.yes : R.string.no); ? R.string.yes : R.string.no);
} }
pref = findPreference("default_browser"); pref = findPreference("default_browser");
if (pref != null) { if (pref != null) {
pref.setSummary(DefaultBrowserPreference.isBrowserDefault(mPackageName, getContext()) pref.setSummary(
DefaultBrowserPreferenceController.isBrowserDefault(mPackageName, context)
? R.string.yes : R.string.no); ? R.string.yes : R.string.no);
} }
pref = findPreference("default_phone_app"); pref = findPreference("default_phone_app");
if (pref != null) { if (pref != null) {
pref.setSummary(DefaultPhonePreference.isPhoneDefault(mPackageName, getContext()) pref.setSummary(
DefaultPhonePreferenceController.isPhoneDefault(mPackageName, context)
? R.string.yes : R.string.no); ? R.string.yes : R.string.no);
} }
pref = findPreference("default_emergency_app"); pref = findPreference("default_emergency_app");
if (pref != null) { if (pref != null) {
pref.setSummary(DefaultEmergencyPreference.isEmergencyDefault(mPackageName, pref.setSummary(DefaultEmergencyPreferenceController.isEmergencyDefault(mPackageName,
getContext()) ? R.string.yes : R.string.no); getContext()) ? R.string.yes : R.string.no);
} }
pref = findPreference("default_sms_app"); pref = findPreference("default_sms_app");
if (pref != null) { if (pref != null) {
pref.setSummary(DefaultSmsPreference.isSmsDefault(mPackageName, getContext()) pref.setSummary(DefaultSmsPreferenceController.isSmsDefault(mPackageName, context)
? R.string.yes : R.string.no); ? R.string.yes : R.string.no);
} }
pref = findPreference("system_alert_window"); pref = findPreference("system_alert_window");

View File

@@ -16,7 +16,9 @@
package com.android.settings.applications; package com.android.settings.applications;
import android.content.ComponentName;
import android.content.Intent; import android.content.Intent;
import android.content.IntentFilter;
import android.content.pm.ApplicationInfo; import android.content.pm.ApplicationInfo;
import android.content.pm.PackageManager; import android.content.pm.PackageManager;
import android.content.pm.ResolveInfo; import android.content.pm.ResolveInfo;
@@ -58,11 +60,42 @@ public interface PackageManagerWrapper {
*/ */
List<ResolveInfo> queryIntentActivitiesAsUser(Intent intent, int flags, int userId); List<ResolveInfo> queryIntentActivitiesAsUser(Intent intent, int flags, int userId);
/** /**
* Calls {@code PackageManager.getInstallReason()}. * Calls {@code PackageManager.getInstallReason()}.
* *
* @see android.content.pm.PackageManager#getInstallReason * @see android.content.pm.PackageManager#getInstallReason
*/ */
int getInstallReason(String packageName, UserHandle user); int getInstallReason(String packageName, UserHandle user);
/**
* Calls {@code PackageManager.getApplicationInfoAsUser}
*/
ApplicationInfo getApplicationInfoAsUser(String packageName, int i, int userId)
throws PackageManager.NameNotFoundException;
/**
* Calls {@code PackageManager.setDefaultBrowserPackageNameAsUser}
*/
boolean setDefaultBrowserPackageNameAsUser(String packageName, int userId);
/**
* Calls {@code PackageManager.getDefaultBrowserPackageNameAsUser}
*/
String getDefaultBrowserPackageNameAsUser(int userId);
/**
* Calls {@code PackageManager.getHomeActivities}
*/
ComponentName getHomeActivities(List<ResolveInfo> homeActivities);
/**
* Calls {@code PackageManager.queryIntentServicesAsUser}
*/
List<ResolveInfo> queryIntentServicesAsUser(Intent intent, int i, int user);
/**
* Calls {@code PackageManager.replacePreferredActivity}
*/
void replacePreferredActivity(IntentFilter homeFilter, int matchCategoryEmpty,
ComponentName[] componentNames, ComponentName component);
} }

View File

@@ -16,7 +16,9 @@
package com.android.settings.applications; package com.android.settings.applications;
import android.content.ComponentName;
import android.content.Intent; import android.content.Intent;
import android.content.IntentFilter;
import android.content.pm.ApplicationInfo; import android.content.pm.ApplicationInfo;
import android.content.pm.PackageManager; import android.content.pm.PackageManager;
import android.content.pm.ResolveInfo; import android.content.pm.ResolveInfo;
@@ -56,4 +58,36 @@ public class PackageManagerWrapperImpl implements PackageManagerWrapper {
public int getInstallReason(String packageName, UserHandle user) { public int getInstallReason(String packageName, UserHandle user) {
return mPm.getInstallReason(packageName, user); return mPm.getInstallReason(packageName, user);
} }
@Override
public ApplicationInfo getApplicationInfoAsUser(String packageName, int i, int userId)
throws PackageManager.NameNotFoundException {
return mPm.getApplicationInfoAsUser(packageName, i, userId);
}
@Override
public boolean setDefaultBrowserPackageNameAsUser(String packageName, int userId) {
return mPm.setDefaultBrowserPackageNameAsUser(packageName, userId);
}
@Override
public String getDefaultBrowserPackageNameAsUser(int userId) {
return mPm.getDefaultBrowserPackageNameAsUser(userId);
}
@Override
public ComponentName getHomeActivities(List<ResolveInfo> homeActivities) {
return mPm.getHomeActivities(homeActivities);
}
@Override
public List<ResolveInfo> queryIntentServicesAsUser(Intent intent, int i, int user) {
return mPm.queryIntentServicesAsUser(intent, i, user);
}
@Override
public void replacePreferredActivity(IntentFilter homeFilter, int matchCategoryEmpty,
ComponentName[] componentNames, ComponentName component) {
mPm.replacePreferredActivity(homeFilter, matchCategoryEmpty, componentNames, component);
}
} }

View File

@@ -0,0 +1,108 @@
/*
* 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.defaultapps;
import android.app.AppGlobals;
import android.content.ComponentName;
import android.content.pm.ActivityInfo;
import android.content.pm.ApplicationInfo;
import android.content.pm.PackageItemInfo;
import android.content.pm.PackageManager;
import android.graphics.drawable.Drawable;
import android.os.RemoteException;
import android.os.UserHandle;
/**
* Data model representing an app in DefaultAppPicker UI.
*/
class DefaultAppInfo {
public final int userId;
public final ComponentName componentName;
public final PackageItemInfo packageItemInfo;
public final String summary;
public DefaultAppInfo(int uid, ComponentName cn, String summary) {
packageItemInfo = null;
userId = uid;
componentName = cn;
this.summary = summary;
}
public DefaultAppInfo(PackageItemInfo info) {
userId = UserHandle.myUserId();
packageItemInfo = info;
componentName = null;
summary = null;
}
public CharSequence loadLabel(PackageManager pm) {
if (componentName != null) {
try {
final ActivityInfo actInfo = AppGlobals.getPackageManager().getActivityInfo(
componentName, 0, userId);
if (actInfo != null) {
return actInfo.loadLabel(pm);
} else {
final ApplicationInfo appInfo = pm.getApplicationInfoAsUser(
componentName.getPackageName(), 0, userId);
return appInfo.loadLabel(pm);
}
} catch (RemoteException | PackageManager.NameNotFoundException e) {
return null;
}
} else if (packageItemInfo != null) {
return packageItemInfo.loadLabel(pm);
} else {
return null;
}
}
public Drawable loadIcon(PackageManager pm) {
if (componentName != null) {
try {
final ActivityInfo actInfo = AppGlobals.getPackageManager().getActivityInfo(
componentName, 0, userId);
if (actInfo != null) {
return actInfo.loadIcon(pm);
} else {
final ApplicationInfo appInfo = pm.getApplicationInfoAsUser(
componentName.getPackageName(), 0, userId);
return appInfo.loadIcon(pm);
}
} catch (RemoteException | PackageManager.NameNotFoundException e) {
return null;
}
}
if (packageItemInfo != null) {
return packageItemInfo.loadIcon(pm);
} else {
return null;
}
}
public String getKey() {
if (componentName != null) {
return componentName.flattenToString();
} else if (packageItemInfo != null) {
return packageItemInfo.packageName;
} else {
return null;
}
}
}

View File

@@ -0,0 +1,228 @@
/*
* 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.defaultapps;
import android.app.Activity;
import android.app.AlertDialog;
import android.app.Dialog;
import android.app.DialogFragment;
import android.app.Fragment;
import android.content.Context;
import android.content.DialogInterface;
import android.os.Bundle;
import android.os.UserHandle;
import android.os.UserManager;
import android.support.annotation.VisibleForTesting;
import android.support.v7.preference.Preference;
import android.support.v7.preference.PreferenceScreen;
import android.text.TextUtils;
import android.util.ArrayMap;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import com.android.internal.logging.nano.MetricsProto;
import com.android.settings.R;
import com.android.settings.Utils;
import com.android.settings.applications.PackageManagerWrapper;
import com.android.settings.applications.PackageManagerWrapperImpl;
import com.android.settings.core.InstrumentedPreferenceFragment;
import com.android.settings.core.instrumentation.InstrumentedDialogFragment;
import com.android.settings.widget.RadioButtonPreference;
import java.util.List;
import java.util.Map;
/**
* A generic app picker fragment that shows a list of app as radio button group.
*/
public abstract class DefaultAppPickerFragment extends InstrumentedPreferenceFragment implements
RadioButtonPreference.OnClickListener {
@VisibleForTesting(otherwise = VisibleForTesting.PRIVATE)
static final String EXTRA_FOR_WORK = "for_work";
private final Map<String, DefaultAppInfo> mCandidates = new ArrayMap<>();
protected PackageManagerWrapper mPm;
protected UserManager mUserManager;
protected int mUserId;
@Override
public void onAttach(Context context) {
super.onAttach(context);
mPm = new PackageManagerWrapperImpl(context.getPackageManager());
mUserManager = (UserManager) context.getSystemService(Context.USER_SERVICE);
final Bundle arguments = getArguments();
boolean mForWork = false;
if (arguments != null) {
mForWork = arguments.getBoolean(EXTRA_FOR_WORK);
}
final UserHandle managedProfile = Utils.getManagedProfile(mUserManager);
mUserId = mForWork && managedProfile != null
? managedProfile.getIdentifier()
: UserHandle.myUserId();
}
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
final View view = super.onCreateView(inflater, container, savedInstanceState);
setHasOptionsMenu(true);
return view;
}
@Override
public void onCreatePreferences(Bundle savedInstanceState, String rootKey) {
super.onCreatePreferences(savedInstanceState, rootKey);
addPreferencesFromResource(R.xml.app_picker_prefs);
mCandidates.clear();
final List<DefaultAppInfo> candidateList = getCandidates();
if (candidateList != null) {
for (DefaultAppInfo info : candidateList) {
mCandidates.put(info.getKey(), info);
}
}
final String defaultAppKey = getDefaultAppKey();
final String systemDefaultAppKey = getSystemDefaultAppKey();
final PreferenceScreen screen = getPreferenceScreen();
screen.removeAll();
if (shouldShowItemNone()) {
final RadioButtonPreference nonePref = new RadioButtonPreference(getPrefContext());
nonePref.setIcon(R.drawable.ic_remove_circle);
nonePref.setTitle(R.string.app_list_preference_none);
nonePref.setChecked(TextUtils.isEmpty(defaultAppKey));
nonePref.setOnClickListener(this);
screen.addPreference(nonePref);
}
for (Map.Entry<String, DefaultAppInfo> app : mCandidates.entrySet()) {
final RadioButtonPreference pref = new RadioButtonPreference(getPrefContext());
final String appKey = app.getKey();
pref.setTitle(app.getValue().loadLabel(mPm.getPackageManager()));
pref.setIcon(app.getValue().loadIcon(mPm.getPackageManager()));
pref.setKey(appKey);
if (TextUtils.equals(defaultAppKey, appKey)) {
pref.setChecked(true);
}
if (TextUtils.equals(systemDefaultAppKey, appKey)) {
pref.setSummary(R.string.system_app);
}
pref.setOnClickListener(this);
screen.addPreference(pref);
}
}
@Override
public void onRadioButtonClicked(RadioButtonPreference selected) {
final String selectedKey = selected.getKey();
final String confirmationMessage = getConfirmationMessage(mCandidates.get(selectedKey));
final Activity activity = getActivity();
if (TextUtils.isEmpty(confirmationMessage)) {
onRadioButtonConfirmed(selectedKey);
} else if (activity != null) {
final DialogFragment fragment = ConfirmationDialogFragment.newInstance(
this, selectedKey, confirmationMessage);
fragment.show(activity.getFragmentManager(), ConfirmationDialogFragment.TAG);
}
}
private void onRadioButtonConfirmed(String selectedKey) {
final boolean success = setDefaultAppKey(selectedKey);
if (success) {
final PreferenceScreen screen = getPreferenceScreen();
if (screen != null) {
final int count = screen.getPreferenceCount();
for (int i = 0; i < count; i++) {
final Preference pref = screen.getPreference(i);
if (pref instanceof RadioButtonPreference) {
final RadioButtonPreference radioPref = (RadioButtonPreference) pref;
final boolean newCheckedState =
TextUtils.equals(pref.getKey(), selectedKey);
if (radioPref.isChecked() != newCheckedState) {
radioPref.setChecked(TextUtils.equals(pref.getKey(), selectedKey));
}
}
}
}
}
}
protected boolean shouldShowItemNone() {
return false;
}
protected String getSystemDefaultAppKey() {
return null;
}
protected abstract List<DefaultAppInfo> getCandidates();
protected abstract String getDefaultAppKey();
protected abstract boolean setDefaultAppKey(String key);
protected String getConfirmationMessage(DefaultAppInfo appInfo) {
return null;
}
public static class ConfirmationDialogFragment extends InstrumentedDialogFragment
implements DialogInterface.OnClickListener {
public static final String TAG = "DefaultAppConfirm";
public static final String EXTRA_KEY = "extra_key";
public static final String EXTRA_MESSAGE = "extra_message";
@Override
public int getMetricsCategory() {
return MetricsProto.MetricsEvent.DEFAULT_APP_PICKER_CONFIRMATION_DIALOG;
}
public static ConfirmationDialogFragment newInstance(DefaultAppPickerFragment parent,
String key, String message) {
final ConfirmationDialogFragment fragment = new ConfirmationDialogFragment();
final Bundle argument = new Bundle();
argument.putString(EXTRA_KEY, key);
argument.putString(EXTRA_MESSAGE, message);
fragment.setArguments(argument);
fragment.setTargetFragment(parent, 0);
return fragment;
}
@Override
public Dialog onCreateDialog(Bundle savedInstanceState) {
final Bundle bundle = getArguments();
final AlertDialog.Builder builder = new AlertDialog.Builder(getActivity())
.setMessage(bundle.getString(EXTRA_MESSAGE))
.setPositiveButton(android.R.string.ok, this)
.setNegativeButton(android.R.string.cancel, null);
return builder.create();
}
@Override
public void onClick(DialogInterface dialog, int which) {
final Fragment fragment = getTargetFragment();
if (fragment instanceof DefaultAppPickerFragment) {
final Bundle bundle = getArguments();
((DefaultAppPickerFragment) fragment).onRadioButtonConfirmed(
bundle.getString(EXTRA_KEY));
}
}
}
}

View File

@@ -0,0 +1,61 @@
/*
* 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.defaultapps;
import android.content.Context;
import android.os.UserHandle;
import android.os.UserManager;
import android.support.v7.preference.Preference;
import android.text.TextUtils;
import android.util.Log;
import com.android.settings.applications.PackageManagerWrapper;
import com.android.settings.applications.PackageManagerWrapperImpl;
import com.android.settings.core.PreferenceController;
public abstract class DefaultAppPreferenceController extends PreferenceController {
private static final String TAG = "DefaultAppPrefControl";
protected final PackageManagerWrapper mPackageManager;
protected final UserManager mUserManager;
protected int mUserId;
public DefaultAppPreferenceController(Context context) {
super(context);
mPackageManager = new PackageManagerWrapperImpl(context.getPackageManager());
mUserManager = (UserManager) context.getSystemService(Context.USER_SERVICE);
mUserId = UserHandle.myUserId();
}
@Override
public void updateState(Preference preference) {
final DefaultAppInfo app = getDefaultAppInfo();
CharSequence defaultAppLabel = null;
if (app != null) {
defaultAppLabel = app.loadLabel(mPackageManager.getPackageManager());
}
if (!TextUtils.isEmpty(defaultAppLabel)) {
preference.setSummary(defaultAppLabel);
} else {
Log.d(TAG, "No default app");
}
}
protected abstract DefaultAppInfo getDefaultAppInfo();
}

View File

@@ -0,0 +1,71 @@
/*
* 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.defaultapps;
import android.content.pm.PackageManager;
import android.content.pm.ResolveInfo;
import com.android.internal.logging.nano.MetricsProto;
import java.util.ArrayList;
import java.util.List;
/**
* Fragment for choosing default browser.
*/
public class DefaultBrowserPicker extends DefaultAppPickerFragment {
@Override
public int getMetricsCategory() {
return MetricsProto.MetricsEvent.DEFAULT_BROWSER_PICKER;
}
@Override
protected String getDefaultAppKey() {
return mPm.getDefaultBrowserPackageNameAsUser(mUserId);
}
@Override
protected boolean setDefaultAppKey(String packageName) {
return mPm.setDefaultBrowserPackageNameAsUser(packageName, mUserId);
}
@Override
protected List<DefaultAppInfo> getCandidates() {
final List<DefaultAppInfo> candidates = new ArrayList<>();
// Resolve that intent and check that the handleAllWebDataURI boolean is set
final List<ResolveInfo> list = mPm.queryIntentActivitiesAsUser(
DefaultBrowserPreferenceController.BROWSE_PROBE, PackageManager.MATCH_ALL, mUserId);
final int count = list.size();
for (int i = 0; i < count; i++) {
ResolveInfo info = list.get(i);
if (info.activityInfo == null || !info.handleAllWebDataURI) {
continue;
}
try {
candidates.add(new DefaultAppInfo(
mPm.getApplicationInfoAsUser(info.activityInfo.packageName, 0, mUserId)));
} catch (PackageManager.NameNotFoundException e) {
// Skip unknown packages.
}
}
return candidates;
}
}

View File

@@ -0,0 +1,104 @@
/*
* 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.defaultapps;
import android.content.Context;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.content.pm.ResolveInfo;
import android.net.Uri;
import android.os.UserHandle;
import android.support.v7.preference.Preference;
import android.text.TextUtils;
import java.util.List;
public class DefaultBrowserPreferenceController extends DefaultAppPreferenceController {
static final Intent BROWSE_PROBE = new Intent()
.setAction(Intent.ACTION_VIEW)
.addCategory(Intent.CATEGORY_BROWSABLE)
.setData(Uri.parse("http:"));
public DefaultBrowserPreferenceController(Context context) {
super(context);
}
@Override
public boolean isAvailable() {
return true;
}
@Override
public String getPreferenceKey() {
return "default_browser";
}
@Override
public void updateState(Preference preference) {
super.updateState(preference);
final DefaultAppInfo defaultApp = getDefaultAppInfo();
final CharSequence defaultAppLabel = defaultApp != null
? defaultApp.loadLabel(mPackageManager.getPackageManager()) : null;
if (TextUtils.isEmpty(defaultAppLabel)) {
final String onlyAppLabel = getOnlyAppLabel();
if (!TextUtils.isEmpty(onlyAppLabel)) {
preference.setSummary(onlyAppLabel);
}
}
}
private String getOnlyAppLabel() {
// Resolve that intent and check that the handleAllWebDataURI boolean is set
final List<ResolveInfo> list = mPackageManager.queryIntentActivitiesAsUser(BROWSE_PROBE,
PackageManager.MATCH_ALL, mUserId);
if (list != null && list.size() == 1) {
return list.get(0).loadLabel(mPackageManager.getPackageManager()).toString();
}
return null;
}
@Override
protected DefaultAppInfo getDefaultAppInfo() {
try {
return new DefaultAppInfo(mPackageManager.getPackageManager().getApplicationInfo(
mPackageManager.getDefaultBrowserPackageNameAsUser(mUserId), 0));
} catch (PackageManager.NameNotFoundException e) {
return null;
}
}
/**
* Whether or not the pkg contains browser capability
*/
public static boolean hasBrowserPreference(String pkg, Context context) {
final Intent intent = new Intent(BROWSE_PROBE);
intent.setPackage(pkg);
final List<ResolveInfo> resolveInfos =
context.getPackageManager().queryIntentActivities(intent, 0);
return resolveInfos != null && resolveInfos.size() != 0;
}
/**
* Whether or not the pkg is the default browser
*/
public static boolean isBrowserDefault(String pkg, Context context) {
String defaultPackage = context.getPackageManager()
.getDefaultBrowserPackageNameAsUser(UserHandle.myUserId());
return defaultPackage != null && defaultPackage.equals(pkg);
}
}

View File

@@ -0,0 +1,101 @@
/*
* 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.defaultapps;
import android.content.ContentResolver;
import android.content.pm.ApplicationInfo;
import android.content.pm.PackageInfo;
import android.content.pm.PackageManager;
import android.content.pm.ResolveInfo;
import android.provider.Settings;
import android.text.TextUtils;
import com.android.internal.logging.nano.MetricsProto;
import com.android.settings.R;
import com.android.settings.Utils;
import java.util.ArrayList;
import java.util.List;
public class DefaultEmergencyPicker extends DefaultAppPickerFragment {
@Override
public int getMetricsCategory() {
return MetricsProto.MetricsEvent.DEFAULT_EMERGENCY_APP_PICKER;
}
@Override
protected List<DefaultAppInfo> getCandidates() {
final List<DefaultAppInfo> candidates = new ArrayList<>();
final List<ResolveInfo> infos = mPm.getPackageManager().queryIntentActivities(
DefaultEmergencyPreferenceController.QUERY_INTENT, 0);
PackageInfo bestMatch = null;
for (ResolveInfo info : infos) {
try {
final PackageInfo packageInfo =
mPm.getPackageManager().getPackageInfo(info.activityInfo.packageName, 0);
final ApplicationInfo appInfo = packageInfo.applicationInfo;
candidates.add(new DefaultAppInfo(appInfo));
// Get earliest installed system app.
if (isSystemApp(appInfo) && (bestMatch == null ||
bestMatch.firstInstallTime > packageInfo.firstInstallTime)) {
bestMatch = packageInfo;
}
} catch (PackageManager.NameNotFoundException e) {
// Skip unknown packages.
}
if (bestMatch != null) {
final String defaultKey = getDefaultAppKey();
if (TextUtils.isEmpty(defaultKey)) {
setDefaultAppKey(bestMatch.packageName);
}
}
}
return candidates;
}
@Override
protected String getConfirmationMessage(DefaultAppInfo info) {
return Utils.isPackageDirectBootAware(getContext(), info.getKey()) ? null
: getContext().getString(R.string.direct_boot_unaware_dialog_message);
}
@Override
protected String getDefaultAppKey() {
return Settings.Secure.getString(getContext().getContentResolver(),
Settings.Secure.EMERGENCY_ASSISTANCE_APPLICATION);
}
@Override
protected boolean setDefaultAppKey(String key) {
final ContentResolver contentResolver = getContext().getContentResolver();
final String previousValue = Settings.Secure.getString(contentResolver,
Settings.Secure.EMERGENCY_ASSISTANCE_APPLICATION);
if (!TextUtils.isEmpty(key) && !TextUtils.equals(key, previousValue)) {
Settings.Secure.putString(contentResolver,
Settings.Secure.EMERGENCY_ASSISTANCE_APPLICATION,
key);
return true;
}
return false;
}
private boolean isSystemApp(ApplicationInfo info) {
return info != null && (info.flags & ApplicationInfo.FLAG_SYSTEM) != 0;
}
}

View File

@@ -0,0 +1,74 @@
/*
* 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.defaultapps;
import android.content.Context;
import android.content.Intent;
import android.content.pm.ResolveInfo;
import android.provider.Settings;
import android.telephony.TelephonyManager;
import java.util.List;
public class DefaultEmergencyPreferenceController extends DefaultAppPreferenceController {
private static final boolean DEFAULT_EMERGENCY_APP_IS_CONFIGURABLE = false;
public static final Intent QUERY_INTENT = new Intent(
TelephonyManager.ACTION_EMERGENCY_ASSISTANCE);
public DefaultEmergencyPreferenceController(Context context) {
super(context);
}
@Override
public boolean isAvailable() {
return DEFAULT_EMERGENCY_APP_IS_CONFIGURABLE
&& isCapable()
&& mPackageManager.getPackageManager().resolveActivity(QUERY_INTENT, 0) != null;
}
@Override
public String getPreferenceKey() {
return "default_emergency_app";
}
@Override
protected DefaultAppInfo getDefaultAppInfo() {
return null;
}
private boolean isCapable() {
return TelephonyManager.EMERGENCY_ASSISTANCE_ENABLED
&& mContext.getResources().getBoolean(
com.android.internal.R.bool.config_voice_capable);
}
public static boolean hasEmergencyPreference(String pkg, Context context) {
Intent i = new Intent(QUERY_INTENT);
i.setPackage(pkg);
final List<ResolveInfo> resolveInfos =
context.getPackageManager().queryIntentActivities(i, 0);
return resolveInfos != null && resolveInfos.size() != 0;
}
public static boolean isEmergencyDefault(String pkg, Context context) {
String defaultPackage = Settings.Secure.getString(context.getContentResolver(),
Settings.Secure.EMERGENCY_ASSISTANCE_APPLICATION);
return defaultPackage != null && defaultPackage.equals(pkg);
}
}

View File

@@ -0,0 +1,133 @@
/*
* 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.defaultapps;
import android.content.ComponentName;
import android.content.Context;
import android.content.IntentFilter;
import android.content.pm.ActivityInfo;
import android.content.pm.ApplicationInfo;
import android.content.pm.PackageManager;
import android.content.pm.ResolveInfo;
import android.content.pm.UserInfo;
import android.os.Build;
import android.text.TextUtils;
import com.android.internal.logging.nano.MetricsProto;
import com.android.settings.R;
import java.util.ArrayList;
import java.util.List;
public class DefaultHomePicker extends DefaultAppPickerFragment {
private String mPackageName;
@Override
public void onAttach(Context context) {
super.onAttach(context);
mPackageName = context.getPackageName();
}
@Override
public int getMetricsCategory() {
return MetricsProto.MetricsEvent.DEFAULT_HOME_PICKER;
}
@Override
protected List<DefaultAppInfo> getCandidates() {
final boolean mustSupportManagedProfile = hasManagedProfile();
final List<DefaultAppInfo> candidates = new ArrayList<>();
final List<ResolveInfo> homeActivities = new ArrayList<>();
mPm.getHomeActivities(homeActivities);
for (ResolveInfo resolveInfo : homeActivities) {
final ActivityInfo info = resolveInfo.activityInfo;
final ComponentName activityName = new ComponentName(info.packageName, info.name);
if (info.packageName.equals(mPackageName)) {
continue;
}
final String summary;
if (mustSupportManagedProfile && !launcherHasManagedProfilesFeature(resolveInfo)) {
summary = getContext().getString(R.string.home_work_profile_not_supported);
} else {
summary = null;
}
final DefaultAppInfo candidate = new DefaultAppInfo(mUserId, activityName, summary);
candidates.add(candidate);
}
return candidates;
}
@Override
protected String getDefaultAppKey() {
final ArrayList<ResolveInfo> homeActivities = new ArrayList<>();
final ComponentName currentDefaultHome = mPm.getHomeActivities(homeActivities);
if (currentDefaultHome != null) {
return currentDefaultHome.flattenToString();
}
return null;
}
@Override
protected boolean setDefaultAppKey(String key) {
if (!TextUtils.isEmpty(key)) {
final ComponentName component = ComponentName.unflattenFromString(key);
final List<ResolveInfo> homeActivities = new ArrayList<>();
mPm.getHomeActivities(homeActivities);
final List<ComponentName> allComponents = new ArrayList<>();
for (ResolveInfo info : homeActivities) {
final ActivityInfo appInfo = info.activityInfo;
ComponentName activityName = new ComponentName(appInfo.packageName, appInfo.name);
allComponents.add(activityName);
}
mPm.replacePreferredActivity(
DefaultHomePreferenceController.HOME_FILTER,
IntentFilter.MATCH_CATEGORY_EMPTY,
allComponents.toArray(new ComponentName[0]),
component);
return true;
}
return false;
}
private boolean hasManagedProfile() {
final Context context = getContext();
List<UserInfo> profiles = mUserManager.getProfiles(context.getUserId());
for (UserInfo userInfo : profiles) {
if (userInfo.isManagedProfile()) {
return true;
}
}
return false;
}
private boolean launcherHasManagedProfilesFeature(ResolveInfo resolveInfo) {
try {
ApplicationInfo appInfo = mPm.getPackageManager().getApplicationInfo(
resolveInfo.activityInfo.packageName, 0 /* default flags */);
return versionNumberAtLeastL(appInfo.targetSdkVersion);
} catch (PackageManager.NameNotFoundException e) {
return false;
}
}
private boolean versionNumberAtLeastL(int versionNumber) {
return versionNumber >= Build.VERSION_CODES.LOLLIPOP;
}
}

View File

@@ -0,0 +1,117 @@
/*
* 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.defaultapps;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.content.pm.ActivityInfo;
import android.content.pm.PackageManager;
import android.content.pm.ResolveInfo;
import android.support.v7.preference.Preference;
import android.text.TextUtils;
import java.util.ArrayList;
import java.util.List;
public class DefaultHomePreferenceController extends DefaultAppPreferenceController {
static final IntentFilter HOME_FILTER;
private final String mPackageName;
static {
HOME_FILTER = new IntentFilter(Intent.ACTION_MAIN);
HOME_FILTER.addCategory(Intent.CATEGORY_HOME);
HOME_FILTER.addCategory(Intent.CATEGORY_DEFAULT);
}
public DefaultHomePreferenceController(Context context) {
super(context);
mPackageName = mContext.getPackageName();
}
@Override
public String getPreferenceKey() {
return "default_home";
}
@Override
public boolean isAvailable() {
return true;
}
@Override
public void updateState(Preference preference) {
super.updateState(preference);
final DefaultAppInfo defaultApp = getDefaultAppInfo();
final CharSequence defaultAppLabel = defaultApp != null
? defaultApp.loadLabel(mPackageManager.getPackageManager()) : null;
if (TextUtils.isEmpty(defaultAppLabel)) {
final String onlyAppLabel = getOnlyAppLabel();
if (!TextUtils.isEmpty(onlyAppLabel)) {
preference.setSummary(onlyAppLabel);
}
}
}
@Override
protected DefaultAppInfo getDefaultAppInfo() {
final ArrayList<ResolveInfo> homeActivities = new ArrayList<>();
final ComponentName currentDefaultHome = mPackageManager.getHomeActivities(homeActivities);
return new DefaultAppInfo(mUserId, currentDefaultHome, null /* summary */);
}
private String getOnlyAppLabel() {
final List<ResolveInfo> homeActivities = new ArrayList<>();
final List<ActivityInfo> appLabels = new ArrayList<>();
mPackageManager.getHomeActivities(homeActivities);
for (ResolveInfo candidate : homeActivities) {
final ActivityInfo info = candidate.activityInfo;
if (info.packageName.equals(mPackageName)) {
continue;
}
appLabels.add(info);
}
return appLabels.size() == 1
? appLabels.get(0).loadLabel(mPackageManager.getPackageManager()).toString()
: null;
}
public static boolean hasHomePreference(String pkg, Context context) {
ArrayList<ResolveInfo> homeActivities = new ArrayList<>();
PackageManager pm = context.getPackageManager();
pm.getHomeActivities(homeActivities);
for (int i = 0; i < homeActivities.size(); i++) {
if (homeActivities.get(i).activityInfo.packageName.equals(pkg)) {
return true;
}
}
return false;
}
public static boolean isHomeDefault(String pkg, Context context) {
ArrayList<ResolveInfo> homeActivities = new ArrayList<>();
PackageManager pm = context.getPackageManager();
ComponentName def = pm.getHomeActivities(homeActivities);
return def != null && def.getPackageName().equals(pkg);
}
}

View File

@@ -1,5 +1,5 @@
/** /*
* Copyright (C) 2016 The Android Open Source Project * Copyright (C) 2017 The Android Open Source Project
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
@@ -14,65 +14,48 @@
* limitations under the License. * limitations under the License.
*/ */
package com.android.settings.applications; package com.android.settings.applications.defaultapps;
import com.android.settings.AppListPreference;
import android.app.ActivityManager; import android.app.ActivityManager;
import android.content.ComponentName; import android.content.ComponentName;
import android.content.Context;
import android.content.Intent; import android.content.Intent;
import android.content.pm.PackageManager; import android.content.pm.PackageManager;
import android.content.pm.ResolveInfo; import android.content.pm.ResolveInfo;
import android.content.pm.ServiceInfo; import android.content.pm.ServiceInfo;
import android.provider.Settings; import android.provider.Settings;
import android.service.notification.NotificationAssistantService; import android.service.notification.NotificationAssistantService;
import android.util.AttributeSet;
import android.util.Slog; import android.util.Slog;
import java.util.ArrayList;
import java.util.List;
import com.android.settings.R; import com.android.settings.R;
import com.android.settings.utils.ManagedServiceSettings; import com.android.settings.utils.ManagedServiceSettings;
public class DefaultNotificationAssistantPreference extends AppListPreference { import java.util.ArrayList;
import java.util.List;
public class DefaultNotificationAssistantPicker extends DefaultAppPickerFragment {
private static final String TAG = "DefaultNotiAssist"; private static final String TAG = "DefaultNotiAssist";
private PackageManager mPm; private final ManagedServiceSettings.Config mConfig = getConfig();
private final ManagedServiceSettings.Config mConfig;
private final Context mContext;
public DefaultNotificationAssistantPreference(Context context, AttributeSet attrs) { @Override
super(context, attrs); public int getMetricsCategory() {
return 0;
mContext = context;
mPm = context.getPackageManager();
mConfig = getConfig();
setShowItemNone(true);
updateList(getServices());
} }
@Override @Override
protected boolean persistString(String value) { protected String getDefaultAppKey() {
Settings.Secure.putString(mContext.getContentResolver(), mConfig.setting, value); return Settings.Secure.getString(getContext().getContentResolver(), mConfig.setting);
setSummary(getEntry()); }
@Override
protected boolean setDefaultAppKey(String value) {
Settings.Secure.putString(getContext().getContentResolver(), mConfig.setting, value);
return true; return true;
} }
private void updateList(List<ServiceInfo> services) { @Override
final ComponentName[] assistants = new ComponentName[services.size()]; protected List<DefaultAppInfo> getCandidates() {
for (int i = 0; i < services.size(); i++) { List<DefaultAppInfo> candidates = new ArrayList<>();
assistants[i] = new ComponentName(services.get(i).packageName, services.get(i).name);
}
final String assistant =
Settings.Secure.getString(mContext.getContentResolver(), mConfig.setting);
setComponentNames(assistants, assistant == null ? null
: ComponentName.unflattenFromString(assistant));
}
private List<ServiceInfo> getServices() {
List<ServiceInfo> services = new ArrayList<>();
final int user = ActivityManager.getCurrentUser(); final int user = ActivityManager.getCurrentUser();
List<ResolveInfo> installedServices = mPm.queryIntentServicesAsUser( List<ResolveInfo> installedServices = mPm.queryIntentServicesAsUser(
@@ -91,9 +74,16 @@ public class DefaultNotificationAssistantPreference extends AppListPreference {
+ mConfig.permission); + mConfig.permission);
continue; continue;
} }
services.add(info);
candidates.add(new DefaultAppInfo(
mUserId, new ComponentName(info.packageName, info.name), null /* summary */));
} }
return services; return candidates;
}
@Override
protected boolean shouldShowItemNone() {
return true;
} }
private ManagedServiceSettings.Config getConfig() { private ManagedServiceSettings.Config getConfig() {
@@ -108,4 +98,4 @@ public class DefaultNotificationAssistantPreference extends AppListPreference {
c.emptyText = R.string.no_notification_listeners; c.emptyText = R.string.no_notification_listeners;
return c; return c;
} }
} }

View File

@@ -0,0 +1,102 @@
/*
* 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.defaultapps;
import android.content.Context;
import android.content.pm.PackageManager;
import android.telecom.DefaultDialerManager;
import android.telecom.TelecomManager;
import android.text.TextUtils;
import com.android.internal.logging.nano.MetricsProto;
import java.util.ArrayList;
import java.util.List;
public class DefaultPhonePicker extends DefaultAppPickerFragment {
private DefaultKeyUpdater mDefaultKeyUpdater;
@Override
public int getMetricsCategory() {
return MetricsProto.MetricsEvent.DEFAULT_PHONE_PICKER;
}
@Override
public void onAttach(Context context) {
super.onAttach(context);
mDefaultKeyUpdater = new DefaultKeyUpdater(
(TelecomManager) context.getSystemService(Context.TELECOM_SERVICE));
}
@Override
protected List<DefaultAppInfo> getCandidates() {
final List<DefaultAppInfo> candidates = new ArrayList<>();
final List<String> dialerPackages =
DefaultDialerManager.getInstalledDialerApplications(getContext(), mUserId);
for (String packageName : dialerPackages) {
try {
candidates.add(new DefaultAppInfo(
mPm.getApplicationInfoAsUser(packageName, 0, mUserId)));
} catch (PackageManager.NameNotFoundException e) {
// Skip unknown packages.
}
}
return candidates;
}
@Override
protected String getDefaultAppKey() {
return mDefaultKeyUpdater.getDefaultDialerApplication(getContext(), mUserId);
}
@Override
protected String getSystemDefaultAppKey() {
return mDefaultKeyUpdater.getSystemDialerPackage();
}
@Override
protected boolean setDefaultAppKey(String key) {
if (!TextUtils.isEmpty(key) && !TextUtils.equals(key, getDefaultAppKey())) {
return mDefaultKeyUpdater.setDefaultDialerApplication(getContext(), key, mUserId);
}
return false;
}
/**
* Wrapper class to handle default phone app update.
*/
static class DefaultKeyUpdater {
private final TelecomManager mTelecomManager;
public DefaultKeyUpdater(TelecomManager telecomManager) {
mTelecomManager = telecomManager;
}
public String getSystemDialerPackage() {
return mTelecomManager.getSystemDialerPackage();
}
public String getDefaultDialerApplication(Context context, int uid) {
return DefaultDialerManager.getDefaultDialerApplication(context, uid);
}
public boolean setDefaultDialerApplication(Context context, String key, int uid) {
return DefaultDialerManager.setDefaultDialerApplication(context, key, uid);
}
}
}

View File

@@ -0,0 +1,74 @@
/*
* 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.defaultapps;
import android.content.Context;
import android.content.pm.PackageManager;
import android.os.UserHandle;
import android.os.UserManager;
import android.telecom.DefaultDialerManager;
import android.telephony.TelephonyManager;
import java.util.List;
public class DefaultPhonePreferenceController extends DefaultAppPreferenceController {
public DefaultPhonePreferenceController(Context context) {
super(context);
}
@Override
public boolean isAvailable() {
final TelephonyManager tm =
(TelephonyManager) mContext.getSystemService(Context.TELEPHONY_SERVICE);
if (!tm.isVoiceCapable()) {
return false;
}
final UserManager um = (UserManager) mContext.getSystemService(Context.USER_SERVICE);
final boolean hasUserRestriction =
um.hasUserRestriction(UserManager.DISALLOW_OUTGOING_CALLS);
return !hasUserRestriction;
}
@Override
public String getPreferenceKey() {
return "default_phone_app";
}
@Override
protected DefaultAppInfo getDefaultAppInfo() {
try {
return new DefaultAppInfo(mPackageManager.getPackageManager().getApplicationInfo(
DefaultDialerManager.getDefaultDialerApplication(mContext, mUserId), 0));
} catch (PackageManager.NameNotFoundException e) {
return null;
}
}
public static boolean hasPhonePreference(String pkg, Context context) {
List<String> dialerPackages =
DefaultDialerManager.getInstalledDialerApplications(context, UserHandle.myUserId());
return dialerPackages.contains(pkg);
}
public static boolean isPhoneDefault(String pkg, Context context) {
String def = DefaultDialerManager.getDefaultDialerApplication(context,
UserHandle.myUserId());
return def != null && def.equals(pkg);
}
}

View File

@@ -0,0 +1,97 @@
/*
* 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.defaultapps;
import android.content.ComponentName;
import android.content.Context;
import android.content.pm.PackageManager;
import android.text.TextUtils;
import com.android.internal.logging.nano.MetricsProto;
import com.android.internal.telephony.SmsApplication;
import com.android.settings.R;
import com.android.settings.Utils;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
public class DefaultSmsPicker extends DefaultAppPickerFragment {
private DefaultKeyUpdater mDefaultKeyUpdater = new DefaultKeyUpdater();
@Override
public int getMetricsCategory() {
return MetricsProto.MetricsEvent.DEFAULT_SMS_PICKER;
}
@Override
protected List<DefaultAppInfo> getCandidates() {
final Collection<SmsApplication.SmsApplicationData> smsApplications =
SmsApplication.getApplicationCollection(getContext());
final List<DefaultAppInfo> candidates = new ArrayList<>(smsApplications.size());
for (SmsApplication.SmsApplicationData smsApplicationData : smsApplications) {
try {
candidates.add(new DefaultAppInfo(
mPm.getApplicationInfoAsUser(smsApplicationData.mPackageName, 0, mUserId)));
} catch (PackageManager.NameNotFoundException e) {
// Skip unknown packages.
}
}
return candidates;
}
@Override
protected String getDefaultAppKey() {
return mDefaultKeyUpdater.getDefaultApplication(getContext());
}
@Override
protected boolean setDefaultAppKey(String key) {
if (!TextUtils.isEmpty(key) && !TextUtils.equals(key, getDefaultAppKey())) {
mDefaultKeyUpdater.setDefaultApplication(getContext(), key);
return true;
}
return false;
}
@Override
protected String getConfirmationMessage(DefaultAppInfo info) {
return Utils.isPackageDirectBootAware(getContext(), info.getKey()) ? null
: getContext().getString(R.string.direct_boot_unaware_dialog_message);
}
/**
* Wrapper class to handle default phone app update.
*/
static class DefaultKeyUpdater {
public String getDefaultApplication(Context context) {
final ComponentName appName = SmsApplication.getDefaultSmsApplication(context, true);
if (appName != null) {
return appName.getPackageName();
}
return null;
}
public void setDefaultApplication(Context context, String key) {
SmsApplication.setDefaultApplication(key, context);
}
}
}

View File

@@ -0,0 +1,70 @@
/*
* 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.defaultapps;
import android.content.ComponentName;
import android.content.Context;
import android.telephony.TelephonyManager;
import com.android.internal.telephony.SmsApplication;
import java.util.Collection;
public class DefaultSmsPreferenceController extends DefaultAppPreferenceController {
public DefaultSmsPreferenceController(Context context) {
super(context);
}
@Override
public boolean isAvailable() {
boolean isRestrictedUser = mUserManager.getUserInfo(mUserId).isRestricted();
TelephonyManager tm =
(TelephonyManager) mContext.getSystemService(Context.TELEPHONY_SERVICE);
return !isRestrictedUser && tm.isSmsCapable();
}
@Override
public String getPreferenceKey() {
return "default_sms_app";
}
@Override
protected DefaultAppInfo getDefaultAppInfo() {
final ComponentName app = SmsApplication.getDefaultSmsApplication(mContext, true);
if (app != null) {
return new DefaultAppInfo(mUserId, app, null /* summary */);
}
return null;
}
public static boolean hasSmsPreference(String pkg, Context context) {
Collection<SmsApplication.SmsApplicationData> smsApplications =
SmsApplication.getApplicationCollection(context);
for (SmsApplication.SmsApplicationData data : smsApplications) {
if (data.mPackageName.equals(pkg)) {
return true;
}
}
return false;
}
public static boolean isSmsDefault(String pkg, Context context) {
ComponentName appName = SmsApplication.getDefaultSmsApplication(context, true);
return appName != null && appName.getPackageName().equals(pkg);
}
}

View File

@@ -0,0 +1,43 @@
/*
* 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.defaultapps;
import android.content.Context;
import android.os.UserHandle;
import com.android.settings.Utils;
public class DefaultWorkBrowserPreferenceController extends DefaultBrowserPreferenceController {
public DefaultWorkBrowserPreferenceController(Context context) {
super(context);
final UserHandle managedProfile = Utils.getManagedProfile(mUserManager);
if (managedProfile != null) {
mUserId = managedProfile.getIdentifier();
}
}
@Override
public boolean isAvailable() {
return Utils.getManagedProfile(mUserManager) != null;
}
@Override
public String getPreferenceKey() {
return "work_default_browser";
}
}

View File

@@ -0,0 +1,31 @@
/*
* 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.defaultapps;
import android.content.Context;
public class DefaultWorkPhonePreferenceController extends DefaultPhonePreferenceController {
public DefaultWorkPhonePreferenceController(Context context) {
super(context);
}
@Override
public String getPreferenceKey() {
return "work_default_phone_app";
}
}

View File

@@ -76,4 +76,8 @@ public abstract class InstrumentedPreferenceFragment extends ObservablePreferenc
mDividerDecoration.setDivider(divider); mDividerDecoration.setDivider(divider);
super.setDivider(new ColorDrawable(Color.TRANSPARENT)); super.setDivider(new ColorDrawable(Color.TRANSPARENT));
} }
protected final Context getPrefContext() {
return getPreferenceManager().getContext();
}
} }

View File

@@ -21,7 +21,6 @@ import android.content.Context;
import com.android.settings.R; import com.android.settings.R;
import com.android.settings.SettingsRobolectricTestRunner; import com.android.settings.SettingsRobolectricTestRunner;
import com.android.settings.TestConfig; import com.android.settings.TestConfig;
import com.android.settings.testutils.FakeFeatureFactory;
import org.junit.Before; import org.junit.Before;
import org.junit.Test; import org.junit.Test;
@@ -33,7 +32,6 @@ import org.robolectric.annotation.Config;
import org.robolectric.shadows.ShadowApplication; import org.robolectric.shadows.ShadowApplication;
import static com.google.common.truth.Truth.assertThat; import static com.google.common.truth.Truth.assertThat;
import static org.mockito.Mockito.when;
@RunWith(SettingsRobolectricTestRunner.class) @RunWith(SettingsRobolectricTestRunner.class)
@Config(manifest = TestConfig.MANIFEST_PATH, sdk = TestConfig.SDK_VERSION) @Config(manifest = TestConfig.MANIFEST_PATH, sdk = TestConfig.SDK_VERSION)
@@ -42,27 +40,20 @@ public class AdvancedAppSettingsTest {
@Mock(answer = Answers.RETURNS_DEEP_STUBS) @Mock(answer = Answers.RETURNS_DEEP_STUBS)
private Context mContext; private Context mContext;
private FakeFeatureFactory mFeatureFactory;
private AdvancedAppSettings mFragment; private AdvancedAppSettings mFragment;
@Before @Before
public void setUp() { public void setUp() {
MockitoAnnotations.initMocks(this); MockitoAnnotations.initMocks(this);
FakeFeatureFactory.setupForTest(mContext);
mFeatureFactory = (FakeFeatureFactory) FakeFeatureFactory.getFactory(mContext);
mFragment = new AdvancedAppSettings(); mFragment = new AdvancedAppSettings();
mFragment.onAttach(ShadowApplication.getInstance().getApplicationContext()); mFragment.onAttach(ShadowApplication.getInstance().getApplicationContext());
} }
@Test @Test
public void getPreferenceScreenResId_differentIAEnabledState_shouldUseDifferentPrefLayout() { public void getPreferenceScreenResId_shouldUseAppDefaultSettingPrefLayout() {
when(mFeatureFactory.dashboardFeatureProvider.isEnabled()).thenReturn(true);
assertThat(mFragment.getPreferenceScreenResId()).isEqualTo( assertThat(mFragment.getPreferenceScreenResId()).isEqualTo(
R.xml.app_default_settings); R.xml.app_default_settings);
when(mFeatureFactory.dashboardFeatureProvider.isEnabled()).thenReturn(false);
assertThat(mFragment.getPreferenceScreenResId()).isEqualTo(
R.xml.advanced_apps);
} }
} }

View File

@@ -0,0 +1,93 @@
/*
* 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.defaultapps;
import android.content.ComponentName;
import android.content.pm.ActivityInfo;
import android.content.pm.ApplicationInfo;
import android.content.pm.PackageManager;
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.mockito.Mock;
import org.mockito.MockitoAnnotations;
import org.robolectric.annotation.Config;
import static com.google.common.truth.Truth.assertThat;
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 DefaultAppInfoTest {
@Mock
private ActivityInfo mActivityInfo;
@Mock
private ApplicationInfo mApplicationInfo;
@Mock
private ComponentName mComponentName;
@Mock
private PackageManager mPackageManager;
private DefaultAppInfo mInfo;
@Before
public void setUp() {
MockitoAnnotations.initMocks(this);
}
@Test
public void initInfoWithActivityInfo_shouldLoadInfo() {
mActivityInfo.packageName = "test";
mInfo = new DefaultAppInfo(mActivityInfo);
mInfo.loadLabel(mPackageManager);
mInfo.loadIcon(mPackageManager);
assertThat(mInfo.getKey()).isEqualTo(mActivityInfo.packageName);
verify(mActivityInfo).loadLabel(mPackageManager);
verify(mActivityInfo).loadIcon(mPackageManager);
}
@Test
public void initInfoWithApplicationInfo_shouldLoadInfo() {
mApplicationInfo.packageName = "test";
mInfo = new DefaultAppInfo(mApplicationInfo);
mInfo.loadLabel(mPackageManager);
mInfo.loadIcon(mPackageManager);
assertThat(mInfo.getKey()).isEqualTo(mApplicationInfo.packageName);
verify(mApplicationInfo).loadLabel(mPackageManager);
verify(mApplicationInfo).loadIcon(mPackageManager);
}
@Test
public void initInfoWithComponent_shouldLoadInfo() {
when(mComponentName.getPackageName()).thenReturn("com.android.settings");
mInfo = new DefaultAppInfo(0 /* uid */, mComponentName, null /*summary */);
mInfo.getKey();
verify(mComponentName).flattenToString();
}
}

View File

@@ -0,0 +1,139 @@
/*
* 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.defaultapps;
import android.app.Activity;
import android.content.Context;
import android.os.Bundle;
import android.os.UserManager;
import android.support.v4.app.FragmentManager;
import android.support.v7.preference.PreferenceScreen;
import com.android.settings.SettingsRobolectricTestRunner;
import com.android.settings.TestConfig;
import com.android.settings.widget.RadioButtonPreference;
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 java.util.ArrayList;
import java.util.List;
import static com.google.common.truth.Truth.assertThat;
import static org.mockito.Matchers.any;
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 DefaultAppPickerFragmentTest {
@Mock(answer = Answers.RETURNS_DEEP_STUBS)
private Activity mActivity;
@Mock
private PreferenceScreen mScreen;
@Mock
private UserManager mUserManager;
@Mock
private FragmentManager mFragmentManager;
private TestFragment mFragment;
@Before
public void setUp() {
MockitoAnnotations.initMocks(this);
mFragment = spy(new TestFragment());
final Bundle bundle = new Bundle();
bundle.putBoolean(DefaultAppPickerFragment.EXTRA_FOR_WORK, false);
mFragment.setArguments(bundle);
when(mActivity.getSystemService(Context.USER_SERVICE)).thenReturn(mUserManager);
doReturn(mActivity).when(mFragment).getContext();
doReturn(mScreen).when(mFragment).getPreferenceScreen();
}
@Test
public void onAttach_userIsInitialized() {
mFragment.onAttach((Context) mActivity);
verify(mActivity).getPackageManager();
verify(mActivity).getSystemService(Context.USER_SERVICE);
}
@Test
public void clickPreference_noCofirmation_shouldDirectlyConfirm() {
final RadioButtonPreference pref =
new RadioButtonPreference(RuntimeEnvironment.application);
pref.setKey("TEST");
mFragment.onRadioButtonClicked(pref);
assertThat(mFragment.setDefaultAppKeyCalled).isTrue();
}
@Test
public void clickPreference_hasCofirmation_shouldShowConfirmation() {
final RadioButtonPreference pref =
new RadioButtonPreference(RuntimeEnvironment.application);
pref.setKey("TEST");
doReturn("confirmation_text").when(mFragment)
.getConfirmationMessage(any(DefaultAppInfo.class));
doReturn(mActivity).when(mFragment).getActivity();
mFragment.onRadioButtonClicked(pref);
}
public static class TestFragment extends DefaultAppPickerFragment {
boolean setDefaultAppKeyCalled;
@Override
public int getMetricsCategory() {
return 0;
}
@Override
protected List<DefaultAppInfo> getCandidates() {
return new ArrayList<>();
}
@Override
protected String getDefaultAppKey() {
return null;
}
@Override
protected boolean setDefaultAppKey(String key) {
setDefaultAppKeyCalled = true;
return true;
}
@Override
public Context getContext() {
return RuntimeEnvironment.application;
}
}
}

View File

@@ -0,0 +1,107 @@
/*
* 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.defaultapps;
import android.content.Context;
import android.os.UserManager;
import android.support.v7.preference.Preference;
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.mockito.Answers;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
import org.robolectric.annotation.Config;
import static org.mockito.Matchers.any;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.never;
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 DefaultAppPreferenceControllerTest {
private static final String TEST_APP_NAME = "test";
@Mock(answer = Answers.RETURNS_DEEP_STUBS)
private Context mContext;
@Mock
private UserManager mUserManager;
@Mock
private Preference mPreference;
private TestPreferenceController mController;
@Before
public void setUp() {
MockitoAnnotations.initMocks(this);
when(mContext.getSystemService(Context.USER_SERVICE)).thenReturn(mUserManager);
}
@Test
public void updateState_hasDefaultApp_shouldUpdateAppName() {
mController = new TestPreferenceController(mContext);
when(mController.mAppInfo.loadLabel(mContext.getPackageManager()))
.thenReturn(TEST_APP_NAME);
mController.updateState(mPreference);
verify(mPreference).setSummary(TEST_APP_NAME);
}
@Test
public void updateState_hasNoApp_shouldNotUpdateAppName() {
mController = new TestPreferenceController(mContext);
mController.updateState(mPreference);
verify(mPreference, never()).setSummary(any(CharSequence.class));
}
private static class TestPreferenceController extends DefaultAppPreferenceController {
private DefaultAppInfo mAppInfo;
public TestPreferenceController(Context context) {
super(context);
mAppInfo = mock(DefaultAppInfo.class);
}
@Override
public boolean isAvailable() {
return true;
}
@Override
public String getPreferenceKey() {
return "test";
}
@Override
protected DefaultAppInfo getDefaultAppInfo() {
return mAppInfo;
}
}
}

View File

@@ -0,0 +1,84 @@
/*
* 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.defaultapps;
import android.app.Activity;
import android.content.Context;
import android.os.UserManager;
import android.provider.Settings;
import com.android.settings.SettingsRobolectricTestRunner;
import com.android.settings.TestConfig;
import com.android.settings.applications.PackageManagerWrapper;
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.anyInt;
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 DefaultBrowserPickerTest {
private static final String TEST_APP_KEY = "";
@Mock(answer = Answers.RETURNS_DEEP_STUBS)
private Activity mActivity;
@Mock
private UserManager mUserManager;
@Mock
private PackageManagerWrapper mPackageManager;
private DefaultBrowserPicker mPicker;
@Before
public void setUp() {
MockitoAnnotations.initMocks(this);
when(mActivity.getSystemService(Context.USER_SERVICE)).thenReturn(mUserManager);
mPicker = new DefaultBrowserPicker();
mPicker.onAttach((Context) mActivity);
ReflectionHelpers.setField(mPicker, "mPm", mPackageManager);
}
@Test
public void setDefaultAppKey_shouldUpdateDefaultBrowser() {
mPicker.setDefaultAppKey(TEST_APP_KEY);
verify(mPackageManager)
.setDefaultBrowserPackageNameAsUser(eq(TEST_APP_KEY), anyInt());
}
@Test
public void getDefaultAppKey_shouldReturnDefaultBrowser() {
mPicker.getDefaultAppKey();
verify(mPackageManager)
.getDefaultBrowserPackageNameAsUser(anyInt());
}
}

View File

@@ -0,0 +1,89 @@
/*
* 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.defaultapps;
import android.content.Context;
import android.content.Intent;
import android.os.UserManager;
import android.support.v7.preference.Preference;
import com.android.settings.SettingsRobolectricTestRunner;
import com.android.settings.TestConfig;
import com.android.settings.applications.PackageManagerWrapper;
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 org.robolectric.util.ReflectionHelpers;
import static com.google.common.truth.Truth.assertThat;
import static org.mockito.Matchers.any;
import static org.mockito.Matchers.anyInt;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.never;
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 DefaultBrowserPreferenceControllerTest {
@Mock
private Context mContext;
@Mock
private UserManager mUserManager;
@Mock(answer = Answers.RETURNS_DEEP_STUBS)
private PackageManagerWrapper mPackageManager;
private DefaultBrowserPreferenceController mController;
@Before
public void setUp() {
MockitoAnnotations.initMocks(this);
when(mContext.getSystemService(Context.USER_SERVICE)).thenReturn(mUserManager);
mController = new DefaultBrowserPreferenceController(mContext);
ReflectionHelpers.setField(mController, "mPackageManager", mPackageManager);
}
@Test
public void isAlwaysAvailable() {
assertThat(mController.isAvailable()).isTrue();
}
@Test
public void getSoleAppLabel_hasNoApp_shouldNotReturnLabel() {
when(mPackageManager.queryIntentActivitiesAsUser(any(Intent.class), anyInt(), anyInt()))
.thenReturn(null);
final Preference pref = mock(Preference.class);
mController.updateState(pref);
verify(pref, never()).setSummary(any(String.class));
}
@Test
public void getDefaultApp_shouldGetDefaultBrowserPackage() {
mController.getDefaultAppInfo();
verify(mPackageManager).getDefaultBrowserPackageNameAsUser(anyInt());
}
}

View File

@@ -0,0 +1,85 @@
/*
* 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.defaultapps;
import android.app.Activity;
import android.content.Context;
import android.os.UserManager;
import android.provider.Settings;
import com.android.settings.SettingsRobolectricTestRunner;
import com.android.settings.TestConfig;
import com.android.settings.applications.PackageManagerWrapper;
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.Mockito.doReturn;
import static org.mockito.Mockito.spy;
import static org.mockito.Mockito.when;
@RunWith(SettingsRobolectricTestRunner.class)
@Config(manifest = TestConfig.MANIFEST_PATH, sdk = TestConfig.SDK_VERSION)
public class DefaultEmergencyPickerTest {
private static final String TEST_APP_KEY = "test_app";
@Mock(answer = Answers.RETURNS_DEEP_STUBS)
private Activity mActivity;
@Mock
private UserManager mUserManager;
@Mock
private PackageManagerWrapper mPackageManager;
private DefaultEmergencyPicker mPicker;
@Before
public void setUp() {
MockitoAnnotations.initMocks(this);
when(mActivity.getSystemService(Context.USER_SERVICE)).thenReturn(mUserManager);
mPicker = spy(new DefaultEmergencyPicker());
mPicker.onAttach((Context) mActivity);
ReflectionHelpers.setField(mPicker, "mPm", mPackageManager);
doReturn(RuntimeEnvironment.application).when(mPicker).getContext();
}
@Test
public void setDefaultAppKey_shouldUpdateDefault() {
assertThat(mPicker.setDefaultAppKey(TEST_APP_KEY)).isTrue();
assertThat(mPicker.getDefaultAppKey()).isEqualTo(TEST_APP_KEY);
}
@Test
public void getDefaultAppKey_shouldReturnDefault() {
Settings.Secure.putString(RuntimeEnvironment.application.getContentResolver(),
Settings.Secure.EMERGENCY_ASSISTANCE_APPLICATION,
TEST_APP_KEY);
assertThat(mPicker.getDefaultAppKey()).isEqualTo(TEST_APP_KEY);
}
}

View File

@@ -0,0 +1,90 @@
/*
* 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.defaultapps;
import android.app.Activity;
import android.content.ComponentName;
import android.content.Context;
import android.content.IntentFilter;
import android.os.UserManager;
import com.android.settings.SettingsRobolectricTestRunner;
import com.android.settings.TestConfig;
import com.android.settings.applications.PackageManagerWrapper;
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 org.robolectric.util.ReflectionHelpers;
import static com.google.common.truth.Truth.assertThat;
import static org.mockito.Matchers.any;
import static org.mockito.Matchers.anyInt;
import static org.mockito.Matchers.anyList;
import static org.mockito.Mockito.mock;
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 DefaultHomePickerTest {
private static final String TEST_APP_KEY = "com.android.settings/DefaultEmergencyPickerTest";
@Mock(answer = Answers.RETURNS_DEEP_STUBS)
private Activity mActivity;
@Mock
private UserManager mUserManager;
@Mock
private PackageManagerWrapper mPackageManager;
private DefaultHomePicker mPicker;
@Before
public void setUp() {
MockitoAnnotations.initMocks(this);
when(mActivity.getSystemService(Context.USER_SERVICE)).thenReturn(mUserManager);
mPicker = new DefaultHomePicker();
mPicker.onAttach((Context) mActivity);
ReflectionHelpers.setField(mPicker, "mPm", mPackageManager);
}
@Test
public void setDefaultAppKey_shouldUpdateDefault() {
assertThat(mPicker.setDefaultAppKey(TEST_APP_KEY)).isTrue();
verify(mPackageManager).replacePreferredActivity(any(IntentFilter.class),
anyInt(), any(ComponentName[].class), any(ComponentName.class));
}
@Test
public void getDefaultAppKey_shouldReturnDefault() {
final ComponentName cn = mock(ComponentName.class);
when(mPackageManager.getHomeActivities(anyList()))
.thenReturn(cn);
mPicker.getDefaultAppKey();
verify(cn).flattenToString();
}
}

View File

@@ -0,0 +1,87 @@
/*
* 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.defaultapps;
import android.content.Context;
import android.os.UserManager;
import android.support.v7.preference.Preference;
import com.android.settings.SettingsRobolectricTestRunner;
import com.android.settings.TestConfig;
import com.android.settings.applications.PackageManagerWrapper;
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 org.robolectric.util.ReflectionHelpers;
import static com.google.common.truth.Truth.assertThat;
import static org.mockito.Matchers.anyList;
import static org.mockito.Mockito.doReturn;
import static org.mockito.Mockito.mock;
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 DefaultHomePreferenceControllerTest {
@Mock
private Context mContext;
@Mock
private UserManager mUserManager;
@Mock(answer = Answers.RETURNS_DEEP_STUBS)
private PackageManagerWrapper mPackageManager;
private DefaultHomePreferenceController mController;
@Before
public void setUp() {
MockitoAnnotations.initMocks(this);
when(mContext.getSystemService(Context.USER_SERVICE)).thenReturn(mUserManager);
mController = spy(new DefaultHomePreferenceController(mContext));
ReflectionHelpers.setField(mController, "mPackageManager", mPackageManager);
}
@Test
public void isAlwaysAvailable() {
assertThat(mController.isAvailable()).isTrue();
}
@Test
public void getDefaultApp_shouldGetDefaultBrowserPackage() {
assertThat(mController.getDefaultAppInfo()).isNotNull();
verify(mPackageManager).getHomeActivities(anyList());
}
@Test
public void updateState_noDefaultApp_shouldAskPackageManagerForOnlyApp() {
doReturn(null).when(mController).getDefaultAppInfo();
mController.updateState(mock(Preference.class));
verify(mPackageManager).getHomeActivities(anyList());
}
}

View File

@@ -0,0 +1,86 @@
/*
* 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.defaultapps;
import android.app.Activity;
import android.content.Context;
import android.os.UserManager;
import android.provider.Settings;
import com.android.settings.SettingsRobolectricTestRunner;
import com.android.settings.TestConfig;
import com.android.settings.applications.PackageManagerWrapper;
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.Mockito.doReturn;
import static org.mockito.Mockito.spy;
import static org.mockito.Mockito.when;
@RunWith(SettingsRobolectricTestRunner.class)
@Config(manifest = TestConfig.MANIFEST_PATH, sdk = TestConfig.SDK_VERSION)
public class DefaultNotificationAssistantPickerTest {
private static final String TEST_APP_KEY = "com.android.settings/PickerTest";
@Mock(answer = Answers.RETURNS_DEEP_STUBS)
private Activity mActivity;
@Mock
private UserManager mUserManager;
@Mock
private PackageManagerWrapper mPackageManager;
private DefaultNotificationAssistantPicker mPicker;
@Before
public void setUp() {
MockitoAnnotations.initMocks(this);
when(mActivity.getSystemService(Context.USER_SERVICE)).thenReturn(mUserManager);
mPicker = spy(new DefaultNotificationAssistantPicker());
mPicker.onAttach((Context) mActivity);
ReflectionHelpers.setField(mPicker, "mPm", mPackageManager);
doReturn(RuntimeEnvironment.application).when(mPicker).getContext();
}
@Test
public void setDefaultAppKey_shouldUpdateDefault() {
mPicker.setDefaultAppKey(TEST_APP_KEY);
assertThat(mPicker.getDefaultAppKey()).isEqualTo(TEST_APP_KEY);
}
@Test
public void getDefaultAppKey_shouldReturnDefault() {
Settings.Secure.putString(RuntimeEnvironment.application.getContentResolver(),
Settings.Secure.ENABLED_NOTIFICATION_ASSISTANT,
TEST_APP_KEY);
assertThat(mPicker.getDefaultAppKey()).isEqualTo(TEST_APP_KEY);
}
}

View File

@@ -0,0 +1,96 @@
/*
* 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.defaultapps;
import android.app.Activity;
import android.content.Context;
import android.os.UserManager;
import com.android.settings.SettingsRobolectricTestRunner;
import com.android.settings.TestConfig;
import com.android.settings.applications.PackageManagerWrapper;
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 org.mockito.Matchers.any;
import static org.mockito.Matchers.anyInt;
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 DefaultPhonePickerTest {
private static final String TEST_APP_KEY = "com.android.settings/PickerTest";
@Mock(answer = Answers.RETURNS_DEEP_STUBS)
private Activity mActivity;
@Mock
private UserManager mUserManager;
@Mock
private DefaultPhonePicker.DefaultKeyUpdater mDefaultKeyUpdater;
@Mock
private PackageManagerWrapper mPackageManager;
private DefaultPhonePicker mPicker;
@Before
public void setUp() {
MockitoAnnotations.initMocks(this);
when(mActivity.getSystemService(Context.USER_SERVICE)).thenReturn(mUserManager);
when(mActivity.getSystemService(Context.TELECOM_SERVICE)).thenReturn(null);
mPicker = spy(new DefaultPhonePicker());
mPicker.onAttach((Context) mActivity);
ReflectionHelpers.setField(mPicker, "mPm", mPackageManager);
ReflectionHelpers.setField(mPicker, "mDefaultKeyUpdater", mDefaultKeyUpdater);
doReturn(RuntimeEnvironment.application).when(mPicker).getContext();
}
@Test
public void getSystemDefaultPackage_shouldAskDefaultKeyUpdater() {
mPicker.getSystemDefaultAppKey();
verify(mDefaultKeyUpdater).getSystemDialerPackage();
}
@Test
public void setDefaultAppKey_shouldUpdateDefault() {
mPicker.setDefaultAppKey(TEST_APP_KEY);
verify(mDefaultKeyUpdater).setDefaultDialerApplication(
any(Context.class), eq(TEST_APP_KEY), anyInt());
}
@Test
public void getDefaultAppKey_shouldReturnDefault() {
mPicker.getDefaultAppKey();
verify(mDefaultKeyUpdater).getDefaultDialerApplication(any(Context.class), anyInt());
}
}

View File

@@ -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.defaultapps;
import android.app.Activity;
import android.content.Context;
import android.os.UserManager;
import com.android.settings.SettingsRobolectricTestRunner;
import com.android.settings.TestConfig;
import com.android.settings.applications.PackageManagerWrapper;
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 org.mockito.Matchers.any;
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 DefaultSmsPickerTest {
private static final String TEST_APP_KEY = "com.android.settings/PickerTest";
@Mock(answer = Answers.RETURNS_DEEP_STUBS)
private Activity mActivity;
@Mock
private UserManager mUserManager;
@Mock
private DefaultSmsPicker.DefaultKeyUpdater mDefaultKeyUpdater;
@Mock
private PackageManagerWrapper mPackageManager;
private DefaultSmsPicker mPicker;
@Before
public void setUp() {
MockitoAnnotations.initMocks(this);
when(mActivity.getSystemService(Context.USER_SERVICE)).thenReturn(mUserManager);
mPicker = spy(new DefaultSmsPicker());
mPicker.onAttach((Context) mActivity);
ReflectionHelpers.setField(mPicker, "mPm", mPackageManager);
ReflectionHelpers.setField(mPicker, "mDefaultKeyUpdater", mDefaultKeyUpdater);
doReturn(RuntimeEnvironment.application).when(mPicker).getContext();
}
@Test
public void setDefaultAppKey_shouldUpdateDefault() {
mPicker.setDefaultAppKey(TEST_APP_KEY);
verify(mDefaultKeyUpdater).setDefaultApplication(any(Context.class), eq(TEST_APP_KEY));
}
@Test
public void getDefaultAppKey_shouldReturnDefault() {
mPicker.getDefaultAppKey();
verify(mDefaultKeyUpdater).getDefaultApplication(any(Context.class));
}
}