Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 1721e451 authored by TreeHugger Robot's avatar TreeHugger Robot Committed by Android (Google) Code Review
Browse files

Merge "Implement Web Action settings" into nyc-mr1-dev

parents adfcb155 d5824967
Loading
Loading
Loading
Loading
+11 −0
Original line number Diff line number Diff line
@@ -7771,5 +7771,16 @@
    <string name="automatic_storage_manager_freed_bytes"><xliff:g id="size" example="3.25MB">%1$s</xliff:g> total made available\n\nLast ran on <xliff:g id="date" example="Jan 12">%2$s</xliff:g></string>
    <!-- Title text for enabling web actions. [CHAR_LIMIT=60] -->
    <string name="web_action_enable_title">Open links in apps</string>
    <!-- Summary text for enabling web actions. [CHAR_LIMIT=250] -->
    <string name="web_action_enable_summary">Open links in supported apps, even if the
      apps aren’t installed on your device</string>
    <!-- Section title for the Web Action preference [CHAR LIMIT=60] -->
    <string name="web_action_section_title">Apps not installed</string>
    <!-- Section title for the Domain URL app preference list [CHAR LIMIT=60]-->
    <string name="domain_url_section_title">Installed apps</string>
</resources>
+1 −4
Original line number Diff line number Diff line
@@ -30,10 +30,7 @@
        <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" />
            android:fragment="com.android.settings.applications.ManageDomainUrls">
        </PreferenceScreen>

        <Preference
+1 −1
Original line number Diff line number Diff line
@@ -119,7 +119,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 ManageDomainUrls extends SettingsActivity { /* empty */ }

    public static class TopLevelSettings extends SettingsActivity { /* empty */ }
    public static class ApnSettingsActivity extends SettingsActivity { /* empty */ }
+2 −40
Original line number Diff line number Diff line
@@ -57,7 +57,6 @@ import com.android.settings.AppHeader;
import com.android.settings.InstrumentedFragment;
import com.android.settings.R;
import com.android.settings.Settings.AllApplicationsActivity;
import com.android.settings.Settings.DomainsURLsAppListActivity;
import com.android.settings.Settings.HighPowerApplicationsActivity;
import com.android.settings.Settings.NotificationAppListActivity;
import com.android.settings.Settings.OverlaySettingsActivity;
@@ -136,7 +135,6 @@ public class ManageApplications extends InstrumentedFragment
    public static final int FILTER_APPS_PRIORITY = 9;
    public static final int FILTER_APPS_PERSONAL = 10;
    public static final int FILTER_APPS_WORK = 11;
    public static final int FILTER_APPS_WITH_DOMAIN_URLS = 12;
    public static final int FILTER_APPS_USAGE_ACCESS = 13;
    public static final int FILTER_APPS_WITH_OVERLAY = 14;
    public static final int FILTER_APPS_WRITE_SETTINGS = 15;
@@ -217,7 +215,6 @@ public class ManageApplications extends InstrumentedFragment

    public static final int LIST_TYPE_MAIN = 0;
    public static final int LIST_TYPE_NOTIFICATION = 1;
    public static final int LIST_TYPE_DOMAINS_URLS = 2;
    public static final int LIST_TYPE_STORAGE = 3;
    public static final int LIST_TYPE_USAGE_ACCESS = 4;
    public static final int LIST_TYPE_HIGH_POWER = 5;
