/* * 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.car.settings.common; import static com.android.settingslib.drawer.CategoryKey.CATEGORY_DEVICE; import static com.android.settingslib.drawer.TileUtils.META_DATA_PREFERENCE_ICON; import static com.android.settingslib.drawer.TileUtils.META_DATA_PREFERENCE_SUMMARY; import static com.android.settingslib.drawer.TileUtils.META_DATA_PREFERENCE_TITLE; import android.app.ActivityManager; import android.content.Context; import android.content.Intent; import android.content.pm.ActivityInfo; import android.content.pm.PackageManager; import android.content.pm.ResolveInfo; import android.content.res.Resources; import android.graphics.drawable.Icon; import android.os.Bundle; import android.text.TextUtils; import androidx.preference.Preference; import com.android.car.apps.common.util.Themes; import com.android.car.settings.R; import com.android.car.ui.preference.CarUiPreference; import java.util.HashMap; import java.util.List; import java.util.Map; /** * Loads Activity with TileUtils.EXTRA_SETTINGS_ACTION. */ // TODO: investigate using SettingsLib Tiles. public class ExtraSettingsLoader { private static final Logger LOG = new Logger(ExtraSettingsLoader.class); private static final String META_DATA_PREFERENCE_CATEGORY = "com.android.settings.category"; private Map mPreferenceBundleMap; private final Context mContext; public ExtraSettingsLoader(Context context) { mContext = context; mPreferenceBundleMap = new HashMap<>(); } /** * Returns a map of {@link Preference} and {@link Bundle} representing settings injected from * system apps and their metadata. The given intent must specify the action to use for * resolving activities and a category with the key "com.android.settings.category" and one of * the values in {@link com.android.settingslib.drawer.CategoryKey}. * * @param intent intent specifying the extra settings category to load */ public Map loadPreferences(Intent intent) { PackageManager pm = mContext.getPackageManager(); List results = pm.queryIntentActivitiesAsUser(intent, PackageManager.GET_META_DATA, ActivityManager.getCurrentUser()); String extraCategory = intent.getStringExtra(META_DATA_PREFERENCE_CATEGORY); for (ResolveInfo resolved : results) { if (!resolved.system) { // Do not allow any app to be added to settings, only system ones. continue; } String title = null; String summary = null; String category = null; ActivityInfo activityInfo = resolved.activityInfo; Bundle metaData = activityInfo.metaData; try { Resources res = pm.getResourcesForApplication(activityInfo.packageName); if (metaData.containsKey(META_DATA_PREFERENCE_TITLE)) { if (metaData.get(META_DATA_PREFERENCE_TITLE) instanceof Integer) { title = res.getString(metaData.getInt(META_DATA_PREFERENCE_TITLE)); } else { title = metaData.getString(META_DATA_PREFERENCE_TITLE); } } if (TextUtils.isEmpty(title)) { LOG.d("no title."); title = activityInfo.loadLabel(pm).toString(); } if (metaData.containsKey(META_DATA_PREFERENCE_SUMMARY)) { if (metaData.get(META_DATA_PREFERENCE_SUMMARY) instanceof Integer) { summary = res.getString(metaData.getInt(META_DATA_PREFERENCE_SUMMARY)); } else { summary = metaData.getString(META_DATA_PREFERENCE_SUMMARY); } } else { LOG.d("no description."); } if (metaData.containsKey(META_DATA_PREFERENCE_CATEGORY)) { if (metaData.get(META_DATA_PREFERENCE_CATEGORY) instanceof Integer) { category = res.getString(metaData.getInt(META_DATA_PREFERENCE_CATEGORY)); } else { category = metaData.getString(META_DATA_PREFERENCE_CATEGORY); } } else { LOG.d("no category."); } } catch (PackageManager.NameNotFoundException | Resources.NotFoundException e) { LOG.d("Couldn't find info", e); } Icon icon = null; if (metaData.containsKey(META_DATA_PREFERENCE_ICON)) { int iconRes = metaData.getInt(META_DATA_PREFERENCE_ICON); icon = Icon.createWithResource(activityInfo.packageName, iconRes); } else { icon = Icon.createWithResource(mContext, R.drawable.ic_settings_gear); LOG.d("use default icon."); } Intent extraSettingIntent = new Intent().setClassName(activityInfo.packageName, activityInfo.name); if (category == null) { // If category is not specified or not supported, default to device. category = CATEGORY_DEVICE; } if (!TextUtils.equals(extraCategory, category)) { continue; } CarUiPreference preference = new CarUiPreference(mContext); preference.setTitle(title); preference.setSummary(summary); if (icon != null) { preference.setIcon(icon.loadDrawable(mContext)); preference.getIcon().setTintList( Themes.getAttrColorStateList(mContext, R.attr.iconColor)); } preference.setIntent(extraSettingIntent); mPreferenceBundleMap.put(preference, metaData); } return mPreferenceBundleMap; } }