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

Commit ec30c5ed authored by Sunny Goyal's avatar Sunny Goyal Committed by Android (Google) Code Review
Browse files

Merge "Adding utility class to load customization resources for easier...

Merge "Adding utility class to load customization resources for easier prototype" into ub-launcher3-master
parents 51a5bf15 7b97eebb
Loading
Loading
Loading
Loading
+0 −3
Original line number Diff line number Diff line
@@ -15,9 +15,6 @@
-->

<resources>
    <!-- Container -->
    <item name="container_margin" format="fraction" type="fraction">12%</item>

    <!-- Fast scroll -->
    <dimen name="fastscroll_popup_width">58dp</dimen>
    <dimen name="fastscroll_popup_height">48dp</dimen>
+3 −0
Original line number Diff line number Diff line
@@ -114,4 +114,7 @@

    <!-- Recents -->
    <item type="id" name="overview_panel"/>

    <!-- Configuration resources -->
    <array name="dynamic_resources"> </array>
</resources>
+9 −0
Original line number Diff line number Diff line
<?xml version="1.0" encoding="utf-8"?>
<DynamicResources>
    <entry id="@color/delete_target_hover_tint" />
    <entry id="@color/delete_target_hover_tint" />
    <entry id="@color/delete_target_hover_tint" />
    <entry id="@color/delete_target_hover_tint" />


</DynamicResources>
 No newline at end of file
+61 −51
Original line number Diff line number Diff line
@@ -15,6 +15,8 @@
 */
package com.android.launcher3.settings;

import static android.content.pm.PackageManager.MATCH_DISABLED_COMPONENTS;

import static com.android.launcher3.uioverrides.plugins.PluginManagerWrapper.PLUGIN_CHANGED;
import static com.android.launcher3.uioverrides.plugins.PluginManagerWrapper.pluginEnabledKey;

@@ -24,28 +26,21 @@ import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.content.pm.PackageInfo;
import android.content.pm.ApplicationInfo;
import android.content.pm.PackageManager;
import android.content.pm.ResolveInfo;
import android.content.pm.ServiceInfo;
import android.net.Uri;
import android.os.Build;
import android.os.Bundle;
import android.provider.Settings;
import android.util.ArrayMap;
import android.util.ArraySet;
import android.util.Pair;
import android.view.Menu;
import android.view.MenuInflater;
import android.view.MenuItem;
import android.view.View;

import com.android.launcher3.R;
import com.android.launcher3.config.FeatureFlags;
import com.android.launcher3.config.FlagTogglerPrefUi;
import com.android.launcher3.uioverrides.plugins.PluginManagerWrapper;

import java.util.List;
import java.util.Set;

import androidx.preference.Preference;
import androidx.preference.PreferenceCategory;
import androidx.preference.PreferenceDataStore;
@@ -54,6 +49,16 @@ import androidx.preference.PreferenceScreen;
import androidx.preference.PreferenceViewHolder;
import androidx.preference.SwitchPreference;

import com.android.launcher3.R;
import com.android.launcher3.config.FeatureFlags;
import com.android.launcher3.config.FlagTogglerPrefUi;
import com.android.launcher3.uioverrides.plugins.PluginManagerWrapper;

import java.util.ArrayList;
import java.util.List;
import java.util.Set;
import java.util.stream.Collectors;

