ManageDomainUrls.java revision 26e5760033c5c3d4f64a0cb34e436fdd95bf7e68
1/* 2 * Copyright (C) 2016 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file 5 * except in compliance with the License. You may obtain a copy of the License at 6 * 7 * http://www.apache.org/licenses/LICENSE-2.0 8 * 9 * Unless required by applicable law or agreed to in writing, software distributed under the 10 * License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 11 * KIND, either express or implied. See the License for the specific language governing 12 * permissions and limitations under the License. 13 */ 14 15package com.android.settings.applications; 16 17import android.app.Application; 18import android.content.Context; 19import android.content.pm.PackageManager; 20import android.os.Bundle; 21import android.os.UserHandle; 22import android.provider.Settings; 23import android.provider.Settings.Global; 24import android.support.v14.preference.SwitchPreference; 25import android.support.v7.preference.Preference; 26import android.support.v7.preference.Preference.OnPreferenceChangeListener; 27import android.support.v7.preference.Preference.OnPreferenceClickListener; 28import android.support.v7.preference.PreferenceCategory; 29import android.support.v7.preference.PreferenceGroup; 30import android.support.v7.preference.PreferenceViewHolder; 31import android.util.ArraySet; 32import android.view.View; 33 34import com.android.internal.logging.MetricsProto.MetricsEvent; 35import com.android.settings.R; 36import com.android.settings.SettingsPreferenceFragment; 37import com.android.settings.Utils; 38import com.android.settingslib.applications.ApplicationsState; 39import com.android.settingslib.applications.ApplicationsState.AppEntry; 40 41import java.util.ArrayList; 42 43/** 44 * Activity to manage how Android handles URL resolution. Includes both per-app 45 * handling as well as system handling for Web Actions. 46 */ 47public class ManageDomainUrls extends SettingsPreferenceFragment 48 implements ApplicationsState.Callbacks, OnPreferenceChangeListener, 49 OnPreferenceClickListener { 50 51 // constant value that can be used to check return code from sub activity. 52 private static final int INSTALLED_APP_DETAILS = 1; 53 54 private ApplicationsState mApplicationsState; 55 private ApplicationsState.Session mSession; 56 private PreferenceGroup mDomainAppList; 57 private SwitchPreference mWebAction; 58 59 @Override 60 public void onCreate(Bundle icicle) { 61 super.onCreate(icicle); 62 setAnimationAllowed(true); 63 setPreferenceScreen(getPreferenceManager().createPreferenceScreen(getContext())); 64 mApplicationsState = ApplicationsState.getInstance( 65 (Application) getContext().getApplicationContext()); 66 mSession = mApplicationsState.newSession(this); 67 setHasOptionsMenu(true); 68 } 69 70 @Override 71 public void onViewCreated(View view, Bundle savedInstanceState) { 72 super.onViewCreated(view, savedInstanceState); 73 } 74 75 @Override 76 public void onResume() { 77 super.onResume(); 78 mSession.resume(); 79 } 80 81 @Override 82 public void onPause() { 83 super.onPause(); 84 mSession.pause(); 85 } 86 87 @Override 88 public void onDestroy() { 89 super.onDestroy(); 90 mSession.release(); 91 } 92 93 @Override 94 public void onRunningStateChanged(boolean running) { 95 } 96 97 @Override 98 public void onPackageListChanged() { 99 } 100 101 @Override 102 public void onRebuildComplete(ArrayList<AppEntry> apps) { 103 if (getContext() == null) { 104 return; 105 } 106 107 final boolean disableWebActions = Global.getInt(getContext().getContentResolver(), 108 Global.ENABLE_EPHEMERAL_FEATURE, 1) == 0; 109 if (disableWebActions) { 110 mDomainAppList = getPreferenceScreen(); 111 } else { 112 final PreferenceGroup preferenceScreen = getPreferenceScreen(); 113 if (preferenceScreen.getPreferenceCount() == 0) { 114 // add preferences 115 final PreferenceCategory webActionCategory = 116 new PreferenceCategory(getPrefContext()); 117 webActionCategory.setTitle(R.string.web_action_section_title); 118 preferenceScreen.addPreference(webActionCategory); 119 120 // toggle to enable / disable Web Actions [aka Instant Apps] 121 mWebAction = new SwitchPreference(getPrefContext()); 122 mWebAction.setTitle(R.string.web_action_enable_title); 123 mWebAction.setSummary(R.string.web_action_enable_summary); 124 mWebAction.setChecked(Settings.Secure.getInt(getContentResolver(), 125 Settings.Secure.WEB_ACTION_ENABLED, 1) != 0); 126 mWebAction.setOnPreferenceChangeListener(this); 127 webActionCategory.addPreference(mWebAction); 128 129 // list to manage link handling per app 130 mDomainAppList = new PreferenceCategory(getPrefContext()); 131 mDomainAppList.setTitle(R.string.domain_url_section_title); 132 preferenceScreen.addPreference(mDomainAppList); 133 } 134 } 135 rebuildAppList(mDomainAppList, apps); 136 } 137 138 @Override 139 public boolean onPreferenceChange(Preference preference, Object newValue) { 140 if (preference == mWebAction) { 141 final int enabled = (boolean) newValue ? 1 : 0; 142 Settings.Secure.putInt( 143 getContentResolver(), Settings.Secure.WEB_ACTION_ENABLED, enabled); 144 return true; 145 } 146 return false; 147 } 148 149 private void rebuild() { 150 final ArrayList<AppEntry> apps = mSession.rebuild( 151 ApplicationsState.FILTER_WITH_DOMAIN_URLS, ApplicationsState.ALPHA_COMPARATOR); 152 if (apps != null) { 153 onRebuildComplete(apps); 154 } 155 } 156 157 private void rebuildAppList(PreferenceGroup group, ArrayList<AppEntry> apps) { 158 cacheRemoveAllPrefs(group); 159 final int N = apps.size(); 160 for (int i = 0; i < N; i++) { 161 AppEntry entry = apps.get(i); 162 String key = entry.info.packageName + "|" + entry.info.uid; 163 DomainAppPreference preference = (DomainAppPreference) getCachedPreference(key); 164 if (preference == null) { 165 preference = new DomainAppPreference(getPrefContext(), entry); 166 preference.setKey(key); 167 preference.setOnPreferenceClickListener(this); 168 group.addPreference(preference); 169 } else { 170 preference.reuse(); 171 } 172 preference.setOrder(i); 173 } 174 removeCachedPrefs(group); 175 } 176 177 @Override 178 public void onPackageIconChanged() { 179 } 180 181 @Override 182 public void onPackageSizeChanged(String packageName) { 183 } 184 185 @Override 186 public void onAllSizesComputed() { 187 } 188 189 @Override 190 public void onLauncherInfoChanged() { 191 } 192 193 @Override 194 public void onLoadEntriesCompleted() { 195 rebuild(); 196 } 197 198 @Override 199 protected int getMetricsCategory() { 200 return MetricsEvent.MANAGE_DOMAIN_URLS; 201 } 202 203 @Override 204 public boolean onPreferenceClick(Preference preference) { 205 if (preference.getClass() == DomainAppPreference.class) { 206 ApplicationsState.AppEntry entry = ((DomainAppPreference) preference).mEntry; 207 AppInfoBase.startAppInfoFragment(AppLaunchSettings.class, R.string.auto_launch_label, 208 entry.info.packageName, entry.info.uid, this, 209 INSTALLED_APP_DETAILS); 210 return true; 211 } 212 return false; 213 } 214 215 private class DomainAppPreference extends Preference { 216 private final AppEntry mEntry; 217 private final PackageManager mPm; 218 219 public DomainAppPreference(final Context context, AppEntry entry) { 220 super(context); 221 mPm = context.getPackageManager(); 222 mEntry = entry; 223 mEntry.ensureLabel(getContext()); 224 setState(); 225 if (mEntry.icon != null) { 226 setIcon(mEntry.icon); 227 } 228 } 229 230 private void setState() { 231 setTitle(mEntry.label); 232 setSummary(getDomainsSummary(mEntry.info.packageName)); 233 } 234 235 public void reuse() { 236 setState(); 237 notifyChanged(); 238 } 239 240 @Override 241 public void onBindViewHolder(PreferenceViewHolder holder) { 242 if (mEntry.icon == null) { 243 holder.itemView.post(new Runnable() { 244 @Override 245 public void run() { 246 // Ensure we have an icon before binding. 247 mApplicationsState.ensureIcon(mEntry); 248 // This might trigger us to bind again, but it gives an easy way to only 249 // load the icon once its needed, so its probably worth it. 250 setIcon(mEntry.icon); 251 } 252 }); 253 } 254 super.onBindViewHolder(holder); 255 } 256 257 private CharSequence getDomainsSummary(String packageName) { 258 // If the user has explicitly said "no" for this package, that's the 259 // string we should show. 260 int domainStatus = 261 mPm.getIntentVerificationStatusAsUser(packageName, UserHandle.myUserId()); 262 if (domainStatus == PackageManager.INTENT_FILTER_DOMAIN_VERIFICATION_STATUS_NEVER) { 263 return getContext().getString(R.string.domain_urls_summary_none); 264 } 265 // Otherwise, ask package manager for the domains for this package, 266 // and show the first one (or none if there aren't any). 267 ArraySet<String> result = Utils.getHandledDomains(mPm, packageName); 268 if (result.size() == 0) { 269 return getContext().getString(R.string.domain_urls_summary_none); 270 } else if (result.size() == 1) { 271 return getContext().getString(R.string.domain_urls_summary_one, result.valueAt(0)); 272 } else { 273 return getContext().getString(R.string.domain_urls_summary_some, result.valueAt(0)); 274 } 275 } 276 } 277} 278