Automatic sources dropoff on 2020-06-10 18:32:38.095721
The change is generated with prebuilt drop tool.
Change-Id: I24cbf6ba6db262a1ae1445db1427a08fee35b3b4
diff --git a/com/android/car/setupwizardlib/partner/PartnerConfig.java b/com/android/car/setupwizardlib/partner/PartnerConfig.java
new file mode 100644
index 0000000..8946b7a
--- /dev/null
+++ b/com/android/car/setupwizardlib/partner/PartnerConfig.java
@@ -0,0 +1,102 @@
+/*
+ * 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.car.setupwizardlib.partner;
+
+/** Resources that can be customized by partner overlay APK. */
+public enum PartnerConfig {
+
+ CONFIG_TOOLBAR_BG_COLOR(
+ PartnerConfigKey.KEY_TOOLBAR_BG_COLOR, ResourceType.COLOR),
+
+ CONFIG_TOOLBAR_BUTTON_ICON_BACK(
+ PartnerConfigKey.KEY_TOOLBAR_BUTTON_ICON_BACK, ResourceType.DRAWABLE),
+
+ CONFIG_TOOLBAR_BUTTON_FONT_FAMILY(
+ PartnerConfigKey.KEY_TOOLBAR_BUTTON_FONT_FAMILY, ResourceType.STRING),
+
+ CONFIG_TOOLBAR_BUTTON_PADDING_HORIZONTAL(
+ PartnerConfigKey.KEY_TOOLBAR_BUTTON_PADDING_HORIZONTAL, ResourceType.DIMENSION),
+
+ CONFIG_TOOLBAR_BUTTON_PADDING_VERTICAL(
+ PartnerConfigKey.KEY_TOOLBAR_BUTTON_PADDING_VERTICAL, ResourceType.DIMENSION),
+
+ CONFIG_TOOLBAR_BUTTON_RADIUS(
+ PartnerConfigKey.KEY_TOOLBAR_BUTTON_RADIUS, ResourceType.DIMENSION),
+
+ CONFIG_TOOLBAR_BUTTON_SPACING(
+ PartnerConfigKey.KEY_TOOLBAR_BUTTON_SPACING, ResourceType.DIMENSION),
+
+ CONFIG_TOOLBAR_BUTTON_TEXT_SIZE(
+ PartnerConfigKey.KEY_TOOLBAR_BUTTON_TEXT_SIZE, ResourceType.DIMENSION),
+
+ CONFIG_TOOLBAR_PRIMARY_BUTTON_BG(
+ PartnerConfigKey.KEY_TOOLBAR_PRIMARY_BUTTON_BG, ResourceType.DRAWABLE),
+
+ CONFIG_TOOLBAR_PRIMARY_BUTTON_BG_COLOR(
+ PartnerConfigKey.KEY_TOOLBAR_PRIMARY_BUTTON_BG_COLOR, ResourceType.COLOR),
+
+ CONFIG_TOOLBAR_PRIMARY_BUTTON_TEXT_COLOR(
+ PartnerConfigKey.KEY_TOOLBAR_PRIMARY_BUTTON_TEXT_COLOR, ResourceType.COLOR),
+
+ CONFIG_TOOLBAR_SECONDARY_BUTTON_BG(
+ PartnerConfigKey.KEY_TOOLBAR_SECONDARY_BUTTON_BG, ResourceType.DRAWABLE),
+
+ CONFIG_TOOLBAR_SECONDARY_BUTTON_BG_COLOR(
+ PartnerConfigKey.KEY_TOOLBAR_SECONDARY_BUTTON_BG_COLOR, ResourceType.COLOR),
+
+ CONFIG_TOOLBAR_SECONDARY_BUTTON_TEXT_COLOR(
+ PartnerConfigKey.KEY_TOOLBAR_SECONDARY_BUTTON_TEXT_COLOR, ResourceType.COLOR),
+
+ CONFIG_TOOLBAR_DIVIDER_BG(
+ PartnerConfigKey.KEY_TOOLBAR_DIVIDER_BG, ResourceType.DRAWABLE),
+
+ CONFIG_TOOLBAR_DIVIDER_LINE_WEIGHT(
+ PartnerConfigKey.KEY_TOOLBAR_DIVIDER_LINE_WEIGHT, ResourceType.DIMENSION),
+
+ CONFIG_LOADING_INDICATOR_COLOR(
+ PartnerConfigKey.KEY_LOADING_INDICATOR_COLOR, ResourceType.COLOR),
+
+ CONFIG_LOADING_INDICATOR_LINE_WEIGHT(
+ PartnerConfigKey.KEY_LOADING_INDICATOR_LINE_WEIGHT, ResourceType.DIMENSION),
+
+ CONFIG_LAYOUT_BG_COLOR(
+ PartnerConfigKey.KEY_LAYOUT_BG_COLOR, ResourceType.COLOR);
+
+ public enum ResourceType {
+ COLOR,
+ DRAWABLE,
+ STRING,
+ DIMENSION,
+ BOOLEAN,
+ }
+
+ private final String mResourceName;
+ private final ResourceType mResourceType;
+
+ public ResourceType getResourceType() {
+ return mResourceType;
+ }
+
+ public String getResourceName() {
+ return mResourceName;
+ }
+
+ PartnerConfig(@PartnerConfigKey String resourceName, ResourceType type) {
+ this.mResourceName = resourceName;
+ this.mResourceType = type;
+ }
+}
diff --git a/com/android/car/setupwizardlib/partner/PartnerConfigHelper.java b/com/android/car/setupwizardlib/partner/PartnerConfigHelper.java
new file mode 100644
index 0000000..2f367a8
--- /dev/null
+++ b/com/android/car/setupwizardlib/partner/PartnerConfigHelper.java
@@ -0,0 +1,305 @@
+/*
+ * 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.car.setupwizardlib.partner;
+
+import android.content.ContentResolver;
+import android.content.Context;
+import android.content.pm.PackageManager;
+import android.content.res.Resources;
+import android.content.res.Resources.NotFoundException;
+import android.graphics.drawable.Drawable;
+import android.net.Uri;
+import android.os.Bundle;
+import android.util.Log;
+import android.util.TypedValue;
+
+import androidx.annotation.ColorInt;
+import androidx.annotation.NonNull;
+import androidx.annotation.Nullable;
+import androidx.annotation.VisibleForTesting;
+
+import java.util.EnumMap;
+
+/** The helper reads and caches the partner configurations from Car Setup Wizard. */
+public class PartnerConfigHelper {
+
+ private static final String TAG = PartnerConfigHelper.class.getSimpleName();
+
+ @VisibleForTesting
+ static final String SUW_AUTHORITY = "com.google.android.car.setupwizard.partner";
+
+ @VisibleForTesting
+ static final String SUW_GET_PARTNER_CONFIG_METHOD = "getOverlayConfig";
+ private static volatile PartnerConfigHelper sInstance = null;
+
+ @VisibleForTesting Bundle mResultBundle = null;
+
+ @VisibleForTesting
+ final EnumMap<PartnerConfig, Object> mPartnerResourceCache = new EnumMap<>(PartnerConfig.class);
+
+ /** Factory method to get an instance */
+ public static PartnerConfigHelper get(@NonNull Context context) {
+ if (sInstance == null) {
+ synchronized (PartnerConfigHelper.class) {
+ if (sInstance == null) {
+ sInstance = new PartnerConfigHelper(context);
+ }
+ }
+ }
+ return sInstance;
+ }
+
+ /**
+ * Returns the color of given {@code partnerConfig}, or 0 if the given {@code partnerConfig}
+ * is not found. If the {@code ResourceType} of the given {@code partnerConfig} is not color,
+ * IllegalArgumentException will be thrown.
+ *
+ * @param context The context of client activity
+ * @param partnerConfig The {@code PartnerConfig} of target resource
+ */
+ @ColorInt
+ public int getColor(@NonNull Context context, PartnerConfig partnerConfig) {
+ if (partnerConfig.getResourceType() != PartnerConfig.ResourceType.COLOR) {
+ throw new IllegalArgumentException("Not a color resource");
+ }
+
+ if (mPartnerResourceCache.containsKey(partnerConfig)) {
+ return (int) mPartnerResourceCache.get(partnerConfig);
+ }
+
+ int result = 0;
+ try {
+ String resourceName = partnerConfig.getResourceName();
+ ResourceEntry resourceEntry = getResourceEntryFromKey(resourceName);
+ if (resourceEntry == null) {
+ Log.w(TAG, "Resource not found: " + resourceName);
+ return 0;
+ }
+
+ Resources resource = getResourcesByPackageName(context, resourceEntry.getPackageName());
+ result = resource.getColor(resourceEntry.getResourceId(), null);
+ mPartnerResourceCache.put(partnerConfig, result);
+ } catch (PackageManager.NameNotFoundException exception) {
+ Log.e(TAG, exception.getMessage());
+ }
+ return result;
+ }
+
+ /**
+ * Returns the {@code Drawable} of given {@code partnerConfig}, or {@code null} if the given
+ * {@code partnerConfig} is not found. If the {@code ResourceType} of the given {@code
+ * resourceConfig} is not drawable, IllegalArgumentException will be thrown.
+ *
+ * @param context The context of client activity
+ * @param partnerConfig The {@code PartnerConfig} of target resource
+ */
+ @Nullable
+ public Drawable getDrawable(@NonNull Context context, PartnerConfig partnerConfig) {
+ if (partnerConfig.getResourceType() != PartnerConfig.ResourceType.DRAWABLE) {
+ throw new IllegalArgumentException("Not a drawable resource");
+ }
+
+ if (mPartnerResourceCache.containsKey(partnerConfig)) {
+ return (Drawable) mPartnerResourceCache.get(partnerConfig);
+ }
+
+ Drawable result = null;
+ try {
+ String resourceName = partnerConfig.getResourceName();
+ ResourceEntry resourceEntry = getResourceEntryFromKey(resourceName);
+ if (resourceEntry == null) {
+ Log.w(TAG, "Resource not found: " + resourceName);
+ return null;
+ }
+ Resources resource = getResourcesByPackageName(context, resourceEntry.getPackageName());
+
+ // for @null
+ TypedValue outValue = new TypedValue();
+ resource.getValue(resourceEntry.getResourceId(), outValue, true);
+ if (outValue.type == TypedValue.TYPE_REFERENCE && outValue.data == 0) {
+ return result;
+ }
+
+ result = resource.getDrawable(resourceEntry.getResourceId(), null);
+ mPartnerResourceCache.put(partnerConfig, result);
+ } catch (PackageManager.NameNotFoundException | NotFoundException exception) {
+ Log.e(TAG, exception.getMessage());
+ }
+ return result;
+ }
+
+ /**
+ * Returns the string of the given {@code partnerConfig}, or {@code null} if the given {@code
+ * resourceConfig} is not found. If the {@code ResourceType} of the given {@code partnerConfig}
+ * is not string, IllegalArgumentException will be thrown.
+ *
+ * @param context The context of client activity
+ * @param partnerConfig The {@code PartnerConfig} of target resource
+ */
+ @Nullable
+ public String getString(@NonNull Context context, PartnerConfig partnerConfig) {
+ if (partnerConfig.getResourceType() != PartnerConfig.ResourceType.STRING) {
+ throw new IllegalArgumentException("Not a string resource");
+ }
+
+ if (mPartnerResourceCache.containsKey(partnerConfig)) {
+ return (String) mPartnerResourceCache.get(partnerConfig);
+ }
+
+ String result = null;
+ try {
+ String resourceName = partnerConfig.getResourceName();
+ ResourceEntry resourceEntry = getResourceEntryFromKey(resourceName);
+ if (resourceEntry == null) {
+ Log.w(TAG, "Resource not found: " + resourceName);
+ return null;
+ }
+ Resources resource = getResourcesByPackageName(context, resourceEntry.getPackageName());
+ result = resource.getString(resourceEntry.getResourceId());
+ mPartnerResourceCache.put(partnerConfig, result);
+ } catch (PackageManager.NameNotFoundException exception) {
+ Log.e(TAG, exception.getMessage());
+ }
+ return result;
+ }
+
+ /**
+ * Returns the dimension of given {@code partnerConfig}. The default return value is 0.
+ *
+ * @param context The context of client activity
+ * @param resourceConfig The {@code PartnerConfig} of target resource
+ */
+ public float getDimension(@NonNull Context context, PartnerConfig resourceConfig) {
+ return getDimension(context, resourceConfig, 0);
+ }
+
+ /**
+ * Returns the dimension of given {@code partnerConfig}. If the given {@code partnerConfig}
+ * not found, will return {@code defaultValue}. If the {@code ResourceType} of given {@code
+ * resourceConfig} is not dimension, will throw IllegalArgumentException.
+ *
+ * @param context The context of client activity
+ * @param partnerConfig The {@code PartnerConfig} of target resource
+ * @param defaultValue The default value
+ */
+ public float getDimension(
+ @NonNull Context context, PartnerConfig partnerConfig, float defaultValue) {
+ if (partnerConfig.getResourceType() != PartnerConfig.ResourceType.DIMENSION) {
+ throw new IllegalArgumentException("Not a dimension resource");
+ }
+
+ if (mPartnerResourceCache.containsKey(partnerConfig)) {
+ return (float) mPartnerResourceCache.get(partnerConfig);
+ }
+
+ float result = defaultValue;
+ try {
+ String resourceName = partnerConfig.getResourceName();
+ ResourceEntry resourceEntry = getResourceEntryFromKey(resourceName);
+ if (resourceEntry == null) {
+ Log.w(TAG, "Resource not found: " + resourceName);
+ return defaultValue;
+ }
+ Resources resource = getResourcesByPackageName(context, resourceEntry.getPackageName());
+ result = resource.getDimension(resourceEntry.getResourceId());
+ mPartnerResourceCache.put(partnerConfig, result);
+ } catch (PackageManager.NameNotFoundException exception) {
+ Log.e(TAG, exception.getMessage());
+ }
+ return result;
+ }
+
+ /**
+ * Returns the boolean value of given {@code partnerConfig}. If the given {@code partnerConfig}
+ * not found, will return {@code defaultValue}. If the {@code ResourceType} of given {@code
+ * resourceConfig} is not boolean, will throw IllegalArgumentException.
+ *
+ * @param context The context of client activity
+ * @param partnerConfig The {@code PartnerConfig} of target resource
+ * @param defaultValue The default value
+ */
+ public boolean getBoolean(
+ @NonNull Context context, PartnerConfig partnerConfig, boolean defaultValue) {
+ if (partnerConfig.getResourceType() != PartnerConfig.ResourceType.BOOLEAN) {
+ throw new IllegalArgumentException("Not a boolean resource");
+ }
+
+ if (mPartnerResourceCache.containsKey(partnerConfig)) {
+ return (boolean) mPartnerResourceCache.get(partnerConfig);
+ }
+
+ boolean result = defaultValue;
+ try {
+ String resourceName = partnerConfig.getResourceName();
+ ResourceEntry resourceEntry = getResourceEntryFromKey(resourceName);
+ if (resourceEntry == null) {
+ Log.w(TAG, "Resource not found: " + resourceName);
+ return defaultValue;
+ }
+ Resources resource = getResourcesByPackageName(context, resourceEntry.getPackageName());
+ result = resource.getBoolean(resourceEntry.getResourceId());
+ mPartnerResourceCache.put(partnerConfig, result);
+ } catch (PackageManager.NameNotFoundException exception) {
+ Log.e(TAG, exception.getMessage());
+ }
+ return result;
+ }
+
+ private void getPartnerConfigBundle(Context context) {
+ if (mResultBundle == null) {
+ try {
+ Uri contentUri =
+ new Uri.Builder()
+ .scheme(ContentResolver.SCHEME_CONTENT)
+ .authority(SUW_AUTHORITY)
+ .appendPath(SUW_GET_PARTNER_CONFIG_METHOD)
+ .build();
+ mResultBundle = context.getContentResolver().call(
+ contentUri,
+ SUW_GET_PARTNER_CONFIG_METHOD,
+ /* arg= */ null,
+ /* extras= */ null);
+ mPartnerResourceCache.clear();
+ } catch (IllegalArgumentException exception) {
+ Log.w(TAG, "Fail to get config from suw provider");
+ }
+ }
+ }
+
+ private Resources getResourcesByPackageName(Context context, String packageName)
+ throws PackageManager.NameNotFoundException {
+ PackageManager manager = context.getPackageManager();
+ return manager.getResourcesForApplication(packageName);
+ }
+
+ private ResourceEntry getResourceEntryFromKey(String resourceName) {
+ if (mResultBundle == null) {
+ return null;
+ }
+ return ResourceEntry.fromBundle(mResultBundle.getBundle(resourceName));
+ }
+
+ private PartnerConfigHelper(Context context) {
+ getPartnerConfigBundle(context);
+ }
+
+
+ @VisibleForTesting
+ static synchronized void resetForTesting() {
+ sInstance = null;
+ }
+}
diff --git a/com/android/car/setupwizardlib/partner/PartnerConfigKey.java b/com/android/car/setupwizardlib/partner/PartnerConfigKey.java
new file mode 100644
index 0000000..de4aa9e
--- /dev/null
+++ b/com/android/car/setupwizardlib/partner/PartnerConfigKey.java
@@ -0,0 +1,89 @@
+/*
+ * 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.car.setupwizardlib.partner;
+
+import androidx.annotation.StringDef;
+
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+
+@Retention(RetentionPolicy.SOURCE)
+@StringDef({
+ PartnerConfigKey.KEY_TOOLBAR_BG_COLOR,
+ PartnerConfigKey.KEY_TOOLBAR_BUTTON_ICON_BACK,
+ PartnerConfigKey.KEY_TOOLBAR_BUTTON_FONT_FAMILY,
+ PartnerConfigKey.KEY_TOOLBAR_BUTTON_PADDING_HORIZONTAL,
+ PartnerConfigKey.KEY_TOOLBAR_BUTTON_PADDING_VERTICAL,
+ PartnerConfigKey.KEY_TOOLBAR_BUTTON_RADIUS,
+ PartnerConfigKey.KEY_TOOLBAR_BUTTON_SPACING,
+ PartnerConfigKey.KEY_TOOLBAR_BUTTON_TEXT_SIZE,
+ PartnerConfigKey.KEY_TOOLBAR_PRIMARY_BUTTON_BG,
+ PartnerConfigKey.KEY_TOOLBAR_PRIMARY_BUTTON_BG_COLOR,
+ PartnerConfigKey.KEY_TOOLBAR_PRIMARY_BUTTON_TEXT_COLOR,
+ PartnerConfigKey.KEY_TOOLBAR_SECONDARY_BUTTON_BG,
+ PartnerConfigKey.KEY_TOOLBAR_SECONDARY_BUTTON_BG_COLOR,
+ PartnerConfigKey.KEY_TOOLBAR_SECONDARY_BUTTON_TEXT_COLOR,
+ PartnerConfigKey.KEY_TOOLBAR_DIVIDER_BG,
+ PartnerConfigKey.KEY_TOOLBAR_DIVIDER_LINE_WEIGHT,
+ PartnerConfigKey.KEY_LOADING_INDICATOR_COLOR,
+ PartnerConfigKey.KEY_LOADING_INDICATOR_LINE_WEIGHT,
+ PartnerConfigKey.KEY_LAYOUT_BG_COLOR
+})
+
+/** Resource names that can be customized by partner overlay APK. */
+public @interface PartnerConfigKey {
+
+ String KEY_TOOLBAR_BG_COLOR = "suw_compat_toolbar_bg_color";
+
+ String KEY_TOOLBAR_BUTTON_ICON_BACK = "suw_compat_toolbar_button_icon_back";
+
+ String KEY_TOOLBAR_BUTTON_FONT_FAMILY = "suw_compat_toolbar_button_font_family";
+
+ String KEY_TOOLBAR_BUTTON_TEXT_SIZE = "suw_compat_toolbar_button_text_size";
+
+ String KEY_TOOLBAR_BUTTON_PADDING_HORIZONTAL = "suw_compat_toolbar_button_padding_horizontal";
+
+ String KEY_TOOLBAR_BUTTON_PADDING_VERTICAL = "suw_compat_toolbar_button_padding_vertical";
+
+ String KEY_TOOLBAR_BUTTON_RADIUS = "suw_compat_toolbar_button_radius";
+
+ String KEY_TOOLBAR_BUTTON_SPACING = "suw_compat_toolbar_button_spacing";
+
+ String KEY_TOOLBAR_PRIMARY_BUTTON_BG = "suw_compat_toolbar_primary_button_bg";
+
+ String KEY_TOOLBAR_PRIMARY_BUTTON_BG_COLOR =
+ "suw_compat_toolbar_primary_button_bg_color";
+
+ String KEY_TOOLBAR_PRIMARY_BUTTON_TEXT_COLOR = "suw_compat_toolbar_primary_button_text_color";
+
+ String KEY_TOOLBAR_SECONDARY_BUTTON_BG = "suw_compat_toolbar_secondary_button_bg";
+
+ String KEY_TOOLBAR_SECONDARY_BUTTON_BG_COLOR = "suw_compat_toolbar_secondary_button_bg_color";
+
+ String KEY_TOOLBAR_SECONDARY_BUTTON_TEXT_COLOR =
+ "suw_compat_toolbar_secondary_button_text_color";
+
+ String KEY_TOOLBAR_DIVIDER_BG = "suw_compat_toolbar_divider_bg";
+
+ String KEY_TOOLBAR_DIVIDER_LINE_WEIGHT = "suw_compat_toolbar_divider_line_weight";
+
+ String KEY_LOADING_INDICATOR_COLOR = "suw_compat_loading_indicator_color";
+
+ String KEY_LOADING_INDICATOR_LINE_WEIGHT = "suw_compat_loading_indicator_line_weight";
+
+ String KEY_LAYOUT_BG_COLOR = "suw_design_layout_bg_color";
+}
diff --git a/com/android/car/setupwizardlib/partner/ResourceEntry.java b/com/android/car/setupwizardlib/partner/ResourceEntry.java
new file mode 100644
index 0000000..6d5d39b
--- /dev/null
+++ b/com/android/car/setupwizardlib/partner/ResourceEntry.java
@@ -0,0 +1,88 @@
+/*
+ * 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.car.setupwizardlib.partner;
+
+import android.content.pm.PackageManager;
+import android.os.Bundle;
+
+import androidx.annotation.Nullable;
+import androidx.annotation.VisibleForTesting;
+
+/**
+ * A potentially cross-package resource entry, which can then be retrieved using {@link
+ * PackageManager#getResourcesForApplication(String)}. This class can also be sent across to other
+ * packages on IPC via the Bundle representation.
+ */
+public final class ResourceEntry {
+ @VisibleForTesting static final String KEY_PACKAGE_NAME = "packageName";
+ @VisibleForTesting static final String KEY_RESOURCE_NAME = "resourceName";
+ @VisibleForTesting static final String KEY_RESOURCE_ID = "resourceId";
+
+ private final String mPackageName;
+ private final String mResourceName;
+ private final int mResourceId;
+
+ /**
+ * Creates a {@code ResourceEntry} object from a provided bundle.
+ *
+ * @param bundle the source bundle needs to have all the information for a {@code ResourceEntry}
+ */
+ public static ResourceEntry fromBundle(@Nullable Bundle bundle) {
+ if (bundle == null
+ || !bundle.containsKey(KEY_PACKAGE_NAME)
+ || !bundle.containsKey(KEY_RESOURCE_NAME)
+ || !bundle.containsKey(KEY_RESOURCE_ID)) {
+ return null;
+ }
+
+ String packageName = bundle.getString(KEY_PACKAGE_NAME);
+ String resourceName = bundle.getString(KEY_RESOURCE_NAME);
+ int resourceId = bundle.getInt(KEY_RESOURCE_ID);
+ return new ResourceEntry(packageName, resourceName, resourceId);
+ }
+
+ public ResourceEntry(String packageName, String resourceName, int resourceId) {
+ mPackageName = packageName;
+ mResourceName = resourceName;
+ mResourceId = resourceId;
+ }
+
+ public String getPackageName() {
+ return this.mPackageName;
+ }
+
+ public String getResourceName() {
+ return this.mResourceName;
+ }
+
+ public int getResourceId() {
+ return this.mResourceId;
+ }
+
+ /**
+ * Returns a bundle representation of this resource entry, which can then be sent over IPC.
+ *
+ * @see #fromBundle(Bundle)
+ */
+ public Bundle toBundle() {
+ Bundle result = new Bundle();
+ result.putString(KEY_PACKAGE_NAME, mPackageName);
+ result.putString(KEY_RESOURCE_NAME, mResourceName);
+ result.putInt(KEY_RESOURCE_ID, mResourceId);
+ return result;
+ }
+}