mirror of
https://github.com/LawnchairLauncher/lawnchair.git
synced 2026-02-27 15:26:58 +00:00
Using resource overrides for PluginManager instead of code-swap
Bug: 330920490 Test: Presubmit Flag: None Change-Id: Ib1cd50f95873928b9ce104e8e95d21f1dca9c6e3
This commit is contained in:
@@ -34,6 +34,7 @@
|
||||
<string name="taskbar_model_callbacks_factory_class" translatable="false">com.android.launcher3.taskbar.TaskbarModelCallbacksFactory</string>
|
||||
<string name="taskbar_view_callbacks_factory_class" translatable="false">com.android.launcher3.taskbar.TaskbarViewCallbacksFactory</string>
|
||||
<string name="launcher_restore_event_logger_class" translatable="false">com.android.quickstep.LauncherRestoreEventLoggerImpl</string>
|
||||
<string name="plugin_manager_wrapper_class" translatable="false">com.android.launcher3.uioverrides.plugins.PluginManagerWrapperImpl</string>
|
||||
|
||||
<string name="nav_handle_long_press_handler_class" translatable="false"></string>
|
||||
<string name="assist_utils_class" translatable="false"></string>
|
||||
|
||||
@@ -16,8 +16,12 @@
|
||||
|
||||
package com.android.launcher3.uioverrides.flags
|
||||
|
||||
import android.content.Intent
|
||||
import android.content.pm.PackageManager
|
||||
import android.net.Uri
|
||||
import android.os.Handler
|
||||
import android.provider.DeviceConfig
|
||||
import android.provider.Settings.ACTION_APPLICATION_DETAILS_SETTINGS
|
||||
import android.text.Html
|
||||
import android.view.inputmethod.EditorInfo
|
||||
import androidx.preference.Preference
|
||||
@@ -26,9 +30,12 @@ import androidx.preference.PreferenceViewHolder
|
||||
import androidx.preference.SwitchPreference
|
||||
import com.android.launcher3.ExtendedEditText
|
||||
import com.android.launcher3.R
|
||||
import com.android.launcher3.uioverrides.plugins.PluginManagerWrapperImpl
|
||||
import com.android.launcher3.util.PluginManagerWrapper
|
||||
import com.android.quickstep.util.DeviceConfigHelper
|
||||
import com.android.quickstep.util.DeviceConfigHelper.Companion.NAMESPACE_LAUNCHER
|
||||
import com.android.quickstep.util.DeviceConfigHelper.DebugInfo
|
||||
import com.android.systemui.shared.plugins.PluginEnabler
|
||||
|
||||
/** Helper class to generate UI for Device Config */
|
||||
class DevOptionsUiHelper {
|
||||
@@ -142,7 +149,92 @@ class DevOptionsUiHelper {
|
||||
.getInt(this.key, DeviceConfig.getInt(NAMESPACE_LAUNCHER, this.key, this.valueInCode))
|
||||
.toString()
|
||||
|
||||
/**
|
||||
* Inflates the preferences for plugins
|
||||
*
|
||||
* A single pref is added for a plugin-group. A plugin-group is a collection of plugins in a
|
||||
* single apk which have the same android:process tags defined. The apk should also hold the
|
||||
* PLUGIN_PERMISSION. We collect all the plugin intents which Launcher listens for and fetch all
|
||||
* corresponding plugins on the device. When a plugin-group is enabled/disabled we also need to
|
||||
* notify the pluginManager manually since the broadcast-mechanism only works in sysui process
|
||||
*/
|
||||
fun inflatePluginPrefs(parent: PreferenceGroup) {
|
||||
val context = parent.context
|
||||
val manager = PluginManagerWrapper.INSTANCE[context] as PluginManagerWrapperImpl
|
||||
val pm = context.packageManager
|
||||
|
||||
val pluginPermissionApps =
|
||||
pm.getPackagesHoldingPermissions(
|
||||
arrayOf(PLUGIN_PERMISSION),
|
||||
PackageManager.MATCH_DISABLED_COMPONENTS
|
||||
)
|
||||
.map { it.packageName }
|
||||
|
||||
manager.pluginActions
|
||||
.flatMap { action ->
|
||||
pm.queryIntentServices(
|
||||
Intent(action),
|
||||
PackageManager.MATCH_DISABLED_COMPONENTS or
|
||||
PackageManager.GET_RESOLVED_FILTER
|
||||
)
|
||||
.filter { pluginPermissionApps.contains(it.serviceInfo.packageName) }
|
||||
}
|
||||
.groupBy { "${it.serviceInfo.packageName}-${it.serviceInfo.processName}" }
|
||||
.values
|
||||
.forEach { infoList ->
|
||||
val pluginInfo = infoList[0]!!
|
||||
val pluginUri = Uri.fromParts("package", pluginInfo.serviceInfo.packageName, null)
|
||||
|
||||
object : SwitchPreference(context) {
|
||||
override fun onBindViewHolder(holder: PreferenceViewHolder) {
|
||||
super.onBindViewHolder(holder)
|
||||
holder.itemView.setOnLongClickListener {
|
||||
context.startActivity(
|
||||
Intent(ACTION_APPLICATION_DETAILS_SETTINGS, pluginUri)
|
||||
)
|
||||
true
|
||||
}
|
||||
}
|
||||
}
|
||||
.apply {
|
||||
isPersistent = true
|
||||
title = pluginInfo.loadLabel(pm)
|
||||
isChecked =
|
||||
infoList.all {
|
||||
manager.pluginEnabler.isEnabled(it.serviceInfo.componentName)
|
||||
}
|
||||
summary =
|
||||
infoList
|
||||
.map { it.filter }
|
||||
.filter { it?.countActions() ?: 0 > 0 }
|
||||
.joinToString(prefix = "Plugins: ") {
|
||||
it.getAction(0)
|
||||
.replace("com.android.systemui.action.PLUGIN_", "")
|
||||
.replace("com.android.launcher3.action.PLUGIN_", "")
|
||||
}
|
||||
|
||||
setOnPreferenceChangeListener { _, newVal ->
|
||||
val disabledState =
|
||||
if (newVal as Boolean) PluginEnabler.ENABLED
|
||||
else PluginEnabler.DISABLED_MANUALLY
|
||||
infoList.forEach {
|
||||
manager.pluginEnabler.setDisabled(
|
||||
it.serviceInfo.componentName,
|
||||
disabledState
|
||||
)
|
||||
}
|
||||
manager.notifyChange(Intent(Intent.ACTION_PACKAGE_CHANGED, pluginUri))
|
||||
true
|
||||
}
|
||||
|
||||
parent.addPreference(this)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
companion object {
|
||||
const val TAG = "DeviceConfigUIHelper"
|
||||
|
||||
const val PLUGIN_PERMISSION = "com.android.systemui.permission.PLUGIN"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -15,13 +15,7 @@
|
||||
*/
|
||||
package com.android.launcher3.uioverrides.flags;
|
||||
|
||||
import static android.content.pm.PackageManager.GET_RESOLVED_FILTER;
|
||||
import static android.content.pm.PackageManager.MATCH_DISABLED_COMPONENTS;
|
||||
import static android.view.View.GONE;
|
||||
import static android.view.View.VISIBLE;
|
||||
|
||||
import static com.android.launcher3.settings.SettingsActivity.EXTRA_FRAGMENT_HIGHLIGHT_KEY;
|
||||
import static com.android.launcher3.uioverrides.plugins.PluginManagerWrapper.PLUGIN_CHANGED;
|
||||
import static com.android.launcher3.util.OnboardingPrefs.ALL_APPS_VISITED_COUNT;
|
||||
import static com.android.launcher3.util.OnboardingPrefs.HOME_BOUNCE_COUNT;
|
||||
import static com.android.launcher3.util.OnboardingPrefs.HOME_BOUNCE_SEEN;
|
||||
@@ -29,18 +23,11 @@ import static com.android.launcher3.util.OnboardingPrefs.HOTSEAT_DISCOVERY_TIP_C
|
||||
import static com.android.launcher3.util.OnboardingPrefs.HOTSEAT_LONGPRESS_TIP_SEEN;
|
||||
import static com.android.launcher3.util.OnboardingPrefs.TASKBAR_EDU_TOOLTIP_STEP;
|
||||
|
||||
import android.content.ComponentName;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.content.SharedPreferences;
|
||||
import android.content.pm.PackageManager;
|
||||
import android.content.pm.ResolveInfo;
|
||||
import android.net.Uri;
|
||||
import android.provider.Settings;
|
||||
import android.text.Editable;
|
||||
import android.text.TextWatcher;
|
||||
import android.util.ArrayMap;
|
||||
import android.util.Pair;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
@@ -52,20 +39,12 @@ import androidx.preference.PreferenceCategory;
|
||||
import androidx.preference.PreferenceFragmentCompat;
|
||||
import androidx.preference.PreferenceGroup;
|
||||
import androidx.preference.PreferenceScreen;
|
||||
import androidx.preference.PreferenceViewHolder;
|
||||
import androidx.preference.SwitchPreference;
|
||||
|
||||
import com.android.launcher3.LauncherPrefs;
|
||||
import com.android.launcher3.R;
|
||||
import com.android.launcher3.config.FeatureFlags;
|
||||
import com.android.launcher3.secondarydisplay.SecondaryDisplayLauncher;
|
||||
import com.android.launcher3.uioverrides.plugins.PluginManagerWrapper;
|
||||
import com.android.systemui.shared.plugins.PluginEnabler;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
import java.util.stream.Collectors;
|
||||
import com.android.systemui.shared.plugins.PluginPrefs;
|
||||
|
||||
/**
|
||||
* Dev-build only UI allowing developers to toggle flag settings and plugins.
|
||||
@@ -73,15 +52,9 @@ import java.util.stream.Collectors;
|
||||
*/
|
||||
public class DeveloperOptionsUI {
|
||||
|
||||
private static final String ACTION_PLUGIN_SETTINGS =
|
||||
"com.android.systemui.action.PLUGIN_SETTINGS";
|
||||
private static final String PLUGIN_PERMISSION = "com.android.systemui.permission.PLUGIN";
|
||||
|
||||
private final PreferenceFragmentCompat mFragment;
|
||||
private final PreferenceScreen mPreferenceScreen;
|
||||
|
||||
private PreferenceCategory mPluginsCategory;
|
||||
|
||||
public DeveloperOptionsUI(PreferenceFragmentCompat fragment, PreferenceCategory flags) {
|
||||
mFragment = fragment;
|
||||
mPreferenceScreen = fragment.getPreferenceScreen();
|
||||
@@ -97,8 +70,10 @@ public class DeveloperOptionsUI {
|
||||
|
||||
DevOptionsUiHelper uiHelper = new DevOptionsUiHelper();
|
||||
uiHelper.inflateServerFlags(newCategory("Server flags"));
|
||||
if (PluginPrefs.hasPlugins(getContext())) {
|
||||
uiHelper.inflatePluginPrefs(newCategory("Plugins"));
|
||||
}
|
||||
|
||||
loadPluginPrefs();
|
||||
maybeAddSandboxCategory();
|
||||
addOnboardingPrefsCatergory();
|
||||
}
|
||||
@@ -160,65 +135,6 @@ public class DeveloperOptionsUI {
|
||||
return mFragment.requireContext();
|
||||
}
|
||||
|
||||
private void loadPluginPrefs() {
|
||||
if (mPluginsCategory != null) {
|
||||
mPreferenceScreen.removePreference(mPluginsCategory);
|
||||
}
|
||||
if (!PluginManagerWrapper.hasPlugins(getContext())) {
|
||||
mPluginsCategory = null;
|
||||
return;
|
||||
}
|
||||
mPluginsCategory = newCategory("Plugins");
|
||||
|
||||
PluginManagerWrapper manager = PluginManagerWrapper.INSTANCE.get(getContext());
|
||||
Context prefContext = getContext();
|
||||
PackageManager pm = getContext().getPackageManager();
|
||||
|
||||
Set<String> pluginActions = manager.getPluginActions();
|
||||
|
||||
ArrayMap<Pair<String, String>, ArrayList<Pair<String, ResolveInfo>>> 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), MATCH_DISABLED_COMPONENTS | GET_RESOLVED_FILTER);
|
||||
for (ResolveInfo info : result) {
|
||||
String packageName = info.serviceInfo.packageName;
|
||||
if (!pluginPermissionApps.contains(packageName)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
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));
|
||||
}
|
||||
}
|
||||
|
||||
PluginEnabler enabler = manager.getPluginEnabler();
|
||||
plugins.forEach((key, si) -> {
|
||||
String packageName = key.first;
|
||||
List<ComponentName> componentNames = si.stream()
|
||||
.map(p -> new ComponentName(packageName, p.second.serviceInfo.name))
|
||||
.collect(Collectors.toList());
|
||||
if (!componentNames.isEmpty()) {
|
||||
SwitchPreference pref = new PluginPreference(
|
||||
prefContext, si.get(0).second, enabler, componentNames);
|
||||
pref.setSummary("Plugins: "
|
||||
+ si.stream().map(p -> p.first).collect(Collectors.joining(", ")));
|
||||
mPluginsCategory.addPreference(pref);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private void maybeAddSandboxCategory() {
|
||||
Context context = getContext();
|
||||
if (context == null) {
|
||||
@@ -321,102 +237,4 @@ public class DeveloperOptionsUI {
|
||||
});
|
||||
return onboardingPref;
|
||||
}
|
||||
|
||||
private String toName(String action) {
|
||||
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) {
|
||||
b.append(' ');
|
||||
}
|
||||
b.append(s.substring(0, 1));
|
||||
b.append(s.substring(1).toLowerCase());
|
||||
}
|
||||
return b.toString();
|
||||
}
|
||||
|
||||
private static class PluginPreference extends SwitchPreference {
|
||||
private final String mPackageName;
|
||||
private final ResolveInfo mSettingsInfo;
|
||||
private final PluginEnabler mPluginEnabler;
|
||||
private final List<ComponentName> mComponentNames;
|
||||
|
||||
PluginPreference(Context prefContext, ResolveInfo pluginInfo,
|
||||
PluginEnabler pluginEnabler, List<ComponentName> componentNames) {
|
||||
super(prefContext);
|
||||
PackageManager pm = prefContext.getPackageManager();
|
||||
mPackageName = pluginInfo.serviceInfo.applicationInfo.packageName;
|
||||
Intent settingsIntent = new Intent(ACTION_PLUGIN_SETTINGS).setPackage(mPackageName);
|
||||
// If any Settings activity in app has category filters, set plugin action as category.
|
||||
List<ResolveInfo> settingsInfos =
|
||||
pm.queryIntentActivities(settingsIntent, GET_RESOLVED_FILTER);
|
||||
if (pluginInfo.filter != null) {
|
||||
for (ResolveInfo settingsInfo : settingsInfos) {
|
||||
if (settingsInfo.filter != null && settingsInfo.filter.countCategories() > 0) {
|
||||
settingsIntent.addCategory(pluginInfo.filter.getAction(0));
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
mSettingsInfo = pm.resolveActivity(settingsIntent, 0);
|
||||
mPluginEnabler = pluginEnabler;
|
||||
mComponentNames = componentNames;
|
||||
setTitle(pluginInfo.loadLabel(pm));
|
||||
setChecked(isPluginEnabled());
|
||||
setWidgetLayoutResource(R.layout.switch_preference_with_settings);
|
||||
}
|
||||
|
||||
private boolean isPluginEnabled() {
|
||||
for (ComponentName componentName : mComponentNames) {
|
||||
if (!mPluginEnabler.isEnabled(componentName)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean persistBoolean(boolean isEnabled) {
|
||||
boolean shouldSendBroadcast = false;
|
||||
for (ComponentName componentName : mComponentNames) {
|
||||
if (mPluginEnabler.isEnabled(componentName) != isEnabled) {
|
||||
mPluginEnabler.setDisabled(componentName,
|
||||
isEnabled ? PluginEnabler.ENABLED : PluginEnabler.DISABLED_MANUALLY);
|
||||
shouldSendBroadcast = true;
|
||||
}
|
||||
}
|
||||
if (shouldSendBroadcast) {
|
||||
final String pkg = mPackageName;
|
||||
final Intent intent = new Intent(PLUGIN_CHANGED,
|
||||
pkg != null ? Uri.fromParts("package", pkg, null) : null);
|
||||
getContext().sendBroadcast(intent);
|
||||
}
|
||||
setChecked(isEnabled);
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onBindViewHolder(PreferenceViewHolder holder) {
|
||||
super.onBindViewHolder(holder);
|
||||
boolean hasSettings = mSettingsInfo != null;
|
||||
holder.findViewById(R.id.settings).setVisibility(hasSettings ? VISIBLE : GONE);
|
||||
holder.findViewById(R.id.divider).setVisibility(hasSettings ? VISIBLE : GONE);
|
||||
holder.findViewById(R.id.settings).setOnClickListener(v -> {
|
||||
if (hasSettings) {
|
||||
v.getContext().startActivity(new Intent().setComponent(
|
||||
new ComponentName(mSettingsInfo.activityInfo.packageName,
|
||||
mSettingsInfo.activityInfo.name)));
|
||||
}
|
||||
});
|
||||
holder.itemView.setOnLongClickListener(v -> {
|
||||
Intent intent = new Intent(Settings.ACTION_APPLICATION_DETAILS_SETTINGS);
|
||||
intent.setData(Uri.fromParts("package", mPackageName, null));
|
||||
getContext().startActivity(intent);
|
||||
return true;
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,15 +1,17 @@
|
||||
/*
|
||||
* Copyright (C) 2018 The Android Open Source Project
|
||||
* Copyright (C) 2024 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
|
||||
* 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.
|
||||
* 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.uioverrides.plugins;
|
||||
@@ -24,11 +26,10 @@ import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.content.pm.ResolveInfo;
|
||||
|
||||
import com.android.launcher3.Utilities;
|
||||
import com.android.launcher3.util.MainThreadInitializedObject;
|
||||
import com.android.launcher3.BuildConfig;
|
||||
import com.android.launcher3.util.PluginManagerWrapper;
|
||||
import com.android.systemui.plugins.Plugin;
|
||||
import com.android.systemui.plugins.PluginListener;
|
||||
import com.android.systemui.plugins.PluginManager;
|
||||
import com.android.systemui.shared.plugins.PluginActionManager;
|
||||
import com.android.systemui.shared.plugins.PluginInstance;
|
||||
import com.android.systemui.shared.plugins.PluginManagerImpl;
|
||||
@@ -41,35 +42,30 @@ import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
|
||||
public class PluginManagerWrapper {
|
||||
|
||||
public static final MainThreadInitializedObject<PluginManagerWrapper> INSTANCE =
|
||||
new MainThreadInitializedObject<>(PluginManagerWrapper::new);
|
||||
|
||||
public static final String PLUGIN_CHANGED = PluginManager.PLUGIN_CHANGED;
|
||||
public class PluginManagerWrapperImpl extends PluginManagerWrapper {
|
||||
|
||||
private static final UncaughtExceptionPreHandlerManager UNCAUGHT_EXCEPTION_PRE_HANDLER_MANAGER =
|
||||
new UncaughtExceptionPreHandlerManager();
|
||||
|
||||
private final Context mContext;
|
||||
private final PluginManager mPluginManager;
|
||||
private final PluginManagerImpl mPluginManager;
|
||||
private final PluginEnablerImpl mPluginEnabler;
|
||||
|
||||
private PluginManagerWrapper(Context c) {
|
||||
public PluginManagerWrapperImpl(Context c) {
|
||||
mContext = c;
|
||||
mPluginEnabler = new PluginEnablerImpl(c);
|
||||
List<String> privilegedPlugins = Collections.emptyList();
|
||||
PluginInstance.Factory instanceFactory = new PluginInstance.Factory(
|
||||
getClass().getClassLoader(), new PluginInstance.InstanceFactory<>(),
|
||||
new PluginInstance.VersionCheckerImpl(), privilegedPlugins,
|
||||
Utilities.IS_DEBUG_DEVICE);
|
||||
BuildConfig.IS_DEBUG_DEVICE);
|
||||
PluginActionManager.Factory instanceManagerFactory = new PluginActionManager.Factory(
|
||||
c, c.getPackageManager(), c.getMainExecutor(), MODEL_EXECUTOR,
|
||||
c.getSystemService(NotificationManager.class), mPluginEnabler,
|
||||
privilegedPlugins, instanceFactory);
|
||||
|
||||
mPluginManager = new PluginManagerImpl(c, instanceManagerFactory,
|
||||
Utilities.IS_DEBUG_DEVICE,
|
||||
BuildConfig.IS_DEBUG_DEVICE,
|
||||
UNCAUGHT_EXCEPTION_PRE_HANDLER_MANAGER, mPluginEnabler,
|
||||
new PluginPrefs(c), privilegedPlugins);
|
||||
}
|
||||
@@ -78,18 +74,13 @@ public class PluginManagerWrapper {
|
||||
return mPluginEnabler;
|
||||
}
|
||||
|
||||
/** */
|
||||
public <T extends Plugin> void addPluginListener(
|
||||
PluginListener<T> listener, Class<T> pluginClass) {
|
||||
addPluginListener(listener, pluginClass, false);
|
||||
}
|
||||
|
||||
/** */
|
||||
@Override
|
||||
public <T extends Plugin> void addPluginListener(
|
||||
PluginListener<T> listener, Class<T> pluginClass, boolean allowMultiple) {
|
||||
mPluginManager.addPluginListener(listener, pluginClass, allowMultiple);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void removePluginListener(PluginListener<? extends Plugin> listener) {
|
||||
mPluginManager.removePluginListener(listener);
|
||||
}
|
||||
@@ -98,10 +89,12 @@ public class PluginManagerWrapper {
|
||||
return new PluginPrefs(mContext).getPluginList();
|
||||
}
|
||||
|
||||
public static boolean hasPlugins(Context context) {
|
||||
return PluginPrefs.hasPlugins(context);
|
||||
/** Notifies that a plugin state has changed */
|
||||
public void notifyChange(Intent intent) {
|
||||
mPluginManager.onReceive(mContext, intent);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void dump(PrintWriter pw) {
|
||||
final List<ComponentName> enabledPlugins = new ArrayList<>();
|
||||
final List<ComponentName> disabledPlugins = new ArrayList<>();
|
||||
@@ -95,9 +95,9 @@ import com.android.launcher3.taskbar.TaskbarManager;
|
||||
import com.android.launcher3.testing.TestLogging;
|
||||
import com.android.launcher3.testing.shared.ResourceUtils;
|
||||
import com.android.launcher3.testing.shared.TestProtocol;
|
||||
import com.android.launcher3.uioverrides.plugins.PluginManagerWrapper;
|
||||
import com.android.launcher3.util.DisplayController;
|
||||
import com.android.launcher3.util.LockedUserState;
|
||||
import com.android.launcher3.util.PluginManagerWrapper;
|
||||
import com.android.launcher3.util.SafeCloseable;
|
||||
import com.android.launcher3.util.ScreenOnTracker;
|
||||
import com.android.launcher3.util.TraceHelper;
|
||||
|
||||
@@ -1,46 +0,0 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!-- Copyright (C) 2018 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="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="horizontal"
|
||||
android:gravity="center_vertical">
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/settings"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:src="@drawable/ic_setting"
|
||||
android:forceDarkAllowed="true"
|
||||
android:padding="12dp"
|
||||
android:background="?android:attr/selectableItemBackgroundBorderless" />
|
||||
|
||||
<View
|
||||
android:id="@+id/divider"
|
||||
android:layout_width="1dp"
|
||||
android:layout_height="30dp"
|
||||
android:layout_marginEnd="8dp"
|
||||
android:background="?android:attr/listDivider" />
|
||||
|
||||
<!-- Note: seems we need focusable="false" and clickable="false" when moving to androidx -->
|
||||
<Switch
|
||||
android:id="@android:id/switch_widget"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:background="@null" />
|
||||
</LinearLayout>
|
||||
@@ -84,7 +84,7 @@
|
||||
<string name="wallpaper_picker_package" translatable="false"></string>
|
||||
<string name="local_colors_extraction_class" translatable="false"></string>
|
||||
<string name="search_session_manager_class" translatable="false"></string>
|
||||
|
||||
<string name="plugin_manager_wrapper_class" translatable="false"></string>
|
||||
|
||||
<!-- Scalable Grid configuration -->
|
||||
<!-- This is a float because it is converted to dp later in DeviceProfile -->
|
||||
|
||||
@@ -222,7 +222,6 @@ import com.android.launcher3.testing.TestLogging;
|
||||
import com.android.launcher3.testing.shared.TestProtocol;
|
||||
import com.android.launcher3.touch.AllAppsSwipeController;
|
||||
import com.android.launcher3.touch.ItemLongClickListener;
|
||||
import com.android.launcher3.uioverrides.plugins.PluginManagerWrapper;
|
||||
import com.android.launcher3.util.ActivityResultInfo;
|
||||
import com.android.launcher3.util.ActivityTracker;
|
||||
import com.android.launcher3.util.BackPressHandler;
|
||||
@@ -235,6 +234,7 @@ import com.android.launcher3.util.KeyboardShortcutsDelegate;
|
||||
import com.android.launcher3.util.LockedUserState;
|
||||
import com.android.launcher3.util.PackageUserKey;
|
||||
import com.android.launcher3.util.PendingRequestArgs;
|
||||
import com.android.launcher3.util.PluginManagerWrapper;
|
||||
import com.android.launcher3.util.RunnableList;
|
||||
import com.android.launcher3.util.ScreenOnTracker;
|
||||
import com.android.launcher3.util.ScreenOnTracker.ScreenOnListener;
|
||||
@@ -576,8 +576,8 @@ public class Launcher extends StatefulActivity<LauncherState>
|
||||
Themes.getAttrBoolean(this, R.attr.isWorkspaceDarkText));
|
||||
|
||||
mOverlayManager = getDefaultOverlay();
|
||||
PluginManagerWrapper.INSTANCE.get(this).addPluginListener(this,
|
||||
LauncherOverlayPlugin.class, false /* allowedMultiple */);
|
||||
PluginManagerWrapper.INSTANCE.get(this)
|
||||
.addPluginListener(this, LauncherOverlayPlugin.class);
|
||||
|
||||
mRotationHelper.initialize();
|
||||
TraceHelper.INSTANCE.endSection();
|
||||
|
||||
@@ -34,7 +34,7 @@ import com.android.launcher3.Insettable;
|
||||
import com.android.launcher3.R;
|
||||
import com.android.launcher3.allapps.ActivityAllAppsContainerView.AdapterHolder;
|
||||
import com.android.launcher3.config.FeatureFlags;
|
||||
import com.android.launcher3.uioverrides.plugins.PluginManagerWrapper;
|
||||
import com.android.launcher3.util.PluginManagerWrapper;
|
||||
import com.android.launcher3.views.ActivityContext;
|
||||
import com.android.systemui.plugins.AllAppsRow;
|
||||
import com.android.systemui.plugins.AllAppsRow.OnHeightUpdatedListener;
|
||||
|
||||
@@ -90,12 +90,12 @@ import com.android.launcher3.model.data.LauncherAppWidgetInfo;
|
||||
import com.android.launcher3.model.data.WorkspaceItemInfo;
|
||||
import com.android.launcher3.pm.InstallSessionHelper;
|
||||
import com.android.launcher3.pm.UserCache;
|
||||
import com.android.launcher3.uioverrides.plugins.PluginManagerWrapper;
|
||||
import com.android.launcher3.util.ComponentKey;
|
||||
import com.android.launcher3.util.DisplayController;
|
||||
import com.android.launcher3.util.IntArray;
|
||||
import com.android.launcher3.util.IntSet;
|
||||
import com.android.launcher3.util.MainThreadInitializedObject.SandboxContext;
|
||||
import com.android.launcher3.util.PluginManagerWrapper;
|
||||
import com.android.launcher3.util.WindowBounds;
|
||||
import com.android.launcher3.util.window.WindowManagerProxy;
|
||||
import com.android.launcher3.views.ActivityContext;
|
||||
|
||||
@@ -22,7 +22,6 @@ 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;
|
||||
|
||||
|
||||
46
src/com/android/launcher3/util/PluginManagerWrapper.java
Normal file
46
src/com/android/launcher3/util/PluginManagerWrapper.java
Normal file
@@ -0,0 +1,46 @@
|
||||
/*
|
||||
* Copyright (C) 2024 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 static com.android.launcher3.util.MainThreadInitializedObject.forOverride;
|
||||
|
||||
import com.android.launcher3.R;
|
||||
import com.android.systemui.plugins.Plugin;
|
||||
import com.android.systemui.plugins.PluginListener;
|
||||
|
||||
import java.io.PrintWriter;
|
||||
|
||||
public class PluginManagerWrapper implements ResourceBasedOverride, SafeCloseable {
|
||||
|
||||
public static final MainThreadInitializedObject<PluginManagerWrapper> INSTANCE =
|
||||
forOverride(PluginManagerWrapper.class, R.string.plugin_manager_wrapper_class);
|
||||
|
||||
public <T extends Plugin> void addPluginListener(
|
||||
PluginListener<T> listener, Class<T> pluginClass) {
|
||||
addPluginListener(listener, pluginClass, false);
|
||||
}
|
||||
|
||||
public <T extends Plugin> void addPluginListener(
|
||||
PluginListener<T> listener, Class<T> pluginClass, boolean allowMultiple) {
|
||||
}
|
||||
|
||||
public void removePluginListener(PluginListener<? extends Plugin> listener) { }
|
||||
|
||||
@Override
|
||||
public void close() { }
|
||||
|
||||
public void dump(PrintWriter pw) { }
|
||||
}
|
||||
@@ -32,9 +32,9 @@ import androidx.annotation.NonNull;
|
||||
import androidx.annotation.Nullable;
|
||||
|
||||
import com.android.launcher3.R;
|
||||
import com.android.launcher3.uioverrides.plugins.PluginManagerWrapper;
|
||||
import com.android.launcher3.util.MainThreadInitializedObject;
|
||||
import com.android.launcher3.util.PackageUserKey;
|
||||
import com.android.launcher3.util.PluginManagerWrapper;
|
||||
import com.android.launcher3.util.SafeCloseable;
|
||||
import com.android.launcher3.widget.LauncherAppWidgetHostView;
|
||||
import com.android.launcher3.widget.LauncherAppWidgetProviderInfo;
|
||||
|
||||
@@ -1,64 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2018 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.uioverrides.plugins;
|
||||
|
||||
import android.content.ComponentName;
|
||||
import android.content.Context;
|
||||
|
||||
import com.android.launcher3.util.MainThreadInitializedObject;
|
||||
import com.android.systemui.plugins.Plugin;
|
||||
import com.android.systemui.plugins.PluginListener;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.Set;
|
||||
|
||||
import androidx.preference.PreferenceDataStore;
|
||||
|
||||
public class PluginManagerWrapper {
|
||||
|
||||
public static final MainThreadInitializedObject<PluginManagerWrapper> INSTANCE =
|
||||
new MainThreadInitializedObject<>(PluginManagerWrapper::new);
|
||||
|
||||
private static final String PREFIX_PLUGIN_ENABLED = "PLUGIN_ENABLED_";
|
||||
public static final String PLUGIN_CHANGED = "com.android.systemui.action.PLUGIN_CHANGED";
|
||||
|
||||
private PluginManagerWrapper(Context c) {
|
||||
}
|
||||
|
||||
public void addPluginListener(PluginListener<? extends Plugin> listener, Class<?> pluginClass) {
|
||||
}
|
||||
|
||||
public void addPluginListener(PluginListener<? extends Plugin> listener, Class<?> pluginClass,
|
||||
boolean allowMultiple) {
|
||||
}
|
||||
|
||||
public void removePluginListener(PluginListener<? extends Plugin> listener) { }
|
||||
|
||||
public Set<String> getPluginActions() {
|
||||
return Collections.emptySet();
|
||||
}
|
||||
|
||||
public PreferenceDataStore getPluginEnabler() {
|
||||
return new PreferenceDataStore() { };
|
||||
}
|
||||
|
||||
public static String pluginEnabledKey(ComponentName cn) {
|
||||
return PREFIX_PLUGIN_ENABLED + cn.flattenToString();
|
||||
}
|
||||
|
||||
public static boolean hasPlugins(Context context) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,31 @@
|
||||
/*
|
||||
* Copyright (C) 2024 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.systemui.plugins;
|
||||
|
||||
import com.android.systemui.plugins.annotations.ProvidesInterface;
|
||||
|
||||
/**
|
||||
* Implement this plugin to proxy network requests
|
||||
*/
|
||||
@ProvidesInterface(action = NetworkFetcherPlugin.ACTION, version = NetworkFetcherPlugin.VERSION)
|
||||
public interface NetworkFetcherPlugin extends Plugin {
|
||||
String ACTION = "com.android.systemui.action.PLUGIN_NETWORK_FETCHER_ACTIONS";
|
||||
int VERSION = 1;
|
||||
|
||||
/** Fetches the provided user and return all byte contents */
|
||||
byte[] fetchUrl(String url) throws Exception;
|
||||
}
|
||||
@@ -60,7 +60,6 @@ import com.android.launcher3.model.ItemInstallQueue;
|
||||
import com.android.launcher3.pm.InstallSessionHelper;
|
||||
import com.android.launcher3.pm.UserCache;
|
||||
import com.android.launcher3.testing.TestInformationProvider;
|
||||
import com.android.launcher3.uioverrides.plugins.PluginManagerWrapper;
|
||||
import com.android.launcher3.util.MainThreadInitializedObject.SandboxContext;
|
||||
import com.android.launcher3.util.window.WindowManagerProxy;
|
||||
import com.android.launcher3.widget.custom.CustomWidgetManager;
|
||||
|
||||
Reference in New Issue
Block a user