Settings - add support for Launch by Default

- implement UX spec

Change-Id: I7ee8962f83983273d809e0ef6fc81b0eb2df15dd
This commit is contained in:
Fabrice Di Meglio
2015-01-23 19:03:22 -08:00
parent 43a0cbad1b
commit 8b2ea39cbc
19 changed files with 763 additions and 215 deletions

View File

@@ -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>

View File

@@ -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"
/>

View File

@@ -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,19 +30,6 @@
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
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"
@@ -51,33 +37,13 @@
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">
<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_marginStart="-4dip"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_weight="0.4"
android:text="@string/clear_activities" />
</LinearLayout>
</RelativeLayout>
</LinearLayout>
</ScrollView>

View File

@@ -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>

View File

@@ -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>

View File

@@ -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>

View File

@@ -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>

View File

@@ -25,6 +25,15 @@
android:title="@string/app_permissions"
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"

View File

@@ -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>

View File

@@ -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 */ }

View File

@@ -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);
}
}

View File

@@ -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()));
}

View File

@@ -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);
}
}
}

View File

@@ -17,175 +17,104 @@
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());
addPreferencesFromResource(R.xml.installed_app_launch_settings);
mPm = getActivity().getPackageManager();
final int myUserId = UserHandle.myUserId();
mOpenDomainUrls = (SwitchPreference) findPreference(KEY_OPEN_DOMAIN_URLS);
mOpenDomainUrls.setOnPreferenceChangeListener(this);
final int status = mPm.getIntentVerificationStatus(mPackageName, myUserId);
boolean checked = status == PackageManager.INTENT_FILTER_DOMAIN_VERIFICATION_STATUS_ALWAYS;
mOpenDomainUrls.setChecked(checked);
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
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
final View view = inflater.inflate(R.layout.app_preferred_settings, container, false);
private CharSequence[] getEntries(String packageName) {
ArraySet<String> result = new ArraySet<>();
final ViewGroup allDetails = (ViewGroup) view.findViewById(R.id.all_details);
Utils.forceCustomPadding(allDetails, true /* additive padding */);
List<IntentFilterVerificationInfo> list =
mPm.getIntentFilterVerifications(packageName);
for (IntentFilterVerificationInfo ivi : list) {
for (String host : ivi.getDomains()) {
result.add(host);
}
}
mActivitiesButton = (Button) view.findViewById(R.id.clear_activities_button);
mRootView = view;
return view;
return result.toArray(new CharSequence[0]);
}
@Override
protected boolean refreshUi() {
retrieveAppEntry();
boolean hasBindAppWidgetPermission =
mAppWidgetManager.hasBindAppWidgetPermission(mAppEntry.info.packageName);
mClearDefaultsPreference.setPackageName(mPackageName);
mClearDefaultsPreference.setAppEntry(mAppEntry);
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);
}
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");
}
autoLaunchView.setText(text);
mActivitiesButton.setEnabled(true);
mActivitiesButton.setOnClickListener(this);
}
return true;
}
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 AlertDialog createDialog(int id, int errorCode) {
// No dialogs for preferred launch settings.
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);
}
}
// Nothing to do
}
private static boolean hasUsbDefaults(IUsbManager usbManager, String packageName) {
try {
if (usbManager != null) {
return usbManager.hasDefaults(packageName, UserHandle.myUserId());
@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());
}
} catch (RemoteException e) {
Log.e(TAG, "mUsbManager.hasDefaults", e);
}
return false;
}
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");
}
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

View File

@@ -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;

View File

@@ -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;

View File

@@ -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);
}
}

View File

@@ -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));

View File

@@ -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) {
switch (mManageApplications.mListType) {
case LIST_TYPE_NOTIFICATION:
if (entry.extraInfo != null) {
holder.summary.setText(InstalledAppDetails.getNotificationSummary(
(AppRow) entry.extraInfo, mContext));
} else {
holder.summary.setText("");
}
} else {
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));
}
}
}
}