diff options
author | Fabrice Di Meglio <fdimeglio@google.com> | 2015-01-23 19:03:22 -0800 |
---|---|---|
committer | Fabrice Di Meglio <fdimeglio@google.com> | 2015-04-03 14:10:01 -0700 |
commit | 8b2ea39cbc5b0923646b5ad4d5f66ff3c66a9f7f (patch) | |
tree | 3bbb8007c3af047f17c22d4e8c5384fe43a55688 | |
parent | 43a0cbad1bc630aca89ff59208f8f5f6260f3efd (diff) | |
download | packages_apps_Settings-8b2ea39cbc5b0923646b5ad4d5f66ff3c66a9f7f.zip packages_apps_Settings-8b2ea39cbc5b0923646b5ad4d5f66ff3c66a9f7f.tar.gz packages_apps_Settings-8b2ea39cbc5b0923646b5ad4d5f66ff3c66a9f7f.tar.bz2 |
Settings - add support for Launch by Default
- implement UX spec
Change-Id: I7ee8962f83983273d809e0ef6fc81b0eb2df15dd
19 files changed, 762 insertions, 214 deletions
diff --git a/res/layout/app_domains_dialog.xml b/res/layout/app_domains_dialog.xml new file mode 100644 index 0000000..c00bff0 --- /dev/null +++ b/res/layout/app_domains_dialog.xml @@ -0,0 +1,31 @@ +<?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. +--> + +<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android" + android:layout_width="match_parent" + android:layout_height="match_parent" + android:paddingStart="24dp" + android:paddingTop="16dp" + android:paddingEnd="24dp"> + + <ListView + android:id="@android:id/list" + android:layout_width="match_parent" + android:layout_height="match_parent" + android:scrollbarStyle="insideOverlay" /> + +</FrameLayout> diff --git a/res/layout/app_domains_item.xml b/res/layout/app_domains_item.xml new file mode 100644 index 0000000..90fc0e4 --- /dev/null +++ b/res/layout/app_domains_item.xml @@ -0,0 +1,25 @@ +<?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. +--> + +<TextView xmlns:android="http://schemas.android.com/apk/res/android" + android:id="@+id/domain_name" + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:paddingStart="4dp" + android:paddingEnd="4dp" + android:paddingTop="16dp" + /> diff --git a/res/layout/app_preferred_settings.xml b/res/layout/app_preferred_settings.xml index 533887d..2e54068 100644 --- a/res/layout/app_preferred_settings.xml +++ b/res/layout/app_preferred_settings.xml @@ -23,7 +23,6 @@ android:scrollbarStyle="@integer/preference_scrollbar_style"> <LinearLayout - android:id="@+id/all_details" android:layout_width="match_parent" android:layout_height="match_parent" android:paddingStart="?android:attr/listPreferredItemPaddingStart" @@ -31,52 +30,19 @@ android:paddingBottom="5dip" android:orientation="vertical"> - <!-- Prefered activities section --> - <TextView android:id="@+id/auto_launch_title" - style="?android:attr/listSeparatorTextViewStyle" - android:layout_marginTop="8dip" - android:text="@string/auto_launch_label" /> - - <RelativeLayout + <TextView android:id="@+id/auto_launch" + android:textAppearance="?android:attr/textAppearanceSmall" + android:layout_alignParentStart="true" android:layout_width="match_parent" android:layout_height="wrap_content" - android:layout_gravity="center_vertical" - android:paddingStart="?android:attr/listPreferredItemPaddingStart" - android:paddingEnd="?android:attr/listPreferredItemPaddingEnd"> - - <TextView android:id="@+id/auto_launch" - android:textAppearance="?android:attr/textAppearanceSmall" - android:layout_alignParentStart="true" - android:layout_width="match_parent" - android:layout_height="wrap_content" - android:paddingTop="6dip" /> - - <LinearLayout - android:layout_width="match_parent" - android:layout_height="wrap_content" - android:layout_below="@id/auto_launch" - android:paddingTop="4dip" - android:orientation="horizontal"> + android:paddingTop="6dip" /> - <View - android:layout_width="120dip" - android:layout_height="0dip" - android:layout_weight="0.4" /> - <View - android:layout_width="0dip" - android:layout_height="0dip" - android:visibility="invisible" - android:layout_weight="0.2" /> - <Button - android:id="@+id/clear_activities_button" - android:layout_width="120dip" - android:layout_height="wrap_content" - android:layout_weight="0.4" - android:text="@string/clear_activities" /> - - </LinearLayout> - - </RelativeLayout> + <Button + android:id="@+id/clear_activities_button" + android:layout_marginStart="-4dip" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:text="@string/clear_activities" /> </LinearLayout> diff --git a/res/layout/default_apps_view.xml b/res/layout/default_apps_view.xml new file mode 100644 index 0000000..3c8cc29 --- /dev/null +++ b/res/layout/default_apps_view.xml @@ -0,0 +1,45 @@ +<?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. +--> + +<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" + android:layout_width="match_parent" + android:layout_height="match_parent" + android:orientation="vertical"> + + <FrameLayout + android:layout_width="match_parent" + android:layout_height="0px" + android:layout_weight="1"> + + <ListView android:id="@android:id/list" + style="@style/PreferenceFragmentListSinglePane" + android:layout_width="match_parent" + android:layout_height="match_parent" + android:drawSelectorOnTop="false" + android:scrollbarStyle="outsideOverlay" + android:fastScrollEnabled="true" /> + + <TextView android:id="@android:id/empty" + android:layout_width="match_parent" + android:layout_height="match_parent" + android:gravity="center" + android:text="@string/no_default_apps" + android:textAppearance="?android:attr/textAppearanceLarge" /> + + </FrameLayout> + +</LinearLayout> diff --git a/res/layout/default_apps_view_item.xml b/res/layout/default_apps_view_item.xml new file mode 100644 index 0000000..2ded826 --- /dev/null +++ b/res/layout/default_apps_view_item.xml @@ -0,0 +1,57 @@ +<?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. +--> + +<GridLayout xmlns:android="http://schemas.android.com/apk/res/android" + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:minHeight="?android:attr/listPreferredItemHeight" + android:paddingStart="?android:attr/listPreferredItemPaddingStart" + android:paddingEnd="?android:attr/listPreferredItemPaddingEnd" + android:paddingTop="8dip" + android:paddingBottom="8dip" + android:columnCount="4"> + + <ImageView + android:id="@+id/app_icon" + android:layout_width="@android:dimen/app_icon_size" + android:layout_height="@android:dimen/app_icon_size" + android:layout_rowSpan="2" + android:layout_marginEnd="8dip" + android:scaleType="centerInside" + android:contentDescription="@null" /> + + <TextView + android:id="@+id/app_name" + android:layout_width="0dip" + android:layout_columnSpan="2" + android:layout_gravity="fill_horizontal" + android:layout_marginTop="2dip" + android:singleLine="true" + android:ellipsize="marquee" + android:textAppearance="@android:style/TextAppearance.Material.Subhead" + android:textAlignment="viewStart"/> + + <TextView + android:id="@+id/app_domains" + android:layout_column="1" + android:layout_row="1" + android:layout_gravity="fill_horizontal|top" + android:textAppearance="@android:style/TextAppearance.Material.Body1" + android:textColor="?android:attr/textColorSecondary" + android:textAlignment="viewStart" /> + +</GridLayout> diff --git a/res/layout/manage_applications_item.xml b/res/layout/manage_applications_item.xml index 5471aa9..042d518 100755 --- a/res/layout/manage_applications_item.xml +++ b/res/layout/manage_applications_item.xml @@ -34,7 +34,8 @@ android:layout_rowSpan="2" android:layout_marginEnd="8dip" android:scaleType="centerInside" - android:contentDescription="@null" /> + android:contentDescription="@null" + android:duplicateParentState="true" /> <TextView android:id="@+id/app_name" @@ -45,7 +46,8 @@ android:singleLine="true" android:ellipsize="marquee" android:textAppearance="@android:style/TextAppearance.Material.Subhead" - android:textAlignment="viewStart"/> + android:textAlignment="viewStart" + android:duplicateParentState="true" /> <CheckBox android:id="@+id/app_on_sdcard" android:layout_marginStart="8dip" @@ -53,7 +55,8 @@ android:layout_rowSpan="2" android:visibility="gone" android:clickable="false" - android:focusable="false" /> + android:focusable="false" + android:duplicateParentState="true" /> <TextView android:id="@+id/app_size" @@ -62,7 +65,8 @@ android:layout_gravity="fill_horizontal|top" android:textAppearance="@android:style/TextAppearance.Material.Body1" android:textColor="?android:attr/textColorSecondary" - android:textAlignment="viewStart" /> + android:textAlignment="viewStart" + android:duplicateParentState="true" /> <TextView android:id="@+id/app_disabled" @@ -73,6 +77,7 @@ android:textColor="?android:attr/textColorSecondary" android:textAlignment="viewEnd" android:singleLine="true" - android:ellipsize="marquee" /> + android:ellipsize="marquee" + android:duplicateParentState="true" /> </GridLayout> diff --git a/res/values/strings.xml b/res/values/strings.xml index 3eaf38d..630d2a4 100644 --- a/res/values/strings.xml +++ b/res/values/strings.xml @@ -3052,6 +3052,9 @@ <!-- [CHAR LIMIT=NONE] Time label for an operation that has never executed. --> <string name="app_ops_never_used">(Never used)</string> + <!-- [CHAR LIMIT=25] Text shown when there are no default Apps --> + <string name="no_default_apps">No default Apps.</string> + <!-- [CHAR LIMIT=25] Services settings screen, setting option name for the user to go to the screen to view app storage use --> <string name="storageuse_settings_title">Storage use</string> <!-- Services settings screen, setting option summary for the user to go to the screen to app storage use --> @@ -6068,6 +6071,20 @@ <!-- Summary for app storage preference [CHAR LIMIT=15] --> <string name="storage_summary_format"><xliff:g id="size" example="30.00MB">%1$s</xliff:g> used in <xliff:g id="storage_type" example="internal storage">%2$s</xliff:g></string> + <!-- Category name for App Launch --> + <string name="app_launch_domain_links_title">Domain links</string> + <string name="app_launch_open_domain_urls_title">Open Domain URLs</string> + <string name="app_launch_open_domain_urls_summary">Allow app to directly open Domain URLs</string> + <string name="app_launch_supported_domain_urls_title">Supported domains URLs</string> + <string name="app_launch_other_defaults_title">Other defaults</string> + + <!-- Summary for app storage preference --> + <string name="storage_summary_format"><xliff:g id="size" example="30.00MB">%1$s</xliff:g> used in <xliff:g id="storage_type" example="internal memory">%2$s</xliff:g></string> + <!-- Internal storage label --> + <string name="storage_type_internal">internal memory</string> + <!-- External storage label --> + <string name="storage_type_external">external memory</string> + <!-- Summary describing internal storage for applications [CHAR LIMIT=25] --> <string name="storage_type_internal">Internal storage</string> <!-- Summary describing external storage for applications [CHAR LIMIT=25] --> @@ -6117,12 +6134,13 @@ <string name="filter_notif_priority_apps">Priority</string> <!-- Label for showing apps with sensitive notifications in list [CHAR LIMIT=30] --> <string name="filter_notif_sensitive_apps">Sensitive</string> + <!-- Label for showing apps with domain URLs (data URI with http or https) in list [CHAR LIMIT=30] --> + <string name="filter_with_domain_urls_apps">With domain URLs</string> <!-- Description for advanced menu option to reset app preferences [CHAR LIMIT=NONE] --> <string name="reset_app_preferences_description">Reset preferences across all apps to defaults</string> - <!-- Description of settings item that leads to list of all apps - [CHAR LIMIT=NONE] --> + <!-- Description of settings item that leads to list of all apps [CHAR LIMIT=NONE] --> <string name="all_apps_summary"><xliff:g id="count" example="10">%d</xliff:g> apps installed, including system and downloaded apps</string> <!-- Title for advanced application management settings [CHAR LIMIT=30] --> @@ -6142,4 +6160,23 @@ LIMIT=45] --> <string name="app_permissions_group_summary"><xliff:g id="count" example="10">%d</xliff:g> of <xliff:g id="count" example="10">%d</xliff:g> apps allowed</string> + <!-- Label for the Domain URLs list that shows domain urls per App [CHAR LIMIT=30] --> + <string name="domain_urls_title">Domain URLs</string> + + <!-- Summary for an App that dont open any domain URLs [CHAR LIMIT=45] --> + <string name="domain_urls_summary_none">Don\'t open any domain URL</string> + + <!-- Summary of number of App that can open one and only one domain URLs [CHAR LIMIT=45] --> + <string name="domain_urls_summary_one">Open \'<xliff:g id="domain" example="mail.google.com">%s</xliff:g>\'</string> + + <!-- Summary of number of App that can open several domain URLs [CHAR LIMIT=45] --> + <string name="domain_urls_summary_some">Open \'<xliff:g id="domain" example="mail.google.com">%s</xliff:g>\' and related URLs</string> + + <!-- Description of settings item that leads to list of all apps with Domain URLs [CHAR LIMIT=NONE] --> + <plurals name="domain_urls_apps_summary"> + <item quantity="zero">No app can open any domain URL</item> + <item quantity="one">One app can open its domain URLs</item> + <item quantity="other"><xliff:g id="count" example="10">%d</xliff:g> apps can open their domain URLs</item> + </plurals> + </resources> diff --git a/res/xml/advanced_apps.xml b/res/xml/advanced_apps.xml index 2bbd5be..682ab2d 100644 --- a/res/xml/advanced_apps.xml +++ b/res/xml/advanced_apps.xml @@ -26,6 +26,15 @@ settings:keywords="@string/keywords_app_permissions" /> <PreferenceScreen + android:key="domain_urls" + android:title="@string/domain_urls_title" + android:fragment="com.android.settings.applications.ManageApplications"> + <extra + android:name="classname" + android:value="com.android.settings.Settings$DomainsURLsAppListActivity" /> + </PreferenceScreen> + + <PreferenceScreen android:key="all_apps" android:fragment="com.android.settings.applications.ManageApplications" android:title="@string/filter_all_apps" diff --git a/res/xml/installed_app_launch_settings.xml b/res/xml/installed_app_launch_settings.xml new file mode 100644 index 0000000..7d6642c --- /dev/null +++ b/res/xml/installed_app_launch_settings.xml @@ -0,0 +1,49 @@ +<?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" + android:title="@string/application_info_label"> + + <PreferenceCategory android:key="app_launch_domain_links" + android:title="@string/app_launch_domain_links_title"> + + <SwitchPreference + android:key="app_launch_open_domain_urls" + android:title="@string/app_launch_open_domain_urls_title" + android:summary="@string/app_launch_open_domain_urls_summary" + /> + + + <com.android.settings.applications.AppDomainsPreference + android:key="app_launch_supported_domain_urls" + android:title="@string/app_launch_supported_domain_urls_title" + android:persistent="false" + android:dependency="app_launch_open_domain_urls" + /> + + </PreferenceCategory> + + <PreferenceCategory android:key="app_launch_other_defaults" + android:title="@string/app_launch_other_defaults_title"> + + <com.android.settings.applications.ClearDefaultsPreference + android:key="app_launch_clear_defaults" + android:persistent="false" + /> + + </PreferenceCategory> + +</PreferenceScreen> diff --git a/src/com/android/settings/Settings.java b/src/com/android/settings/Settings.java index 20ce116..864cc95 100644 --- a/src/com/android/settings/Settings.java +++ b/src/com/android/settings/Settings.java @@ -98,6 +98,7 @@ public class Settings extends SettingsActivity { public static class NotificationAppListActivity extends SettingsActivity { /* empty */ } public static class AppNotificationSettingsActivity extends SettingsActivity { /* empty */ } public static class OtherSoundSettingsActivity extends SettingsActivity { /* empty */ } + public static class DomainsURLsAppListActivity extends SettingsActivity { /* empty */ } public static class TopLevelSettings extends SettingsActivity { /* empty */ } public static class ApnSettingsActivity extends SettingsActivity { /* empty */ } diff --git a/src/com/android/settings/Utils.java b/src/com/android/settings/Utils.java index bc6cbed..23b2c85 100644 --- a/src/com/android/settings/Utils.java +++ b/src/com/android/settings/Utils.java @@ -25,10 +25,12 @@ import android.app.AlertDialog; import android.app.Dialog; import android.app.Fragment; import android.app.IActivityManager; +import android.content.ComponentName; import android.content.ContentResolver; import android.content.Context; import android.content.DialogInterface; import android.content.Intent; +import android.content.IntentFilter; import android.content.pm.ApplicationInfo; import android.content.pm.PackageInfo; import android.content.pm.PackageManager; @@ -43,6 +45,7 @@ import android.database.Cursor; import android.graphics.Bitmap; import android.graphics.BitmapFactory; import android.graphics.drawable.Drawable; +import android.hardware.usb.IUsbManager; import android.net.ConnectivityManager; import android.net.LinkProperties; import android.net.Uri; @@ -76,6 +79,7 @@ import android.widget.TabWidget; import com.android.internal.util.UserIcons; import com.android.settings.UserAdapter.UserDetails; +import com.android.settings.applications.ApplicationsState; import com.android.settings.dashboard.DashboardTile; import com.android.settings.drawable.CircleFramedDrawable; @@ -84,6 +88,7 @@ import java.io.InputStream; import java.net.InetAddress; import java.text.NumberFormat; import java.util.ArrayList; +import java.util.Collections; import java.util.Iterator; import java.util.List; import java.util.Locale; @@ -1101,7 +1106,6 @@ public final class Utils { return (sm.getStorageBytesUntilLow(context.getFilesDir()) < 0); } - /** * Returns a default user icon (as a {@link Bitmap}) for the given user. * @@ -1119,4 +1123,39 @@ public final class Utils { } return bitmap; } + + public static boolean hasUsbDefaults(IUsbManager usbManager, String packageName) { + try { + if (usbManager != null) { + return usbManager.hasDefaults(packageName, UserHandle.myUserId()); + } + } catch (RemoteException e) { + Log.e(TAG, "mUsbManager.hasDefaults", e); + } + return false; + } + + public static boolean hasPreferredActivities(PackageManager pm, String packageName) { + // Get list of preferred activities + List<ComponentName> prefActList = new ArrayList<>(); + // Intent list cannot be null. so pass empty list + List<IntentFilter> intentList = new ArrayList<>(); + pm.getPreferredActivities(intentList, prefActList, packageName); + Log.d(TAG, "Have " + prefActList.size() + " number of activities in preferred list"); + return prefActList.size() > 0; + } + + public static CharSequence getLaunchByDeafaultSummary(ApplicationsState.AppEntry appEntry, + IUsbManager usbManager, PackageManager pm, Context context) { + String packageName = appEntry.info.packageName; + boolean hasPreferred = hasPreferredActivities(pm, packageName) + || hasUsbDefaults(usbManager, packageName); + int status = pm.getIntentVerificationStatus(packageName, UserHandle.myUserId()); + boolean hasDomainURLsPreference = + (status == PackageManager.INTENT_FILTER_DOMAIN_VERIFICATION_STATUS_ALWAYS) || + (status == PackageManager.INTENT_FILTER_DOMAIN_VERIFICATION_STATUS_NEVER); + return context.getString(hasPreferred || hasDomainURLsPreference + ? R.string.launch_defaults_some + : R.string.launch_defaults_none); + } } diff --git a/src/com/android/settings/applications/AdvancedAppSettings.java b/src/com/android/settings/applications/AdvancedAppSettings.java index d5ab8dc..3d3c9f6 100644 --- a/src/com/android/settings/applications/AdvancedAppSettings.java +++ b/src/com/android/settings/applications/AdvancedAppSettings.java @@ -18,6 +18,7 @@ package com.android.settings.applications; import static android.net.NetworkPolicyManager.POLICY_NONE; import static android.net.NetworkPolicyManager.POLICY_REJECT_METERED_BACKGROUND; +import android.app.Activity; import android.app.ActivityManager; import android.app.AlertDialog; import android.app.AppOpsManager; @@ -26,7 +27,6 @@ import android.content.Context; import android.content.DialogInterface; import android.content.pm.ApplicationInfo; import android.content.pm.IPackageManager; -import android.content.pm.PackageInfo; import android.content.pm.PackageManager; import android.net.NetworkPolicyManager; import android.os.AsyncTask; @@ -35,11 +35,9 @@ import android.os.Handler; import android.os.RemoteException; import android.os.ServiceManager; import android.os.UserHandle; -import android.os.UserManager; import android.preference.Preference; import android.preference.Preference.OnPreferenceClickListener; import android.util.Log; -import android.util.Pair; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; @@ -63,14 +61,16 @@ public class AdvancedAppSettings extends SettingsPreferenceFragment implements C private static final String KEY_APP_PERM = "manage_perms"; private static final String KEY_ALL_APPS = "all_apps"; + private static final String KEY_APP_DOMAIN_URLS = "domain_urls"; private static final String KEY_RESET_ALL = "reset_all"; private static final String EXTRA_RESET_DIALOG = "resetDialog"; private ApplicationsState mApplicationsState; private Session mSession; - private Preference mAppPerms; - private Preference mAllApps; - private Preference mResetAll; + private Preference mAppPermsPreference; + private Preference mAppDomainURLsPreference; + private Preference mAllAppsPreference; + private Preference mResetAllPreference; AlertDialog mResetDialog; @@ -91,17 +91,18 @@ public class AdvancedAppSettings extends SettingsPreferenceFragment implements C mApplicationsState = ApplicationsState.getInstance(getActivity().getApplication()); mSession = mApplicationsState.newSession(this); - mAppPerms = findPreference(KEY_APP_PERM); - mAllApps = findPreference(KEY_ALL_APPS); - mResetAll = findPreference(KEY_RESET_ALL); - mResetAll.setOnPreferenceClickListener(new OnPreferenceClickListener() { + mAppPermsPreference = findPreference(KEY_APP_PERM); + mAppDomainURLsPreference = findPreference(KEY_APP_DOMAIN_URLS); + mAllAppsPreference = findPreference(KEY_ALL_APPS); + mResetAllPreference = findPreference(KEY_RESET_ALL); + mResetAllPreference.setOnPreferenceClickListener(new OnPreferenceClickListener() { @Override public boolean onPreferenceClick(Preference preference) { buildResetDialog(); return true; } }); - updateAllAppsSummary(); + updateUI(); mPm = getActivity().getPackageManager(); mIPm = IPackageManager.Stub.asInterface(ServiceManager.getService("package")); @@ -112,8 +113,19 @@ public class AdvancedAppSettings extends SettingsPreferenceFragment implements C mHandler = new Handler(getActivity().getMainLooper()); } - private void updateAllAppsSummary() { - mAllApps.setSummary(getString(R.string.all_apps_summary, mSession.getAllApps().size())); + private void updateUI() { + ArrayList<AppEntry> allApps = mSession.getAllApps(); + mAllAppsPreference.setSummary(getString(R.string.all_apps_summary, allApps.size())); + + int countAppWithDomainURLs = 0; + for (AppEntry entry : allApps) { + boolean hasDomainURLs = + (entry.info.privateFlags & ApplicationInfo.PRIVATE_FLAG_HAS_DOMAIN_URLS) != 0; + if (hasDomainURLs) countAppWithDomainURLs++; + } + String summary = getResources().getQuantityString( + R.plurals.domain_urls_apps_summary, countAppWithDomainURLs, countAppWithDomainURLs); + mAppDomainURLsPreference.setSummary(summary); } @Override @@ -241,7 +253,7 @@ public class AdvancedAppSettings extends SettingsPreferenceFragment implements C @Override public void onPackageListChanged() { - updateAllAppsSummary(); + updateUI(); } @Override @@ -276,7 +288,9 @@ public class AdvancedAppSettings extends SettingsPreferenceFragment implements C @Override public void onPermissionLoadComplete() { - mAppPerms.setSummary(getActivity().getString(R.string.app_permissions_summary, + Activity activity = getActivity(); + if (activity == null) return; + mAppPermsPreference.setSummary(activity.getString(R.string.app_permissions_summary, mPermissionsInfo.getRuntimePermAppsGrantedCount(), mPermissionsInfo.getRuntimePermAppsCount())); } diff --git a/src/com/android/settings/applications/AppDomainsPreference.java b/src/com/android/settings/applications/AppDomainsPreference.java new file mode 100644 index 0000000..7e29a20 --- /dev/null +++ b/src/com/android/settings/applications/AppDomainsPreference.java @@ -0,0 +1,44 @@ +/* + * 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.util.AttributeSet; +import android.view.View; +import android.widget.TextView; +import com.android.settings.accessibility.ListDialogPreference; + +import com.android.settings.R; + +public class AppDomainsPreference extends ListDialogPreference { + + public AppDomainsPreference(Context context, AttributeSet attrs) { + super(context, attrs); + + setDialogLayoutResource(R.layout.app_domains_dialog); + setListItemLayoutResource(R.layout.app_domains_item); + } + + @Override + protected void onBindListItem(View view, int index) { + final CharSequence title = getTitleAt(index); + if (title != null) { + final TextView domainName = (TextView) view.findViewById(R.id.domain_name); + domainName.setText(title); + } + } +} diff --git a/src/com/android/settings/applications/AppLaunchSettings.java b/src/com/android/settings/applications/AppLaunchSettings.java index ffb84ef..c0a662a 100644 --- a/src/com/android/settings/applications/AppLaunchSettings.java +++ b/src/com/android/settings/applications/AppLaunchSettings.java @@ -17,117 +17,78 @@ package com.android.settings.applications; import android.app.AlertDialog; -import android.appwidget.AppWidgetManager; -import android.content.ComponentName; -import android.content.Context; -import android.content.IntentFilter; +import android.content.pm.IntentFilterVerificationInfo; import android.content.pm.PackageManager; -import android.hardware.usb.IUsbManager; import android.os.Bundle; -import android.os.RemoteException; import android.os.UserHandle; -import android.text.SpannableString; -import android.text.TextUtils; -import android.text.style.BulletSpan; -import android.util.Log; -import android.view.LayoutInflater; +import android.preference.Preference; +import android.preference.SwitchPreference; +import android.util.ArraySet; import android.view.View; import android.view.View.OnClickListener; -import android.view.ViewGroup; -import android.widget.Button; -import android.widget.TextView; import com.android.internal.logging.MetricsLogger; import com.android.settings.R; -import com.android.settings.Utils; -import com.android.settings.applications.ApplicationsState.AppEntry; -import java.util.ArrayList; import java.util.List; -public class AppLaunchSettings extends AppInfoWithHeader implements OnClickListener { +public class AppLaunchSettings extends AppInfoWithHeader implements OnClickListener, + Preference.OnPreferenceChangeListener { - private Button mActivitiesButton; - private AppWidgetManager mAppWidgetManager; + private static final String KEY_OPEN_DOMAIN_URLS = "app_launch_open_domain_urls"; + private static final String KEY_SUPPORTED_DOMAIN_URLS = "app_launch_supported_domain_urls"; + private static final String KEY_CLEAR_DEFAULTS = "app_launch_clear_defaults"; - private View mRootView; + private PackageManager mPm; + + private SwitchPreference mOpenDomainUrls; + private AppDomainsPreference mAppDomainUrls; + private ClearDefaultsPreference mClearDefaultsPreference; @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); - mAppWidgetManager = AppWidgetManager.getInstance(getActivity()); - } - @Override - public View onCreateView(LayoutInflater inflater, ViewGroup container, - Bundle savedInstanceState) { - final View view = inflater.inflate(R.layout.app_preferred_settings, container, false); + addPreferencesFromResource(R.xml.installed_app_launch_settings); + + mPm = getActivity().getPackageManager(); + final int myUserId = UserHandle.myUserId(); - final ViewGroup allDetails = (ViewGroup) view.findViewById(R.id.all_details); - Utils.forceCustomPadding(allDetails, true /* additive padding */); + mOpenDomainUrls = (SwitchPreference) findPreference(KEY_OPEN_DOMAIN_URLS); + mOpenDomainUrls.setOnPreferenceChangeListener(this); - mActivitiesButton = (Button) view.findViewById(R.id.clear_activities_button); - mRootView = view; + final int status = mPm.getIntentVerificationStatus(mPackageName, myUserId); + boolean checked = status == PackageManager.INTENT_FILTER_DOMAIN_VERIFICATION_STATUS_ALWAYS; + mOpenDomainUrls.setChecked(checked); - return view; + mAppDomainUrls = (AppDomainsPreference) findPreference(KEY_SUPPORTED_DOMAIN_URLS); + CharSequence[] entries = getEntries(mPackageName); + mAppDomainUrls.setTitles(entries); + mAppDomainUrls.setValues(new int[entries.length]); + + mClearDefaultsPreference = (ClearDefaultsPreference) findPreference(KEY_CLEAR_DEFAULTS); } - @Override - protected boolean refreshUi() { - retrieveAppEntry(); - boolean hasBindAppWidgetPermission = - mAppWidgetManager.hasBindAppWidgetPermission(mAppEntry.info.packageName); - - TextView autoLaunchTitleView = (TextView) mRootView.findViewById(R.id.auto_launch_title); - TextView autoLaunchView = (TextView) mRootView.findViewById(R.id.auto_launch); - boolean autoLaunchEnabled = hasPreferredActivities(mPm, mPackageName) - || hasUsbDefaults(mUsbManager, mPackageName); - if (!autoLaunchEnabled && !hasBindAppWidgetPermission) { - resetLaunchDefaultsUi(autoLaunchTitleView, autoLaunchView); - } else { - boolean useBullets = hasBindAppWidgetPermission && autoLaunchEnabled; - - if (hasBindAppWidgetPermission) { - autoLaunchTitleView.setText(R.string.auto_launch_label_generic); - } else { - autoLaunchTitleView.setText(R.string.auto_launch_label); - } + private CharSequence[] getEntries(String packageName) { + ArraySet<String> result = new ArraySet<>(); - CharSequence text = null; - int bulletIndent = getResources() - .getDimensionPixelSize(R.dimen.installed_app_details_bullet_offset); - if (autoLaunchEnabled) { - CharSequence autoLaunchEnableText = getText(R.string.auto_launch_enable_text); - SpannableString s = new SpannableString(autoLaunchEnableText); - if (useBullets) { - s.setSpan(new BulletSpan(bulletIndent), 0, autoLaunchEnableText.length(), 0); - } - text = (text == null) ? - TextUtils.concat(s, "\n") : TextUtils.concat(text, "\n", s, "\n"); - } - if (hasBindAppWidgetPermission) { - CharSequence alwaysAllowBindAppWidgetsText = - getText(R.string.always_allow_bind_appwidgets_text); - SpannableString s = new SpannableString(alwaysAllowBindAppWidgetsText); - if (useBullets) { - s.setSpan(new BulletSpan(bulletIndent), - 0, alwaysAllowBindAppWidgetsText.length(), 0); - } - text = (text == null) ? - TextUtils.concat(s, "\n") : TextUtils.concat(text, "\n", s, "\n"); + List<IntentFilterVerificationInfo> list = + mPm.getIntentFilterVerifications(packageName); + for (IntentFilterVerificationInfo ivi : list) { + for (String host : ivi.getDomains()) { + result.add(host); } - autoLaunchView.setText(text); - mActivitiesButton.setEnabled(true); - mActivitiesButton.setOnClickListener(this); } - return true; + + return result.toArray(new CharSequence[0]); } - private void resetLaunchDefaultsUi(TextView title, TextView autoLaunchView) { - title.setText(R.string.auto_launch_label); - autoLaunchView.setText(R.string.auto_launch_disable_text); - // Disable clear activities button - mActivitiesButton.setEnabled(false); + @Override + protected boolean refreshUi() { + mClearDefaultsPreference.setPackageName(mPackageName); + mClearDefaultsPreference.setAppEntry(mAppEntry); + + return true; } @Override @@ -136,56 +97,24 @@ public class AppLaunchSettings extends AppInfoWithHeader implements OnClickListe return null; } + @Override public void onClick(View v) { - if (v == mActivitiesButton) { - if (mUsbManager != null) { - mPm.clearPackagePreferredActivities(mPackageName); - try { - mUsbManager.clearDefaults(mPackageName, UserHandle.myUserId()); - } catch (RemoteException e) { - Log.e(TAG, "mUsbManager.clearDefaults", e); - } - mAppWidgetManager.setBindAppWidgetPermission(mPackageName, false); - TextView autoLaunchTitleView = - (TextView) mRootView.findViewById(R.id.auto_launch_title); - TextView autoLaunchView = (TextView) mRootView.findViewById(R.id.auto_launch); - resetLaunchDefaultsUi(autoLaunchTitleView, autoLaunchView); - } - } - } - - private static boolean hasUsbDefaults(IUsbManager usbManager, String packageName) { - try { - if (usbManager != null) { - return usbManager.hasDefaults(packageName, UserHandle.myUserId()); - } - } catch (RemoteException e) { - Log.e(TAG, "mUsbManager.hasDefaults", e); - } - return false; + // Nothing to do } - private static boolean hasPreferredActivities(PackageManager pm, String packageName) { - // Get list of preferred activities - List<ComponentName> prefActList = new ArrayList<>(); - // Intent list cannot be null. so pass empty list - List<IntentFilter> intentList = new ArrayList<>(); - pm.getPreferredActivities(intentList, prefActList, packageName); - if (localLOGV) { - Log.i(TAG, "Have " + prefActList.size() + " number of activities in preferred list"); + @Override + public boolean onPreferenceChange(Preference preference, Object newValue) { + boolean ret = false; + final String key = preference.getKey(); + if (KEY_OPEN_DOMAIN_URLS.equals(key)) { + SwitchPreference pref = (SwitchPreference) preference; + int status = !pref.isChecked() ? + PackageManager.INTENT_FILTER_DOMAIN_VERIFICATION_STATUS_ALWAYS : + PackageManager.INTENT_FILTER_DOMAIN_VERIFICATION_STATUS_NEVER; + ret = mPm.updateIntentVerificationStatus(mPackageName, status, UserHandle.myUserId()); } - return prefActList.size() > 0; - } - - public static CharSequence getSummary(AppEntry appEntry, IUsbManager usbManager, - PackageManager pm, Context context) { - String packageName = appEntry.info.packageName; - boolean hasPreferred = hasPreferredActivities(pm, packageName) - || hasUsbDefaults(usbManager, packageName); - return context.getString(hasPreferred - ? R.string.launch_defaults_some - : R.string.launch_defaults_none); + return ret; } @Override diff --git a/src/com/android/settings/applications/AppViewHolder.java b/src/com/android/settings/applications/AppViewHolder.java index 176ccca..92aa87a 100644 --- a/src/com/android/settings/applications/AppViewHolder.java +++ b/src/com/android/settings/applications/AppViewHolder.java @@ -1,3 +1,19 @@ +/* + * 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 com.android.settings.R; diff --git a/src/com/android/settings/applications/ApplicationsState.java b/src/com/android/settings/applications/ApplicationsState.java index daa3842..71d0790 100644 --- a/src/com/android/settings/applications/ApplicationsState.java +++ b/src/com/android/settings/applications/ApplicationsState.java @@ -1,3 +1,19 @@ +/* + * Copyright (C) 2015 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + package com.android.settings.applications; import android.app.ActivityManager; @@ -116,7 +132,7 @@ public class ApplicationsState { } // Need to synchronize on 'this' for the following. - ApplicationInfo info; + public ApplicationInfo info; Drawable icon; String sizeStr; String internalSizeStr; @@ -323,6 +339,16 @@ public class ApplicationsState { } }; + public static final AppFilter FILTER_WITH_DOMAIN_URLS = new AppFilter() { + public void init() { + } + + @Override + public boolean filterApp(AppEntry entry) { + return (entry.info.privateFlags & ApplicationInfo.PRIVATE_FLAG_HAS_DOMAIN_URLS) != 0; + } + }; + final Context mContext; final PackageManager mPm; final IPackageManager mIpm; diff --git a/src/com/android/settings/applications/ClearDefaultsPreference.java b/src/com/android/settings/applications/ClearDefaultsPreference.java new file mode 100644 index 0000000..1799cad --- /dev/null +++ b/src/com/android/settings/applications/ClearDefaultsPreference.java @@ -0,0 +1,172 @@ +/* + * 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.appwidget.AppWidgetManager; +import android.content.Context; +import android.content.pm.PackageManager; +import android.hardware.usb.IUsbManager; +import android.os.IBinder; +import android.os.RemoteException; +import android.os.ServiceManager; +import android.os.UserHandle; +import android.preference.Preference; +import android.text.SpannableString; +import android.text.TextUtils; +import android.text.style.BulletSpan; +import android.util.AttributeSet; +import android.util.Log; +import android.view.View; +import android.view.ViewGroup; +import android.widget.Button; +import android.widget.TextView; + +import com.android.settings.R; +import com.android.settings.Utils; + +public class ClearDefaultsPreference extends Preference { + + protected static final String TAG = ClearDefaultsPreference.class.getSimpleName(); + + private View mRootView; + private Button mActivitiesButton; + + private AppWidgetManager mAppWidgetManager; + private IUsbManager mUsbManager; + private PackageManager mPm; + private String mPackageName; + protected ApplicationsState.AppEntry mAppEntry; + + public ClearDefaultsPreference(Context context, AttributeSet attrs, int defStyleAttr, + int defStyleRes) { + super(context, attrs, defStyleAttr, defStyleRes); + + setLayoutResource(R.layout.app_preferred_settings); + + mAppWidgetManager = AppWidgetManager.getInstance(context); + mPm = context.getPackageManager(); + IBinder b = ServiceManager.getService(Context.USB_SERVICE); + mUsbManager = IUsbManager.Stub.asInterface(b); + } + + public ClearDefaultsPreference(Context context, AttributeSet attrs, int defStyleAttr) { + this(context, attrs, defStyleAttr, 0); + } + + public ClearDefaultsPreference(Context context, AttributeSet attrs) { + this(context, attrs, 0); + } + + public ClearDefaultsPreference(Context context) { + this(context, null); + } + + public void setPackageName(String packageName) { + mPackageName = packageName; + } + + public void setAppEntry(ApplicationsState.AppEntry entry) { + mAppEntry = entry; + } + + @Override + protected View onCreateView(ViewGroup parent) { + mRootView = super.onCreateView(parent); + + mActivitiesButton = (Button) mRootView.findViewById(R.id.clear_activities_button); + mActivitiesButton.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + if (mUsbManager != null) { + mPm.clearPackagePreferredActivities(mPackageName); + try { + mUsbManager.clearDefaults(mPackageName, UserHandle.myUserId()); + } catch (RemoteException e) { + Log.e(TAG, "mUsbManager.clearDefaults", e); + } + mAppWidgetManager.setBindAppWidgetPermission(mPackageName, false); + TextView autoLaunchView = (TextView) mRootView.findViewById(R.id.auto_launch); + resetLaunchDefaultsUi(autoLaunchView); + } + } + }); + + return mRootView; + } + + @Override + protected void onBindView(View view) { + super.onBindView(view); + + updateUI(); + } + + public boolean updateUI() { + boolean hasBindAppWidgetPermission = + mAppWidgetManager.hasBindAppWidgetPermission(mAppEntry.info.packageName); + + TextView autoLaunchView = (TextView) mRootView.findViewById(R.id.auto_launch); + boolean autoLaunchEnabled = Utils.hasPreferredActivities(mPm, mPackageName) + || Utils.hasUsbDefaults(mUsbManager, mPackageName); + if (!autoLaunchEnabled && !hasBindAppWidgetPermission) { + resetLaunchDefaultsUi(autoLaunchView); + } else { + boolean useBullets = hasBindAppWidgetPermission && autoLaunchEnabled; + + if (hasBindAppWidgetPermission) { + autoLaunchView.setText(R.string.auto_launch_label_generic); + } else { + autoLaunchView.setText(R.string.auto_launch_label); + } + + Context context = getContext(); + CharSequence text = null; + int bulletIndent = context.getResources().getDimensionPixelSize( + R.dimen.installed_app_details_bullet_offset); + if (autoLaunchEnabled) { + CharSequence autoLaunchEnableText = context.getText( + R.string.auto_launch_enable_text); + SpannableString s = new SpannableString(autoLaunchEnableText); + if (useBullets) { + s.setSpan(new BulletSpan(bulletIndent), 0, autoLaunchEnableText.length(), 0); + } + text = (text == null) ? + TextUtils.concat(s, "\n") : TextUtils.concat(text, "\n", s, "\n"); + } + if (hasBindAppWidgetPermission) { + CharSequence alwaysAllowBindAppWidgetsText = + context.getText(R.string.always_allow_bind_appwidgets_text); + SpannableString s = new SpannableString(alwaysAllowBindAppWidgetsText); + if (useBullets) { + s.setSpan(new BulletSpan(bulletIndent), + 0, alwaysAllowBindAppWidgetsText.length(), 0); + } + text = (text == null) ? + TextUtils.concat(s, "\n") : TextUtils.concat(text, "\n", s, "\n"); + } + autoLaunchView.setText(text); + mActivitiesButton.setEnabled(true); + } + return true; + } + + private void resetLaunchDefaultsUi(TextView autoLaunchView) { + autoLaunchView.setText(R.string.auto_launch_disable_text); + // Disable clear activities button + mActivitiesButton.setEnabled(false); + } +} diff --git a/src/com/android/settings/applications/InstalledAppDetails.java b/src/com/android/settings/applications/InstalledAppDetails.java index 9f6c969..33a7428 100755 --- a/src/com/android/settings/applications/InstalledAppDetails.java +++ b/src/com/android/settings/applications/InstalledAppDetails.java @@ -261,10 +261,17 @@ public class InstalledAppDetails extends AppInfoBase mStoragePreference.setOnPreferenceClickListener(this); mPermissionsPreference = findPreference(KEY_PERMISSION); mPermissionsPreference.setOnPreferenceClickListener(this); - mLaunchPreference = findPreference(KEY_LAUNCH); - mLaunchPreference.setOnPreferenceClickListener(this); mDataPreference = findPreference(KEY_DATA); mDataPreference.setOnPreferenceClickListener(this); + + mLaunchPreference = findPreference(KEY_LAUNCH); + if ((mAppEntry.info.flags&ApplicationInfo.FLAG_INSTALLED) == 0) { + mLaunchPreference.setEnabled(false); + } else if (!mAppEntry.info.enabled) { + mLaunchPreference.setEnabled(false); + } else { + mLaunchPreference.setOnPreferenceClickListener(this); + } } private void handleHeader() { @@ -421,7 +428,7 @@ public class InstalledAppDetails extends AppInfoBase Activity context = getActivity(); mStoragePreference.setSummary(AppStorageSettings.getSummary(mAppEntry, context)); mPermissionsPreference.setSummary(AppPermissionSettings.getSummary(mAppEntry, context)); - mLaunchPreference.setSummary(AppLaunchSettings.getSummary(mAppEntry, mUsbManager, + mLaunchPreference.setSummary(Utils.getLaunchByDeafaultSummary(mAppEntry, mUsbManager, mPm, context)); mNotificationPreference.setSummary(getNotificationSummary(mAppEntry, context, mBackend)); diff --git a/src/com/android/settings/applications/ManageApplications.java b/src/com/android/settings/applications/ManageApplications.java index 84b9763..b416aef 100644 --- a/src/com/android/settings/applications/ManageApplications.java +++ b/src/com/android/settings/applications/ManageApplications.java @@ -17,12 +17,13 @@ package com.android.settings.applications; import android.app.Activity; -import android.app.Fragment; import android.content.Context; import android.content.Intent; import android.content.pm.ApplicationInfo; import android.content.pm.IPackageManager; +import android.content.pm.IntentFilterVerificationInfo; import android.content.pm.PackageInfo; +import android.content.pm.PackageManager; import android.net.Uri; import android.os.Bundle; import android.os.Environment; @@ -32,6 +33,7 @@ import android.os.UserHandle; import android.os.UserManager; import android.preference.PreferenceFrameLayout; import android.provider.Settings; +import android.util.ArraySet; import android.util.Log; import android.view.LayoutInflater; import android.view.Menu; @@ -63,10 +65,12 @@ import com.android.settings.applications.ApplicationsState.AppEntry; import com.android.settings.applications.ApplicationsState.AppFilter; import com.android.settings.notification.NotificationBackend; import com.android.settings.notification.NotificationBackend.AppRow; +import com.android.settings.Settings.DomainsURLsAppListActivity; import java.util.ArrayList; import java.util.Collections; import java.util.Comparator; +import java.util.List; final class CanBeOnSdCardChecker { final IPackageManager mPm; @@ -145,6 +149,7 @@ public class ManageApplications extends InstrumentedFragment public static final int FILTER_APPS_SENSITIVE = 6; public static final int FILTER_APPS_PERSONAL = 7; public static final int FILTER_APPS_WORK = 8; + public static final int FILTER_APPS_WITH_DOMAIN_URLS = 9; // This is the string labels for the filter modes above, the order must be kept in sync. public static final int[] FILTER_LABELS = new int[] { @@ -157,6 +162,7 @@ public class ManageApplications extends InstrumentedFragment R.string.filter_notif_sensitive_apps, // Sensitive Notifications R.string.filter_personal_apps, // Personal R.string.filter_work_apps, // Work + R.string.filter_with_domain_urls_apps, // Domain URLs }; // This is the actual mapping to filters from FILTER_ constants above, the order must // be kept in sync. @@ -170,6 +176,7 @@ public class ManageApplications extends InstrumentedFragment AppStateNotificationBridge.FILTER_APP_NOTIFICATION_SENSITIVE, // Sensitive Notifications ApplicationsState.FILTER_PERSONAL, // Personal ApplicationsState.FILTER_WORK, // Work + ApplicationsState.FILTER_WITH_DOMAIN_URLS, // Apps with Domain URLs }; // sort order that can be changed through the menu can be sorted alphabetically @@ -209,6 +216,7 @@ public class ManageApplications extends InstrumentedFragment public static final int LIST_TYPE_MAIN = 0; public static final int LIST_TYPE_ALL = 1; public static final int LIST_TYPE_NOTIFICATION = 2; + public static final int LIST_TYPE_DOMAINS_URLS = 3; private View mRootView; @@ -224,7 +232,6 @@ public class ManageApplications extends InstrumentedFragment mApplicationsState = ApplicationsState.getInstance(getActivity().getApplication()); Intent intent = getActivity().getIntent(); - String action = intent.getAction(); String className = getArguments() != null ? getArguments().getString("classname") : null; if (className == null) { @@ -235,6 +242,8 @@ public class ManageApplications extends InstrumentedFragment } else if (className.equals(NotificationAppListActivity.class.getName())) { mListType = LIST_TYPE_NOTIFICATION; mNotifBackend = new NotificationBackend(); + } else if (className.equals(DomainsURLsAppListActivity.class.getName())) { + mListType = LIST_TYPE_DOMAINS_URLS; } else { mListType = LIST_TYPE_MAIN; } @@ -311,12 +320,17 @@ public class ManageApplications extends InstrumentedFragment mFilterAdapter.enableFilter(FILTER_APPS_BLOCKED); mFilterAdapter.enableFilter(FILTER_APPS_PRIORITY); mFilterAdapter.enableFilter(FILTER_APPS_SENSITIVE); + } else if (mListType == LIST_TYPE_DOMAINS_URLS) { + mFilterAdapter.disableFilter(FILTER_APPS_ALL); + mFilterAdapter.enableFilter(FILTER_APPS_WITH_DOMAIN_URLS); } } private int getDefaultFilter() { if (mListType == LIST_TYPE_MAIN) { return FILTER_APPS_DOWNLOADED_AND_LAUNCHER; + } else if (mListType == LIST_TYPE_DOMAINS_URLS) { + return FILTER_APPS_WITH_DOMAIN_URLS; } return FILTER_APPS_ALL; } @@ -330,6 +344,8 @@ public class ManageApplications extends InstrumentedFragment return MetricsLogger.MANAGE_APPLICATIONS_ALL; case LIST_TYPE_NOTIFICATION: return MetricsLogger.MANAGE_APPLICATIONS_NOTIFICATIONS; + case LIST_TYPE_DOMAINS_URLS: + return MetricsLogger.MANAGE_DOMAIN_URLS; default: return MetricsLogger.VIEW_UNKNOWN; } @@ -382,24 +398,39 @@ public class ManageApplications extends InstrumentedFragment // utility method used to start sub activity private void startApplicationDetailsActivity() { + Activity activity = getActivity(); if (mListType == LIST_TYPE_NOTIFICATION) { - getActivity().startActivity(new Intent(Settings.ACTION_APP_NOTIFICATION_SETTINGS) + activity.startActivity(new Intent(Settings.ACTION_APP_NOTIFICATION_SETTINGS) .addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP) .putExtra(Settings.EXTRA_APP_PACKAGE, mCurrentPkgName) .putExtra(Settings.EXTRA_APP_UID, mCurrentUid)); + } else if (mListType == LIST_TYPE_DOMAINS_URLS) { + final String title = getString(R.string.auto_launch_label); + startAppInfoFragment(AppLaunchSettings.class, title); } else { // TODO: Figure out if there is a way where we can spin up the profile's settings // process ahead of time, to avoid a long load of data when user clicks on a managed app. // Maybe when they load the list of apps that contains managed profile apps. Intent intent = new Intent(Settings.ACTION_APPLICATION_DETAILS_SETTINGS); intent.setData(Uri.fromParts("package", mCurrentPkgName, null)); - getActivity().startActivityAsUser(intent, - new UserHandle(UserHandle.getUserId(mCurrentUid))); + activity.startActivityAsUser(intent, new UserHandle(UserHandle.getUserId(mCurrentUid))); } } + private void startAppInfoFragment(Class<? extends AppInfoBase> fragment, CharSequence title) { + Bundle args = new Bundle(); + args.putString("package", mCurrentPkgName); + + SettingsActivity sa = (SettingsActivity) getActivity(); + sa.startPreferencePanel(fragment.getName(), args, -1, title, this, 0); + } + @Override public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) { + if (mListType == LIST_TYPE_DOMAINS_URLS) { + // No option menu + return; + } mOptionsMenu = menu; if (mListType == LIST_TYPE_MAIN) { // Only show advanced options when in the main app list (from dashboard). @@ -426,7 +457,6 @@ public class ManageApplications extends InstrumentedFragment if (mOptionsMenu == null) { return; } - if (mListType != LIST_TYPE_MAIN) { // Allow sorting except on main apps list. mOptionsMenu.findItem(SORT_ORDER_ALPHA).setVisible(mSortOrder != SORT_ORDER_ALPHA); @@ -580,6 +610,7 @@ public class ManageApplications extends InstrumentedFragment private int mLastSortMode=-1; private int mWhichSize = SIZE_TOTAL; CharSequence mCurFilterPrefix; + private PackageManager mPm; private Filter mFilter = new Filter() { @Override @@ -607,6 +638,7 @@ public class ManageApplications extends InstrumentedFragment mSession = state.newSession(this); mManageApplications = manageApplications; mContext = manageApplications.getActivity(); + mPm = mContext.getPackageManager(); mFilterMode = filterMode; if (mManageApplications.mListType == LIST_TYPE_NOTIFICATION) { mNotifBridge = new AppStateNotificationBridge( @@ -842,6 +874,24 @@ public class ManageApplications extends InstrumentedFragment return mEntries.get(position).id; } + @Override + public boolean areAllItemsEnabled() { + return false; + } + + @Override + public boolean isEnabled(int position) { + ApplicationsState.AppEntry entry = mEntries.get(position); + synchronized (entry) { + if ((entry.info.flags&ApplicationInfo.FLAG_INSTALLED) == 0) { + return false; + } else if (!entry.info.enabled) { + return false; + } + return true; + } + } + public View getView(int position, View convertView, ViewGroup parent) { // A ViewHolder keeps references to children views to avoid unnecessary calls // to findViewById() on each row. @@ -860,15 +910,23 @@ public class ManageApplications extends InstrumentedFragment if (entry.icon != null) { holder.appIcon.setImageDrawable(entry.icon); } - if (mManageApplications.mListType == LIST_TYPE_NOTIFICATION) { - if (entry.extraInfo != null) { - holder.summary.setText(InstalledAppDetails.getNotificationSummary( - (AppRow) entry.extraInfo, mContext)); - } else { - holder.summary.setText(""); - } - } else { - holder.updateSizeText(mManageApplications.mInvalidSizeStr, mWhichSize); + switch (mManageApplications.mListType) { + case LIST_TYPE_NOTIFICATION: + if (entry.extraInfo != null) { + holder.summary.setText(InstalledAppDetails.getNotificationSummary( + (AppRow) entry.extraInfo, mContext)); + } else { + holder.summary.setText(""); + } + break; + + case LIST_TYPE_DOMAINS_URLS: + holder.summary.setText(getDomainsSummary(entry.info.packageName)); + break; + + default: + holder.updateSizeText(mManageApplications.mInvalidSizeStr, mWhichSize); + break; } if ((entry.info.flags&ApplicationInfo.FLAG_INSTALLED) == 0) { holder.disabled.setVisibility(View.VISIBLE); @@ -895,5 +953,23 @@ public class ManageApplications extends InstrumentedFragment public void onMovedToScrapHeap(View view) { mActive.remove(view); } + + private CharSequence getDomainsSummary(String packageName) { + ArraySet<String> result = new ArraySet<>(); + List<IntentFilterVerificationInfo> list = + mPm.getIntentFilterVerifications(packageName); + for (IntentFilterVerificationInfo ivi : list) { + for (String host : ivi.getDomains()) { + result.add(host); + } + } + if (result.size() == 0) { + return mContext.getString(R.string.domain_urls_summary_none); + } else if (result.size() == 1) { + return mContext.getString(R.string.domain_urls_summary_one, result.valueAt(0)); + } else { + return mContext.getString(R.string.domain_urls_summary_some, result.valueAt(0)); + } + } } } |