/* * 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.systemui.tuner; import android.content.BroadcastReceiver; 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.PackageManager; import android.content.pm.ResolveInfo; import android.net.Uri; import android.os.Bundle; import android.provider.Settings; import android.support.v14.preference.PreferenceFragment; import android.support.v14.preference.SwitchPreference; import android.support.v7.preference.PreferenceScreen; import android.support.v7.preference.PreferenceViewHolder; import android.util.ArrayMap; import android.util.ArraySet; import android.view.View; import com.android.systemui.R; import com.android.systemui.plugins.PluginInstanceManager; import com.android.systemui.plugins.PluginManager; import com.android.systemui.plugins.PluginPrefs; import java.util.ArrayList; import java.util.List; import java.util.Set; public class PluginFragment extends PreferenceFragment { public static final String ACTION_PLUGIN_SETTINGS = "com.android.systemui.action.PLUGIN_SETTINGS"; private PluginPrefs mPluginPrefs; @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); IntentFilter filter = new IntentFilter(Intent.ACTION_PACKAGE_ADDED); filter.addAction(Intent.ACTION_PACKAGE_CHANGED); filter.addAction(Intent.ACTION_PACKAGE_REMOVED); filter.addDataScheme("package"); getContext().registerReceiver(mReceiver, filter); filter = new IntentFilter(Intent.ACTION_USER_UNLOCKED); getContext().registerReceiver(mReceiver, filter); } @Override public void onDestroy() { super.onDestroy(); getContext().unregisterReceiver(mReceiver); } @Override public void onCreatePreferences(Bundle savedInstanceState, String rootKey) { loadPrefs(); } private void loadPrefs() { PreferenceScreen screen = getPreferenceManager().createPreferenceScreen(getContext()); screen.setOrderingAsAdded(false); Context prefContext = getPreferenceManager().getContext(); mPluginPrefs = new PluginPrefs(getContext()); PackageManager pm = getContext().getPackageManager(); Set pluginActions = mPluginPrefs.getPluginList(); ArrayMap> plugins = new ArrayMap<>(); for (String action : pluginActions) { String name = toName(action); List result = pm.queryIntentServices( new Intent(action), PackageManager.MATCH_DISABLED_COMPONENTS); for (ResolveInfo info : result) { String packageName = info.serviceInfo.packageName; if (!plugins.containsKey(packageName)) { plugins.put(packageName, new ArraySet<>()); } plugins.get(packageName).add(name); } } List apps = pm.getPackagesHoldingPermissions(new String[]{ PluginInstanceManager.PLUGIN_PERMISSION}, PackageManager.MATCH_DISABLED_COMPONENTS | PackageManager.GET_SERVICES); apps.forEach(app -> { if (!plugins.containsKey(app.packageName)) return; SwitchPreference pref = new PluginPreference(prefContext, app); pref.setSummary("Plugins: " + toString(plugins.get(app.packageName))); screen.addPreference(pref); }); setPreferenceScreen(screen); } private String toString(ArraySet plugins) { StringBuilder b = new StringBuilder(); for (String string : plugins) { if (b.length() != 0) { b.append(", "); } b.append(string); } return b.toString(); } private String toName(String action) { String str = action.replace("com.android.systemui.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 final BroadcastReceiver mReceiver = new BroadcastReceiver() { @Override public void onReceive(Context context, Intent intent) { loadPrefs(); } }; private static class PluginPreference extends SwitchPreference { private final boolean mHasSettings; private final PackageInfo mInfo; private final PackageManager mPm; public PluginPreference(Context prefContext, PackageInfo info) { super(prefContext); mPm = prefContext.getPackageManager(); mHasSettings = mPm.resolveActivity(new Intent(ACTION_PLUGIN_SETTINGS) .setPackage(info.packageName), 0) != null; mInfo = info; setTitle(info.applicationInfo.loadLabel(mPm)); setChecked(isPluginEnabled()); setWidgetLayoutResource(R.layout.tuner_widget_settings_switch); } private boolean isPluginEnabled() { for (int i = 0; i < mInfo.services.length; i++) { ComponentName componentName = new ComponentName(mInfo.packageName, mInfo.services[i].name); if (mPm.getComponentEnabledSetting(componentName) == PackageManager.COMPONENT_ENABLED_STATE_DISABLED) { return false; } } return true; } @Override protected boolean persistBoolean(boolean value) { final int desiredState = value ? PackageManager.COMPONENT_ENABLED_STATE_ENABLED : PackageManager.COMPONENT_ENABLED_STATE_DISABLED; boolean shouldSendBroadcast = false; for (int i = 0; i < mInfo.services.length; i++) { ComponentName componentName = new ComponentName(mInfo.packageName, mInfo.services[i].name); if (mPm.getComponentEnabledSetting(componentName) != desiredState) { mPm.setComponentEnabledSetting(componentName, desiredState, PackageManager.DONT_KILL_APP); shouldSendBroadcast = true; } } if (shouldSendBroadcast) { final String pkg = mInfo.packageName; final Intent intent = new Intent(PluginManager.PLUGIN_CHANGED, pkg != null ? Uri.fromParts("package", pkg, null) : null); getContext().sendBroadcast(intent); } return true; } @Override public void onBindViewHolder(PreferenceViewHolder holder) { super.onBindViewHolder(holder); holder.findViewById(R.id.settings).setVisibility(mHasSettings ? View.VISIBLE : View.GONE); holder.findViewById(R.id.divider).setVisibility(mHasSettings ? View.VISIBLE : View.GONE); holder.findViewById(R.id.settings).setOnClickListener(v -> { ResolveInfo result = v.getContext().getPackageManager().resolveActivity( new Intent(ACTION_PLUGIN_SETTINGS).setPackage( mInfo.packageName), 0); if (result != null) { v.getContext().startActivity(new Intent().setComponent( new ComponentName(result.activityInfo.packageName, result.activityInfo.name))); } }); holder.itemView.setOnLongClickListener(v -> { Intent intent = new Intent(Settings.ACTION_APPLICATION_DETAILS_SETTINGS); intent.setData(Uri.fromParts("package", mInfo.packageName, null)); getContext().startActivity(intent); return true; }); } } }