/**
 * Dev-build only UI allowing developers to toggle flag settings and plugins.
 * See {@link FeatureFlags}.
@@ -154,44 +159,53 @@ public class DeveloperOptionsFragment extends PreferenceFragment {
        PackageManager pm = getContext().getPackageManager();

        Set<String> pluginActions = manager.getPluginActions();
        ArrayMap<String, ArraySet<String>> plugins = new ArrayMap<>();

        ArrayMap<Pair<String, String>, ArrayList<Pair<String, ServiceInfo>>> plugins =
                new ArrayMap<>();

        Set<String> pluginPermissionApps = pm.getPackagesHoldingPermissions(
                new String[]{PLUGIN_PERMISSION}, MATCH_DISABLED_COMPONENTS)
                .stream()
                .map(pi -> pi.packageName)
                .collect(Collectors.toSet());

        for (String action : pluginActions) {
            String name = toName(action);
            List<ResolveInfo> result = pm.queryIntentServices(
                    new Intent(action), PackageManager.MATCH_DISABLED_COMPONENTS);
                    new Intent(action), MATCH_DISABLED_COMPONENTS);
            for (ResolveInfo info : result) {
                String packageName = info.serviceInfo.packageName;
                if (!plugins.containsKey(packageName)) {
                    plugins.put(packageName, new ArraySet<>());
                if (!pluginPermissionApps.contains(packageName)) {
                    continue;
                }
                plugins.get(packageName).add(name);

                Pair<String, String> key = Pair.create(packageName, info.serviceInfo.processName);
                if (!plugins.containsKey(key)) {
                    plugins.put(key, new ArrayList<>());
                }
                plugins.get(key).add(Pair.create(name, info.serviceInfo));
            }

        List<PackageInfo> apps = pm.getPackagesHoldingPermissions(new String[]{PLUGIN_PERMISSION},
                PackageManager.MATCH_DISABLED_COMPONENTS | PackageManager.GET_SERVICES);
        PreferenceDataStore enabled = manager.getPluginEnabler();
        apps.forEach(app -> {
            if (!plugins.containsKey(app.packageName)) return;
            SwitchPreference pref = new PluginPreference(prefContext, app, enabled);
            pref.setSummary("Plugins: " + toString(plugins.get(app.packageName)));
            mPluginsCategory.addPreference(pref);
        });
        }

    private String toString(ArraySet<String> plugins) {
        StringBuilder b = new StringBuilder();
        for (String string : plugins) {
            if (b.length() != 0) {
                b.append(", ");
            }
            b.append(string);
        PreferenceDataStore enabler = manager.getPluginEnabler();
        plugins.forEach((key, si) -> {
            String packageName = key.first;
            List<ComponentName> componentNames = si.stream()
                    .map(p -> new ComponentName(packageName, p.second.name))
                    .collect(Collectors.toList());
            if (!componentNames.isEmpty()) {
                SwitchPreference pref = new PluginPreference(
                        prefContext, si.get(0).second.applicationInfo, enabler, componentNames);
                pref.setSummary("Plugins: "
                        + si.stream().map(p -> p.first).collect(Collectors.joining(", ")));
                mPluginsCategory.addPreference(pref);
            }
        return b.toString();
        });
    }

    private String toName(String action) {
        String str = action.replace("com.android.systemui.action.PLUGIN_", "");
        String str = action.replace("com.android.systemui.action.PLUGIN_", "")
                .replace("com.android.launcher3.action.PLUGIN_", "");
        StringBuilder b = new StringBuilder();
        for (String s : str.split("_")) {
            if (b.length() != 0) {
@@ -205,18 +219,20 @@ public class DeveloperOptionsFragment extends PreferenceFragment {

    private static class PluginPreference extends SwitchPreference {
        private final boolean mHasSettings;
        private final PackageInfo mInfo;
        private final PreferenceDataStore mPluginEnabler;
        private final String mPackageName;
        private final List<ComponentName> mComponentNames;

        public PluginPreference(Context prefContext, PackageInfo info,
                PreferenceDataStore pluginEnabler) {
        PluginPreference(Context prefContext, ApplicationInfo info,
                PreferenceDataStore pluginEnabler, List<ComponentName> componentNames) {
            super(prefContext);
            PackageManager pm = prefContext.getPackageManager();
            mHasSettings = pm.resolveActivity(new Intent(ACTION_PLUGIN_SETTINGS)
                    .setPackage(info.packageName), 0) != null;
            mInfo = info;
            mPackageName = info.packageName;
            mComponentNames = componentNames;
            mPluginEnabler = pluginEnabler;
            setTitle(info.applicationInfo.loadLabel(pm));
            setTitle(info.loadLabel(pm));
            setChecked(isPluginEnabled());
            setWidgetLayoutResource(R.layout.switch_preference_with_settings);
        }
@@ -227,9 +243,7 @@ public class DeveloperOptionsFragment extends PreferenceFragment {
        }

        private boolean isPluginEnabled() {
            for (int i = 0; i < mInfo.services.length; i++) {
                ComponentName componentName = new ComponentName(mInfo.packageName,
                        mInfo.services[i].name);
            for (ComponentName componentName : mComponentNames) {
                if (!isEnabled(componentName)) {
                    return false;
                }
@@ -240,17 +254,14 @@ public class DeveloperOptionsFragment extends PreferenceFragment {
        @Override
        protected boolean persistBoolean(boolean isEnabled) {
            boolean shouldSendBroadcast = false;
            for (int i = 0; i < mInfo.services.length; i++) {
                ComponentName componentName = new ComponentName(mInfo.packageName,
                        mInfo.services[i].name);

            for (ComponentName componentName : mComponentNames) {
                if (isEnabled(componentName) != isEnabled) {
                    mPluginEnabler.putBoolean(pluginEnabledKey(componentName), isEnabled);
                    shouldSendBroadcast = true;
                }
            }
            if (shouldSendBroadcast) {
                final String pkg = mInfo.packageName;
                final String pkg = mPackageName;
                final Intent intent = new Intent(PLUGIN_CHANGED,
                        pkg != null ? Uri.fromParts("package", pkg, null) : null);
                getContext().sendBroadcast(intent);
@@ -268,8 +279,7 @@ public class DeveloperOptionsFragment extends PreferenceFragment {
                    : View.GONE);
            holder.findViewById(R.id.settings).setOnClickListener(v -> {
                ResolveInfo result = v.getContext().getPackageManager().resolveActivity(
                        new Intent(ACTION_PLUGIN_SETTINGS).setPackage(
                                mInfo.packageName), 0);
                        new Intent(ACTION_PLUGIN_SETTINGS).setPackage(mPackageName), 0);
                if (result != null) {
                    v.getContext().startActivity(new Intent().setComponent(
                            new ComponentName(result.activityInfo.packageName,
@@ -278,7 +288,7 @@ public class DeveloperOptionsFragment extends PreferenceFragment {
            });
            holder.itemView.setOnLongClickListener(v -> {
                Intent intent = new Intent(Settings.ACTION_APPLICATION_DETAILS_SETTINGS);
                intent.setData(Uri.fromParts("package", mInfo.packageName, null));
                intent.setData(Uri.fromParts("package", mPackageName, null));
                getContext().startActivity(intent);
                return true;
            });
+89 −0
Original line number Diff line number Diff line
/*
 * Copyright (C) 2019 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.launcher3.util;

import android.content.Context;

import androidx.annotation.ColorRes;
import androidx.annotation.DimenRes;
import androidx.annotation.FractionRes;
import androidx.annotation.IntegerRes;

import com.android.launcher3.uioverrides.plugins.PluginManagerWrapper;
import com.android.systemui.plugins.PluginListener;
import com.android.systemui.plugins.ResourceProvider;

/**
 * Utility class to support customizing resource values using plugins
 *
 * To load resources, call
 *    DynamicResource.provider(context).getInt(resId) or any other supported methods
 *
 * To allow customization for a particular resource, add them to dynamic_resources.xml
 */