@@ -251,8 +248,6 @@ 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 if (className.equals(StorageUseActivity.class.getName())) {
            if (args != null && args.containsKey(EXTRA_VOLUME_UUID)) {
                mVolumeUuid = args.getString(EXTRA_VOLUME_UUID);
@@ -382,8 +377,6 @@ public class ManageApplications extends InstrumentedFragment

    private int getDefaultFilter() {
        switch (mListType) {
            case LIST_TYPE_DOMAINS_URLS:
                return FILTER_APPS_WITH_DOMAIN_URLS;
            case LIST_TYPE_USAGE_ACCESS:
                return FILTER_APPS_USAGE_ACCESS;
            case LIST_TYPE_HIGH_POWER:
@@ -415,8 +408,6 @@ public class ManageApplications extends InstrumentedFragment
                return MetricsEvent.MANAGE_APPLICATIONS;
            case LIST_TYPE_NOTIFICATION:
                return MetricsEvent.MANAGE_APPLICATIONS_NOTIFICATIONS;
            case LIST_TYPE_DOMAINS_URLS:
                return MetricsEvent.MANAGE_DOMAIN_URLS;
            case LIST_TYPE_STORAGE:
                return MetricsEvent.APPLICATIONS_STORAGE_APPS;
            case LIST_TYPE_USAGE_ACCESS:
@@ -502,9 +493,6 @@ public class ManageApplications extends InstrumentedFragment
                startAppInfoFragment(AppNotificationSettings.class,
                        R.string.app_notifications_title);
                break;
            case LIST_TYPE_DOMAINS_URLS:
                startAppInfoFragment(AppLaunchSettings.class, R.string.auto_launch_label);
                break;
            case LIST_TYPE_USAGE_ACCESS:
                startAppInfoFragment(UsageAccessDetails.class, R.string.usage_access);
                break;
@@ -537,9 +525,6 @@ public class ManageApplications extends InstrumentedFragment

    @Override
    public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
        if (mListType == LIST_TYPE_DOMAINS_URLS) {
            return;
        }
        HelpUtils.prepareHelpMenuItem(getActivity(), menu, mListType == LIST_TYPE_MAIN
                ? R.string.help_uri_apps : R.string.help_uri_notifications, getClass().getName());
        mOptionsMenu = menu;
@@ -760,7 +745,7 @@ public class ManageApplications extends InstrumentedFragment
        private boolean mHasReceivedLoadEntries;
        private boolean mHasReceivedBridgeCallback;

        private AlphabeticIndex.ImmutableIndex mIndex;
        private AlphabeticIndex.ImmutableIndex<Locale> mIndex;
        private SectionInfo[] mSections = EMPTY_SECTIONS;
        private int[] mPositionToSectionIndex;

@@ -984,7 +969,7 @@ public class ManageApplications extends InstrumentedFragment
                    if (locales.size() == 0) {
                        locales = new LocaleList(Locale.ENGLISH);
                    }
                    AlphabeticIndex index = new AlphabeticIndex<>(locales.get(0));
                    AlphabeticIndex<Locale> index = new AlphabeticIndex<>(locales.get(0));
                    int localeCount = locales.size();
                    for (int i = 1; i < localeCount; i++) {
                        index.addLabels(locales.get(i));
@@ -1181,10 +1166,6 @@ public class ManageApplications extends InstrumentedFragment
                    }
                    break;

                case LIST_TYPE_DOMAINS_URLS:
                    holder.summary.setText(getDomainsSummary(holder.entry.info.packageName));
                    break;

                case LIST_TYPE_USAGE_ACCESS:
                    if (holder.entry.extraInfo != null) {
                        holder.summary.setText((new UsageState((PermissionState) holder.entry
@@ -1224,25 +1205,6 @@ public class ManageApplications extends InstrumentedFragment
            mActive.remove(view);
        }

        private CharSequence getDomainsSummary(String packageName) {
            // If the user has explicitly said "no" for this package, that's the
            // string we should show.
            int domainStatus = mPm.getIntentVerificationStatusAsUser(packageName, UserHandle.myUserId());
            if (domainStatus == PackageManager.INTENT_FILTER_DOMAIN_VERIFICATION_STATUS_NEVER) {
                return mContext.getString(R.string.domain_urls_summary_none);
            }
            // Otherwise, ask package manager for the domains for this package,
            // and show the first one (or none if there aren't any).
            ArraySet<String> result = Utils.getHandledDomains(mPm, packageName);
            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));
            }
        }

        @Override
        public Object[] getSections() {
            return mSections;
+273 −0
Original line number Diff line number Diff line
/*
 * Copyright (C) 2016 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file
 * except in compliance with the License. You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software distributed under the
 * License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 * KIND, either express or implied. See the License for the specific language governing
 * permissions and limitations under the License.
 */

package com.android.settings.applications;

import android.app.Application;
import android.content.Context;
import android.content.DialogInterface;
import android.content.pm.PackageManager;
import android.os.Build;
import android.os.Bundle;
import android.os.UserHandle;
import android.provider.Settings;
import android.support.v14.preference.SwitchPreference;
import android.support.v7.preference.Preference;
import android.support.v7.preference.Preference.OnPreferenceChangeListener;
import android.support.v7.preference.PreferenceCategory;
import android.support.v7.preference.PreferenceGroup;
import android.support.v7.preference.PreferenceViewHolder;
import android.util.ArraySet;
import android.view.Menu;
import android.view.MenuInflater;
import android.view.MenuItem;
import android.view.View;

import com.android.internal.logging.MetricsProto.MetricsEvent;
import com.android.settings.AppHeader;
import com.android.settings.R;
import com.android.settings.SettingsActivity;
import com.android.settings.SettingsPreferenceFragment;
import com.android.settings.Utils;
import com.android.settings.applications.AppInfoBase;
import com.android.settings.applications.AppStateBaseBridge;
import com.android.settings.applications.InstalledAppDetails;
import com.android.settings.datausage.AppStateDataUsageBridge.DataUsageState;
import com.android.settingslib.applications.ApplicationsState;
import com.android.settingslib.applications.ApplicationsState.AppEntry;
import com.android.settingslib.applications.ApplicationsState.AppFilter;

import java.util.ArrayList;

/**
 * Activity to manage how Android handles URL resolution. Includes both per-app
 * handling as well as system handling for Web Actions.
 */
public class ManageDomainUrls extends SettingsPreferenceFragment
        implements ApplicationsState.Callbacks, OnPreferenceChangeListener {

    // STOPSHIP; b/30256615
    private static final boolean DISABLE_WEB_ACTIONS = !Build.IS_DEBUGGABLE;

    private ApplicationsState mApplicationsState;
    private ApplicationsState.Session mSession;
    private PreferenceGroup mDomainAppList;
    private SwitchPreference mWebAction;

    @Override
    public void onCreate(Bundle icicle) {
        super.onCreate(icicle);
        setAnimationAllowed(true);
        setPreferenceScreen(getPreferenceManager().createPreferenceScreen(getContext()));
        mApplicationsState = ApplicationsState.getInstance(
                (Application) getContext().getApplicationContext());
        mSession = mApplicationsState.newSession(this);
        setHasOptionsMenu(true);
    }

    @Override
    public void onViewCreated(View view, Bundle savedInstanceState) {
        super.onViewCreated(view, savedInstanceState);
        setLoading(true, false);
    }

    @Override
    public void onResume() {
        super.onResume();
        mSession.resume();
    }

    @Override
    public void onPause() {
        super.onPause();
        mSession.pause();
    }

    @Override
    public void onDestroy() {
        super.onDestroy();
        mSession.release();
    }

    @Override
    public void onRunningStateChanged(boolean running) {
    }

    @Override
    public void onPackageListChanged() {
    }

    @Override
    public void onRebuildComplete(ArrayList<AppEntry> apps) {
        if (getContext() == null) {
            return;
        }

        if (DISABLE_WEB_ACTIONS) {
            mDomainAppList = getPreferenceScreen();
        } else {
            final PreferenceGroup preferenceScreen = getPreferenceScreen();
            if (preferenceScreen.getPreferenceCount() == 0) {
                // add preferences
                final PreferenceCategory webActionCategory =
                        new PreferenceCategory(getPrefContext());
                webActionCategory.setTitle(R.string.web_action_section_title);
                preferenceScreen.addPreference(webActionCategory);

                // toggle to enable / disable Web Actions [aka Instant Apps]
                mWebAction = new SwitchPreference(getPrefContext());
                mWebAction.setTitle(R.string.web_action_enable_title);
                mWebAction.setSummary(R.string.web_action_enable_summary);
                mWebAction.setChecked(Settings.Secure.getInt(getContentResolver(),
                        Settings.Secure.WEB_ACTION_ENABLED, 1) != 0);
                mWebAction.setOnPreferenceChangeListener(this);
                webActionCategory.addPreference(mWebAction);

                // list to manage link handling per app
                mDomainAppList = new PreferenceCategory(getPrefContext());
                mDomainAppList.setTitle(R.string.domain_url_section_title);
                preferenceScreen.addPreference(mDomainAppList);
            }
        }
        rebuildAppList(mDomainAppList, apps);
        setLoading(false, true);
    }

    @Override
    public boolean onPreferenceChange(Preference preference, Object newValue) {
        if (preference == mWebAction) {
            final int enabled = (boolean) newValue ? 1 : 0;
            Settings.Secure.putInt(
                    getContentResolver(), Settings.Secure.WEB_ACTION_ENABLED, enabled);
            return true;
        }
        return false;
    }

    private void rebuild() {
        final ArrayList<AppEntry> apps = mSession.rebuild(
                ApplicationsState.FILTER_WITH_DOMAIN_URLS, ApplicationsState.ALPHA_COMPARATOR);
        if (apps != null) {
            onRebuildComplete(apps);
        }
    }

    private void rebuildAppList(PreferenceGroup group, ArrayList<AppEntry> apps) {
        cacheRemoveAllPrefs(group);
        final int N = apps.size();
        for (int i = 0; i < N; i++) {
            AppEntry entry = apps.get(i);
            String key = entry.info.packageName + "|" + entry.info.uid;
            DomainAppPreference preference = (DomainAppPreference) getCachedPreference(key);
            if (preference == null) {
                preference = new DomainAppPreference(getPrefContext(), entry);
                preference.setKey(key);
                group.addPreference(preference);
            } else {
                preference.reuse();
            }
            preference.setOrder(i);
        }
        removeCachedPrefs(group);
    }

    @Override
    public void onPackageIconChanged() {
    }

    @Override
    public void onPackageSizeChanged(String packageName) {
    }

    @Override
    public void onAllSizesComputed() {
    }

    @Override
    public void onLauncherInfoChanged() {
    }

    @Override
    public void onLoadEntriesCompleted() {
        rebuild();
    }

    @Override
    protected int getMetricsCategory() {
        return MetricsEvent.MANAGE_DOMAIN_URLS;
    }

    private class DomainAppPreference extends Preference {
        private final AppEntry mEntry;
        private final PackageManager mPm;

        public DomainAppPreference(final Context context, AppEntry entry) {
            super(context);
            mPm = context.getPackageManager();
            mEntry = entry;
            mEntry.ensureLabel(getContext());
            setState();
            if (mEntry.icon != null) {
                setIcon(mEntry.icon);
            }
        }

        private void setState() {
            setTitle(mEntry.label);
            setSummary(getDomainsSummary(mEntry.info.packageName));
        }

        public void reuse() {
            setState();
            notifyChanged();
        }

        @Override
        public void onBindViewHolder(PreferenceViewHolder holder) {
            if (mEntry.icon == null) {
                holder.itemView.post(new Runnable() {
                    @Override
                    public void run() {
                        // Ensure we have an icon before binding.
                        mApplicationsState.ensureIcon(mEntry);
                        // This might trigger us to bind again, but it gives an easy way to only
                        // load the icon once its needed, so its probably worth it.
                        setIcon(mEntry.icon);
                    }
                });
            }
            super.onBindViewHolder(holder);
        }

        private CharSequence getDomainsSummary(String packageName) {
            // If the user has explicitly said "no" for this package, that's the
            // string we should show.
            int domainStatus =
                    mPm.getIntentVerificationStatusAsUser(packageName, UserHandle.myUserId());
            if (domainStatus == PackageManager.INTENT_FILTER_DOMAIN_VERIFICATION_STATUS_NEVER) {
                return getContext().getString(R.string.domain_urls_summary_none);
            }
            // Otherwise, ask package manager for the domains for this package,
            // and show the first one (or none if there aren't any).
            ArraySet<String> result = Utils.getHandledDomains(mPm, packageName);
            if (result.size() == 0) {
                return getContext().getString(R.string.domain_urls_summary_none);
            } else if (result.size() == 1) {
                return getContext().getString(R.string.domain_urls_summary_one, result.valueAt(0));
            } else {
                return getContext().getString(R.string.domain_urls_summary_some, result.valueAt(0));
            }
        }
    }
}