public class DynamicResource implements ResourceProvider, PluginListener<ResourceProvider> {

    private static final MainThreadInitializedObject<DynamicResource> INSTANCE =
            new MainThreadInitializedObject<>(DynamicResource::new);

    private final Context mContext;
    private ResourceProvider mPlugin;

    private DynamicResource(Context context) {
        mContext = context;
        PluginManagerWrapper.INSTANCE.get(context).addPluginListener(this,
                ResourceProvider.class, false /* allowedMultiple */);
    }

    @Override
    public int getInt(@IntegerRes int resId) {
        return mContext.getResources().getInteger(resId);
    }

    @Override
    public float getFraction(@FractionRes int resId) {
        return mContext.getResources().getFraction(resId, 1, 1);
    }

    @Override
    public float getDimension(@DimenRes int resId) {
        return mContext.getResources().getDimension(resId);
    }

    @Override
    public int getColor(@ColorRes int resId) {
        return mContext.getResources().getColor(resId, null);
    }

    @Override
    public void onPluginConnected(ResourceProvider plugin, Context context) {
        mPlugin = plugin;
    }

    @Override
    public void onPluginDisconnected(ResourceProvider plugin) {
        mPlugin = null;
    }

    /**
     * Returns the currently active or default provider
     */
    public static ResourceProvider provider(Context context) {
        DynamicResource dr = DynamicResource.INSTANCE.get(context);
        ResourceProvider plugin = dr.mPlugin;
        return plugin == null ? dr : plugin;
    }
}
Loading